Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ggplot change the x axis label colors dynamically

Tags:

r

ggplot2

Below is the test code:

library(tidyverse)

df<- data.frame(PCP = c("BOB","FRED","ED","Other"),
                closed = c(42,64,45,1812), 
                total= c(53,81,58,3188), 
                percentage = c(.7924,.7901,.7758,.5683),
                row= c(1, 2, 3,4),
                color =c("0099FF","#CCCCCC","#CCCCCC","#660033"),
                color_fill = c("99","0","0","98"
                ))

col  <- c(
  "99" = "#0099FF",
  "98" = "#660033", 
  "0" = "#CCCCCC" 
)

df %>%  
  arrange(desc(percentage)) %>% 
  mutate(PCP = PCP,
         closed = closed,
         total = total,
         percentage = percentage,
         row = row,
         color = color,
         color_fill = color_fill) -> df1

ggplot(df1,aes(x=PCP, y = percentage,fill=color_fill, color = color)) +
  geom_col() +
  coord_flip() +
  labs(x ="PCP Name",
       y = "Percentage of Gap Closures",
       title =  "TOP 10 PCPs")+
   scale_fill_manual(values = col)+
  scale_color_manual(values = col) +
  scale_y_continuous(labels = percent_format(), limits=c(0,1))+
  theme(legend.position = "none",
        panel.grid = element_blank(),
        panel.background = element_blank(),
        text = element_text(size=15),
        plot.caption = element_text(hjust = 0, face= "italic"),
        axis.text.y = element_text(colour = col ))

My goal is to match x axis labels with the bar colors.

I have attempted solutions from, Matching axis.text labels to colors contained in data frame variable in ggplot

However when attempting the factor levels portion, I get an error because my actual data contains other values that utilize the same #CCCCCC color code.

Below is the output of the attached code.

Results

Is there something I am doing wrong?

like image 895
CCP Avatar asked Feb 20 '26 07:02

CCP


1 Answers

I'm not entirely sure what the issue is here (I mean I understand that you provide the colors in the wrong order; in the theme you would have to use col[as.integer(df$color)] to mimic the order of the factor but I have no clue why) but I have a workaround that works well.

One less known function in ggplot2 is ggplot_build. Using this you can, as the name suggests, build the plot, which means you can extract the values you want from it. Based on this I wrote a little function which can do what you want.

axis_text_color <- function(plot, col = "fill") {
  c <- ggplot_build(plot)$data[[1]]
  plot +
    theme(axis.text.y = element_text(colour = c[[col]]))
}

The way you use it is by first saving the plot in an object:

library(tidyverse)
plot <- ggplot(df, aes(
    x = PCP,
    y = percentage,
    fill = color_fill,
    color = color
  )) +
  geom_col() +
  coord_flip() +
  labs(x = "PCP Name",
       y = "Percentage of Gap Closures",
       title =  "TOP 10 PCPs") +
  scale_fill_manual(values = col) +
  scale_color_manual(values = col) +
  scale_y_continuous(labels = scales::percent_format(), limits = c(0, 1)) +
  theme(
    legend.position = "none",
    panel.grid = element_blank(),
    panel.background = element_blank(),
    text = element_text(size = 15),
    plot.caption = element_text(hjust = 0, face = "italic")
  )

And then calling the function on that plot:

axis_text_color(plot)

Created on 2020-01-20 by the reprex package (v0.3.0)

like image 179
JBGruber Avatar answered Feb 22 '26 20:02

JBGruber