11

I would like to change the color of the median line in geom_boxplot(). I have looked and can't find a way to do it. I have posted the R code here that I am using but I just really need a reference to how to change the color.

ggplot(invitro2) +
  geom_boxplot(aes(x = reorder(CANCER_TYPE,tmedian), y = GeoMedian_IC50)) +
  xlab("") +  
  geom_point(aes(x = reorder(CANCER_TYPE,tmedian), y = GeoMedian_IC50)) +
  theme_bw() +
  scale_y_log10(breaks = trans_breaks("log10", function(x) 10^x),
                labels = trans_format("log10", math_format(10^.x))) +
  annotation_logticks(sides="l")   +  
  theme(axis.text.x=element_text(angle=45,size=10,hjust=1),
        panel.grid.major = element_blank()) 
Jaap
  • 81,064
  • 34
  • 182
  • 193
user2945234
  • 418
  • 6
  • 12

1 Answers1

19

You can use the details of the plot, to derive the coordinates of where the median line is, and then add colour to it using geom_segment.

library(ggplot2)

p <- ggplot(mtcars, aes(factor(am), mpg)) + geom_boxplot()

dat <- ggplot_build(p)$data[[1]]

p + geom_segment(data=dat, aes(x=xmin, xend=xmax, 
                               y=middle, yend=middle), colour="red", size=2)

Also had to increase the size of the line so that it covers the original black median line

enter image description here

cdcarrion
  • 574
  • 6
  • 22
user20650
  • 24,654
  • 5
  • 56
  • 91
  • how to perform it in a faceted geom_boxplot()? – Wilson Souza Jan 06 '23 at 11:50
  • @WilsonSouza ; append the faceting variable to `dat`. A quick example; `p <- ggplot(mtcars, aes(factor(am), mpg)) + geom_boxplot() + facet_wrap(~cyl) ; dat <- ggplot_build(p)$data[[1]] dat <- cbind(dat, cyl=sort(unique(mtcars$cyl))[dat$PANEL])` If your facetting variable is a factor you should use `levels` instead of the `sort(unique())`. But this answer is ~6.5 years old, and there may now be better ways to do this. – user20650 Jan 06 '23 at 14:11
  • What about if you have multiple boxplots at each `x` value in a faceted `geom_boxplot` ? – Jared Mar 07 '23 at 18:40
  • Can you give an example please @Jared, similar to example in my comment above, – user20650 Mar 07 '23 at 19:07
  • A fake dataframe in the same format as the data I am working with - `df_fish <- data.frame( Fish_Group = factor(rep(c( "Bluegill", "Minnow", "Pike" ), each = 27)), Label = factor(c( rep(c("BG1", "BG2", "BG3"), each = 3, times = 3), rep(c("MN1", "MN2", "MN3"), each = 3, times = 3), rep(c("P1", "P2", "P3"), each = 3, times = 3) )), Measure_Type = factor(rep( c("Longest Side", "Hypotenuse", "Arc Length"), each = 1 )), Length = c( runif(27, 8, 12), runif(27, 8, 12), runif(27, 25, 35) ) )` – Jared Mar 07 '23 at 20:02
  • Fake plot to try and replace the median with a different color line - `df_fish %>% group_by(Fish_Group, Label, Measure_Type) %>% ggplot(data = ., aes(x = Label, y = Length)) + geom_boxplot(aes(fill = Measure_Type), size = 0.25, color = "black") + facet_grid(~ Fish_Group, scales = "free_x")` – Jared Mar 07 '23 at 20:03
  • Now I have each level of `Measure_Type` at each `Label` with the plot faceted by `Fish_Group`. – Jared Mar 07 '23 at 20:05
  • 1
    @Jared; a quick look seems that the approach in the earlier comment still works. The only difference is you are using some grouping. I'd thus split it into; `plot_dat = df_fish %>% group_by(Fish_Group, Label, Measure_Type)` . Then your plot code saved into an object: `p <- plot_dat %>% ggplot(data = . ....and so on)`. Match in panel data: `dat <- ggplot_build(p)$data [[1]] ; dat <- cbind(dat, Fish_Group=levels(plot_dat$Fish_Group)[dat$PANEL])` . The add segments: `p + geom_segment(data=dat, aes(x=xmin, xend=xmax, y=middle, yend=middle), colour="red", linewidth=2)` – user20650 Mar 07 '23 at 20:44
  • 1
    Yup, it does work. I was making a mistake with my actual dataframe, but got it working on my real data now. Thanks!! – Jared Mar 07 '23 at 21:18