Tati
Tati

Reputation: 25

Assign specific color to definite value in bar plot using scale_fill_gradientn

I have a huge dataset containing minute-by minute recordings of some parameters in 20 patients. By visualizing the records of patient's monitoring (The IP parameter) I was trying to construct the colored barplots. So I used the scale_fill_gradient() function in r.

The problem is, that I'd like to assign to a definite value (for example IP = 20) a special color (let's say white). Is it possible to do that with scale_fill_gradient?

my database looks like that:

Patient min IP
1a      75  19
1a      76  21 
1a      77  20
1a      78  18.5
1a      79  17
1a      80  25
1a      81  29.3
1a      82  32.1
1a      83  30.9
2c      1   2
2c      2   5
2c      3   8 
2c      4   9
2c      5   12
2c      6   16   
2c      7   18
3v      72  38 
3v      73  35
3v      74  30.3
3v      75  28.7
3v      76  27
3v      77  25.2
3v      78  22
3v      79  19.1
3v      80  18 
3v      81  15

my code is

i<- ggplot(data, aes(patient, IP, fill=IP))
IPcol <- c("green", "greenyellow", "#fed976","#feb24c", "#fd8d3c", "#fc4e2a", "#e31a1c", "#bd0026", "#800026", "black")
i+geom_bar(stat = "identity")+ scale_fill_gradientn(colours = IPcol)+ coord_flip()+scale_y_time()

From this code I obtain the following image:

So the only thing i want to change - is that IP = 20 should be white

Upvotes: 1

Views: 723

Answers (1)

teunbrand
teunbrand

Reputation: 37933

So the easy option would be to recode the IPs that equal 20s to NAs and set a na.value in that scale:

data <- read.table(text = your_posted_data, header = T)


IPcol <- c("green", "greenyellow", "#fed976","#feb24c", "#fd8d3c", 
           "#fc4e2a", "#e31a1c", "#bd0026", "#800026", "black")

ggplot(data, aes(Patient, IP, fill= ifelse(IP != 20, IP, NA))) +
  geom_col() +
  scale_fill_gradientn(colours = IPcol, na.value = "white")+ 
  coord_flip()+
  scale_y_time()

enter image description here

If you want the difficult option, you'd have to write a palette function that works on values ranged 0-1 and set the rescaled 20 to white:

# Define an area to set to white
target <- (c(19.5, 20.5) - min(data$IP)) / (max(data$IP) - min(data$IP))

# Build a palette function
my_palette <- function(colours, values = NULL) {
  ramp <- scales::colour_ramp(colours)
  force(values)
  function(x) {
    # Decide what values to replace
    replace <- x > target[1] & x < target[2]
    if (length(x) == 0)
      return(character())
    if (!is.null(values)) {
      xs <- seq(0, 1, length.out = length(values))
      f <- stats::approxfun(values, xs)
      x <- f(x)
    }
    out <- ramp(x)
    # Actually replace values
    out[replace] <- "white"
    out
  }
}

And now you could plot it like thus:

ggplot(data, aes(Patient, IP, fill= IP)) +
  geom_col() +
  continuous_scale("fill", "my_pal", my_palette(IPcol), 
                   guide = guide_colourbar(nbin = 100))+ 
  coord_flip()+
  scale_y_time()

enter image description here

Upvotes: 3

Related Questions