Search code examples
rggplot2tidyverseboxplotfacet-wrap

Ordering facet levels using value of another column


this is part of my data. I had a long format of 3 factor levels and 20 variables.

str(Data_Penelitian2) 
tibble [540 × 5] (S3: tbl_df/tbl/data.frame)
 $ Zonation        : chr [1:540] "PRG" "PRG" "PRG" "PRG"  "PRG" ... "GWM" "GWM" .. "GWH" "GWH"..
 $ Variables       : chr [1:540] "WT (%)" "WT (%)" "Wt (%)" "pH" "pH" "pH" "Corg" "Corg" "Corg" ...
 $ Value           : num [1:540] 352 723 1084 4.8 5.5 4.2 47.8 48.2 41.6...
 $ ID              : num [1:540] 1 1 1 2 2 2 3 3 3 ... 20

I faceted the boxplot+violinplot of Value and Zonation factor based on Variables. But the facets are alphabetically ordered. So I assign the ID for each variable to order the facet. Basically, I want to facet using "Variables" but ordered them using "ID". I was experimenting with facet_wrap, avoiding manual ordering (like this one:Fixing the order of facets in ggplot or this: How do I get ggplot to order facets correctly?) since I had 20 unique variable names.

calc_stat <- function(x) {
  coef <- 1.5
  n <- sum(!is.na(x))
  # calculate quantiles
  stats <- quantile(x, probs = c(0.1, 0.25, 0.5, 0.75, 0.9))
  names(stats) <- c("ymin", "lower", "middle", "upper", "ymax")
  return(stats)
}

windowsFonts(Times=windowsFont("Times New Roman"))

p <- ggplot(Data_Penelitian2, aes(x=Zonation, y=Value)) + 
    geom_violin(trim=FALSE) + 
    stat_summary(fun.data = calc_stat, geom="boxplot",alpha = 0.2, width = 0.2 ) +  
    geom_jitter(width = 0.3, alpha = 0.5, aes(color = Zonation))+
    facet_wrap(factor(Data_Penelitian2$Variables~., levels = unique(Data_Penelitian2$ID)),scales="free", ncol=4) +
  # scale_fill_viridis(discrete = TRUE,  option = "turbo", alpha=0.7)+
   theme_minimal()+ theme(text=element_text(family="Times")) +
    theme(legend.position = "none")

The facet_wrap didn't work. Any suggestion?


Solution

  • I found the trick by creating labeller function and then passing it to ggplot2. Thanks to @naught101 answer https://stackoverflow.com/a/12104207/17292783.

    calc_stat <- function(x) {
      coef <- 1.5
      n <- sum(!is.na(x))
      # calculate quantiles
      stats <- quantile(x, probs = c(0.1, 0.25, 0.5, 0.75, 0.9))
      names(stats) <- c("ymin", "lower", "middle", "upper", "ymax")
      return(stats)
    }
    
    varNames = list(
    '1'="WT (%)",
    '2'="pH",
    '3'="C-org (%)",
    '4'="AC (%)",
    '5'="CNR"
    )
    
    var_labeller <- function(variable,value){
      return(varNames[value])
    }
    p <- ggplot(Data_Penelitian2, aes(x=Zonation, y=Value)) + 
        geom_violin(trim=FALSE) + 
        stat_summary(fun.data = calc_stat, geom="boxplot",alpha = 0.2, width = 0.2 ) +  
        geom_jitter(width = 0.3, alpha = 0.5, aes(color = Zonation))+
        facet_wrap(ID~., labeller=var_labeller, scales="free", ncol=4,) +
      # scale_fill_viridis(discrete = TRUE,  option = "turbo", alpha=0.7)+
       theme_minimal()+ theme(text=element_text(family="Times")) +
        theme(legend.position = "none")