2

I'm trying to colour geom_bar according to the number of the sample ifelse(total > 90, "#FC2D00", "#008EFC"). In other words, if the total > 90, the bar should be red but total < 90, it should be blue.

type = c("aa", "bb", "cc")
total = c(110, 90, 89)

df = data.frame(type, total)

df %>% 
ggplot2::ggplot(aes(x = type, y = total)) +
  geom_bar(position = "dodge",
           stat = "identity")

I tried

df %>% 
ggplot2::ggplot(aes(x = type, y = total)) +
  geom_bar(position = "dodge",
           stat = "identity",
           fill = (ifelse(
           levels(studies$total > 90, "#FC2D00", "#008EFC"))))

and also

df %>% 
mutate(fill = ifelse(levels(total > 90, "#FC2D00", "#008EFC"))) %>% 
ggplot2::ggplot(aes(x = type, y = total)) +
  geom_bar(position = "dodge",
           stat = "identity",
           fill = fill)

but it still not working. I'm not sure what is the problem.

Sam
  • 309
  • 2
  • 10

3 Answers3

3

There is no need of ifelse() or mutate(). You can directly use the logical condition inside fill and then format using scale_fill_manual() for the colors and labels:

library(ggplot2)
library(dplyr)
#Data
type = c("aa", "bb", "cc")
total = c(110, 90, 89)
df = data.frame(type, total)
#Plot
df %>% 
  ggplot2::ggplot(aes(x = type, y = total,fill=total > 90)) +
  geom_bar(position = "dodge",
           stat = "identity")+
  scale_fill_manual(values = c("#FC2D00","#008EFC"),
                    labels=c('TRUE'='>90','FALSE'='<90'))+
  labs(fill='Total')

Output:

enter image description here

Duck
  • 39,058
  • 13
  • 42
  • 84
  • 1
    Oh, I wasn't aware that you can use `scale_fill_manual ` . That's awesome :) Thank you a lot Duck – Sam Nov 20 '20 at 20:16
2

Move your fill inside of the aes().

You should specify the colors in scale_fill_manual():

df %>% 
mutate(fill = ifelse(levels(total > 90, "#FC2D00", "#008EFC"))) %>% 
ggplot2::ggplot(aes(x = type, y = total, fill = fill)) +
  geom_bar(position = "dodge",
           stat = "identity") +
  scale_fill_manual(values= c("red","blue"))
Ben Norris
  • 5,639
  • 2
  • 6
  • 15
  • Thank you so much Ben. When I tried to copy your code, it gave me an error ```Problem with `mutate()` input `fill`` ```. Thank you anyway – Sam Nov 20 '20 at 20:09
  • but I wasn't aware of the use `scale_fill_manual()`. Thanks :) – Sam Nov 20 '20 at 20:10
2

In ggplot, we normally define color values in the scales, and legends are nicely autogenerated based on the data. So put in the data what you would want the legend labels to be, not the colors you want used.

df %>% 
mutate(emphasize = ifelse(total > 90, "> 90", "<= 90")) %>% 
ggplot(aes(x = type, y = total, fill = emphasize)) +
  geom_col(position = "dodge") +
  scale_fill_manual(values = c("> 90" = "#FC2D00", "<= 90" = "#008EFC"))

We don't need to use levels() - it's a bad choice here because total is not a factor (and it doesn't return one value per row, it may have a different order than the data...). I also switched geom_bar to geom_col - geom_col has stat = "identity" as the default.

Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294
  • Thank you Gregor for the detailed explanation. It is working now but I don't want to generate a legend. I tried `geom_col(aes(fill = ifelse(totalSamples > 4000, "#FC2D00", "#008EFC")))` and it also working. Thanks a lot – Sam Nov 20 '20 at 20:14