Home > front end >  ggplot2 align fun.data in stat_summary
ggplot2 align fun.data in stat_summary

Time:12-10

Let

df <- data.frame("Method" = rep(c("Method1", "Method2", "Method3", "Method4", "Method5"), each = 3, times = 1),
                 "Type" = rep(c("A", "B", "C"), 5),
                 "Value" = c(runif(5, 0, 1), runif(5, 0.2, 1.2), runif(5, 0.4, 1.4)))

I created a boxplot

get_box_stats <- function(y, upper_limit = max(df$Value) * 1.42) {
  return(data.frame(
    y = upper_limit,
    label = paste(
      length(y), "\n",
      round(quantile(y, 0.25), 2), "\n",
      round(median(y), 2), "\n",
      round(quantile(y, 0.75), 2), "\n"
    )
  ))
}

ggplot(df, aes(factor(Type), Value))  
  labs(fill = "Method")  
  stat_summary(size = 4.6, fun.data = get_box_stats, geom = "text", position = position_dodge(.9),
               hjust = 0.5, vjust = 1, aes(group = factor(Type))) 
  geom_boxplot(coef = 0, aes(fill = factor(Type)))   theme_classic()  
  theme(legend.position = "top", axis.text.x = element_text(size = 15),
        axis.text.y = element_text(size = 15),  
        axis.title.x = element_text(size = 15),
        axis.title.y = element_text(size = 15),
        legend.title=element_text(size = 15), 
        legend.text=element_text(size = 15))  
  geom_dotplot(aes(fill = factor(Type)), dotsize = 0.8, binaxis = 'y', stackdir = 'center',
               position = position_dodge(0.75)) 
  xlab("Method")

This results in a boxplot enter image description here

QUESTION: As you can see, for stats are not perfectly centered, i.e for Method B -- values 1 and 5. Is there a way to fix this?

CodePudding user response:

The problem lies in your use of paste in your summary function. By default, paste adds a space character between each element you want to paste together. Your summary string therefore has a space before and after every line break, but not before the first line. Since a space takes up some room, the aligment is off. Instead of adding in all those newline characters, specify that you want to use just a newline character as a separator using the sep argument:

get_box_stats <- function(y, upper_limit = max(df$Value) * 1.42) {
  return(data.frame(
    y = upper_limit,
    label = paste(
      length(y), 
      round(quantile(y, 0.25), 2), 
      round(median(y), 2), 
      round(quantile(y, 0.75), 2), sep = "\n"
    )
  ))
}

ggplot(df, aes(factor(Type), Value))  
  labs(fill = "Method")  
  stat_summary(size = 4.6, fun.data = get_box_stats, geom = "text",
               hjust = 0.5, vjust = 1, aes(group = factor(Type))) 
  geom_boxplot(coef = 0, aes(fill = factor(Type)))   theme_classic()  
  theme(legend.position = "top", axis.text.x = element_text(size = 15),
        axis.text.y = element_text(size = 15),  
        axis.title.x = element_text(size = 15),
        axis.title.y = element_text(size = 15),
        legend.title=element_text(size = 15), 
        legend.text=element_text(size = 15))  
  geom_dotplot(aes(fill = factor(Type)), dotsize = 0.8, binaxis = 'y',
               stackdir = 'center',
               position = position_dodge(0.75)) 
  xlab("Method")

enter image description here

  • Related