Search code examples
rggplot2facet-wrapx-axis

Current development in how to adjust individual x axis title using ggplot facet_wrap


I have some difficulties in developing correct labeller function for adding x axis title within a facet_wrap plots. This is the code:

    str(R_macro_rev)
        tibble [857 × 15] (S3: tbl_df/tbl/data.frame)
         $ OP_Age : chr [1:857] "<6" "<6" "<6" "<6" ...
         $ Thick  : chr [1:857] "<3" "<3" "<3" "<3" ...
         $ Season : chr [1:857] "Rainy" "Rainy" "Rainy" "Rainy" ...
         $ D_Canal: num [1:857] 10 10 10 10 10 10 10 10 10 10 ...
         $ D_OPT  : num [1:857] 1 1 1 2 2 2 3 3 3 4 ...
         $ Depth  : num [1:857] 20 40 70 20 40 70 20 40 70 20 ...
         $ N      : num [1:857] NA 15946 11816 13862 14955 ...
         $ P      : num [1:857] 2082 1361 1931 1303 1641 ...
         $ K      : num [1:857] 787 237 624 252 259 ...
         $ Ca     : num [1:857] 1506 654 567 649 499 ...
         $ Mg     : num [1:857] 282.3 32.7 566.7 89.7 99.8 ...
         $ NP     : num [1:857] 10.35 11.71 6.12 10.64 9.11 ...
         $ NK     : num [1:857] 27.4 67.3 18.9 54.9 57.8 ...
         $ PK     : num [1:857] 2.65 5.75 3.09 5.17 6.35 ...
         $ CaMg   : num [1:857] 5.33 NA 1 7.24 5


# look after the histogram
# firstly, cast the wrapper function to automatize the process

windowsFonts(Palatino=windowsFont("Palatino Linotype"))

plot_histograms <- function(data, columns = where(is.numeric), rename_vars = NULL) {  
  # Select columns properly
  selected_cols <- if (is.numeric(columns)) {
    names(data)[columns]  # Select by index
  } else {
    names(select(data, {{ columns }}))  # Select by condition (e.g., numeric)
  }  
  # Convert data to long format
  data_long <- data %>%
    pivot_longer(cols = all_of(selected_cols), names_to = "Variable", values_to = "Value")  
  # Rename variables if rename_vars is provided
  if (!is.null(rename_vars)) {
    data_long$Variable <- factor(data_long$Variable, 
                                 levels = selected_cols, 
                                 labels = ifelse(selected_cols %in% names(rename_vars), 
                                                 rename_vars[selected_cols], 
                                                 selected_cols))
  } else {
    data_long$Variable <- factor(data_long$Variable, levels = selected_cols)
  }
  # Plot histograms
  ggplot(data_long, aes(x = Value)) +
    geom_histogram(aes(y = after_stat(count)), bins = 30, fill = "#69b3a2", color = "#e9ecef", alpha = 0.9, na.rm = TRUE) +
    facet_wrap(~Variable, scales = "free") +
    theme_bw()+
    theme(text = element_text(family = "Palatino"))+
    labs(x = "Value", y = "Frequency")
}


plot_hist_all <- plot_histograms(data = R_macro_rev, 
                columns = 7:15, 
                rename_vars = c("N" = "Total N", "P" = "Total P", "K" = "Total K", "Ca" = "Total Ca", 
                      "Mg" = "Total Mg","NP" = "N:P", "NK" = "N:K", "PK" = "P:K", "CaMg" = "Ca:Mg"))

And the resulting plot:

histogram1

Any new development in ggplot facet_wrap to add separate x axis title for each facet plot? so I can pass some labeller arguments in the wrapper function like this:

plot_hist_all <- plot_histograms(data = R_macro_rev, 
                columns = 7:15, 
                rename_vars = c("N" = "Total N", "P" = "Total P", "K" = "Total K", "Ca" = "Total Ca", 
                      "Mg" = "Total Mg","NP" = "N:P", "NK" = "N:K", "PK" = "P:K", "CaMg" = "Ca:Mg"),  #  rename the stoichiometric vars
                rename_xlab = c("N" = "Total N (mg/kg)", "P" = "Total P (mg/kg)", "K" = "Total K (mg/kg)", "Ca" = "Total Ca (cmol(+)/kg)", 
                      "Mg" = "Total Mg (cmol(+)/kg)", "NP" = "N:P", "NK" = "N:K", "PK" = "P:K", "CaMg" = "Ca:Mg"))
plot_hist_all

I've used annotate approach but, it must be set manually, and cannot automatically fit at the correct x axis location, like this:

hist2


Solution

  • Please find a proposition to manually update the x axis names.

    I do not have access to the dataframe so I cannot output the graph.

    ##### Defining x axis names for facet_wrap
    my_strip_labels <- 
      as_labeller(c(
        "Total N (mg/kg)", "Total P (mg/kg)", "Total K (mg/kg)", 
        "Total Ca (cmol(+)/kg)", "Total Mg (cmol(+)/kg)", 
        "N:P", "N:K", "P:K", "Ca:Mg"))
    
    
    ##### Part of the ggplot to update
     ggplot(data_long, aes(x = Value)) +
        geom_histogram(aes(y = after_stat(count)), bins = 30, fill = "#69b3a2", color = "#e9ecef", alpha = 0.9, na.rm = TRUE) +
        facet_wrap(~Variable, 
                   scales = "free", 
                   labeller = my_strip_labels,  # This part has been updated
                   strip.position = "bottom") + # This part has been updated
        theme_bw() + 
        theme(text = element_text(family = "Palatino"),
              strip.placement = "outside",          # This part has been updated
              strip.background = element_blank()) + # This part has been updated
      labs(x = "Value", y = "Frequency")