Jadabu Jadabu - 3 months ago 41
R Question

R ggplot: Change Grouped Boxplot Median line

I have plotted grouped boxplots and now I would like to replace the standard black median line with a white line while keeping the borders in an other color. I'm following the instructions on the site Minimalist Boxplots because I really like their style.

They use the command

stat_summary(geom = "crossbar", width=0.65, fatten=0, color="white", fun.data = function(x){ return(c(y=median(x), ymin=median(x), ymax=median(x))) })
.
That command worked well with simple boxplots:
enter image description here

But now that I'm trying to use it on my grouped boxplots its not working anymore (white median line is missing):

enter image description here

Here is my the code for reproducing my data:

Data <- data.frame(
W = sample(1:100),
M = sample(1:100),
A = sample(1:100),
O = sample(1:100),
Type = sample(c("1", "2", "3", "4", "5")))


And my script:

Data_Boxplot <- melt(Data,id.vars='Type', measure.vars=c('W','M','A', 'O'))
Boxplots <- ggplot(Data_Boxplot, aes(Type, value, group=variable)) +
geom_boxplot(outlier.colour = NULL, aes(color=variable, fill=variable)) +
stat_summary(geom = "crossbar", width=0.65, fatten=0, color="white",
fun.data = function(x){c(y=median(x), ymin=median(x), ymax=median(x))})
Boxplots


What do I have to change? Thank you very much for your help.

Answer

You only mapped x and y for the geom_boxplot. Variables that are shared among geoms should be mapped for all. In this case, you also need to group by variable.

ggplot(Data.m, aes(Type, value, group=variable) +
geom_boxplot(outlier.colour = NULL, aes(color=variable, fill=variable)) + 
stat_summary(geom = "crossbar", width=0.65, fatten=0, color="white", 
             fun.data = function(x){c(y=median(x), ymin=median(x), ymax=median(x))})

I did not test, as you did not provide data.

Edit:

Ok, now that we have a good example with data we can see what's going on.

There is actually a two issues I had missed. Both are because geom_boxplot will automatically solve some problems for you because of the fill, that stat_summary doesn't. So we'll have to do them manually.

Firstly, we want to be grouping on both variable as well as Type, we can do this by using the interaction function.

Secondly, the boxplots are automatically dodged (i.e. moved apart within groups), while the horizontal lines aren't. We'll define our positioning using position_dodge, and apply it to both geoms. Applying it to both is the easiest way to make them exactly line up. We end up with:

p <- position_dodge(0.8)
ggplot(Data_Boxplot, aes(Type, value, group = interaction(variable, Type))) +
  geom_boxplot(aes(color = variable, fill = variable), outlier.colour = NULL, position = p) + 
  stat_summary(geom = "crossbar", width = 0.6, fatten=0, color="white", position = p,
               fun.data = function(x){c(y=median(x), ymin=median(x), ymax=median(x))}) +
  theme_minimal()

enter image description here

Comments