0

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

5
  • You want to put the annotations in the title of each 9 subplots or put the annotations automatically to the bottom right of each 9 subplots? Commented Feb 12, 2025 at 9:46
  • Not bottom right, but at the bottom center Yacine, another idea is by using ggplotly, I've actually found another workaround using patchwork. More manual and hardcoded, but for now, it work. Commented Feb 12, 2025 at 10:01
  • 1
    You mean the x axis name. Then you can use a labeller in the facet_wrap. Please see the following topic stackoverflow.com/questions/69199276/… Commented Feb 12, 2025 at 10:10
  • many thanks, it works. Can you post it as an answer? Commented Feb 12, 2025 at 10:20
  • Sure please find a proposition Commented Feb 12, 2025 at 10:28

2 Answers 2

1

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")
answered Feb 12, 2025 at 10:28
Sign up to request clarification or add additional context in comments.

Comments

0

Another workaround using patchwork. But still waiting for facet_wrap approach.

library(ggplot2)
library(dplyr)
library(tidyr)
library(patchwork)
windowsFonts(Palatino = windowsFont("Palatino Linotype"))
plot_histograms_patchwork <- function(data, columns = where(is.numeric), rename_xlab = 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)
 } 
 plots <- list() # Store individual plots 
 for (col in selected_cols) {
 x_label <- if (!is.null(rename_xlab) && col %in% names(rename_xlab)) rename_xlab[[col]] else "Value" 
 # Conditional y-axis title only for "Ca"
 y_label <- if (col == "Ca") "Frequency" else NULL 
 p <- ggplot(data, aes(x = .data[[col]])) +
 geom_histogram(aes(y = after_stat(count)), bins = 30, fill = "#69b3a2", color = "#e9ecef", alpha = 0.9, na.rm = TRUE) +
 theme_bw() +
 theme(
 text = element_text(family = "Palatino"),
 axis.title.x = element_text(size = 12),
 axis.title.y = if (col == "Ca") element_text(size = 12) else element_blank(),
 plot.title = element_blank() # Remove titles
 ) +
 labs(x = x_label, y = y_label) 
 plots <- append(plots, list(p))
 } 
 # Arrange all plots using patchwork with 3 columns
 final_plot <- wrap_plots(plots) + plot_layout(ncol = 3) 
 return(final_plot)
}
plot_hist_all <- plot_histograms_patchwork(
 data = R_macro_rev, 
 columns = 7:15, 
 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

the resulting plot here:

enter image description here

answered Feb 12, 2025 at 10:04

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.