Home > database >  Issue with scale_color_identity() in ggplot -- labels reordered automatically by colour name
Issue with scale_color_identity() in ggplot -- labels reordered automatically by colour name

Time:07-19

I want to control my font colour using explicitly named colours in the label_col column. However, it seems that the colours "black" and "white" end up being ordered alphabetically by the colour name, instead of following the same fill and position specified in ggplot(aes()) and geom_col().

Here is my minimal example with black and white:

list_order <- c("a", "b", "c", "d", "e", "f")

test <- data.frame(indicator = rep(list_order, 2),
                   mean = c(1.1, 0.3, 6.3, 4, 7, 2.1, 1.2, 0.7, 6.9, 3.3, 5.4, 1.8),
                   group = c(rep("Group A", 6), rep("Group B", 6)))

test %>% 
  mutate(indicator = factor(indicator, levels = list_order),
         label = round(mean, 1),
         label_col = ifelse(indicator %in% c("a", "d", "e", "f"), "black", "white")) %>% 
  ggplot(aes(x = group, y = mean, fill = indicator))  
  geom_col(width = 0.7, position = "stack")  
  geom_text(aes(label = label, color = label_col), size = 3, position = position_stack(vjust = 0.5))  
  scale_color_identity()  
  scale_fill_viridis(discrete = T, option = "plasma")

Which gives me this: enter image description here

If I change the colours in label_col to both "white", or both "black", I get them in the correct places like here:

enter image description here

enter image description here

Is there something I am not understanding about how ggplot positions labels and text? I know how to work around this by using scale_color_manual(), but would also like to understand why scale_color_identity() is not working here, and the solution for it.

CodePudding user response:

The problem is with no explicit grouping of variables. I modified your code by adding group = group to aesthetics specification and it seem to work.

I am not entirely sure where specifically lies the problem, but I assume that the problem is with some reordering done under the hood -- you can see in your example that all white labels are brought to the bottom and all black are brought to the top.

test %>% 
  mutate(indicator = factor(indicator, levels = list_order),
         label = round(mean, 1),
         label_col = ifelse(indicator %in% c("a", "d", "e", "f"), "black", "white")) %>% 
  ggplot(aes(x = group, y = mean, fill = indicator, group = group))  
  geom_col(width = 0.7, position = "stack")  
  geom_text(aes(label = label, color = label_col), size = 3, position = position_stack(vjust = 0.5))  
  scale_color_identity()  
  scale_fill_viridis(discrete = T, option = "plasma")
  • Related