如何用ggplot创建带单X轴的双Y轴分面网格并复刻SigmaPlot图形
Alright, let's figure out how to replicate that SigmaPlot 4x4 grid in ggplot—including those empty first two slots in the first column for your legend! Here's a practical, step-by-step solution tailored to your data setup:
First, let's build the core plot with your mappings: Station on X, value on Y, shape for quarter, color for species, and faceted by constituent in a 4-column grid. I'll add some theme tweaks to align closer to SigmaPlot's clean style:
library(ggplot2) library(patchwork) # For flexible grid layout (way easier than gridExtra here) library(dplyr) library(purrr) # Replace `your_data` with your actual dataset name base_plot <- ggplot(your_data, aes(x = Station, y = value)) + geom_point(aes(shape = quarter, color = species), size = 3) + # Make points easy to distinguish facet_wrap(~constituent, ncol = 4) + # 4 columns to get the 4x4 grid # Customize scales for better visibility scale_shape_manual(values = c(1, 2, 5, 6)) # Adjust based on how many levels `quarter` has scale_color_brewer(palette = "Set2") # Use a distinct color palette for species # Theme adjustments to match SigmaPlot's vibe theme_bw() + theme( panel.grid.major = element_line(color = "gray90"), panel.grid.minor = element_blank(), strip.background = element_rect(fill = "gray85"), strip.text = element_text(size = 10, face = "bold"), axis.text = element_text(size = 9), axis.title = element_text(size = 11, face = "bold") )
We need to pull the legend out of the base plot so we can place it in those empty first-column slots:
# Extract the legend (using cowplot's helper function—install with `install.packages("cowplot")` if needed) library(cowplot) plot_legend <- get_legend(base_plot) # Remove the legend from the original plot plot_no_legend <- base_plot + theme(legend.position = "none")
The key part is creating a 4x4 layout where the first two slots in column 1 are merged to hold the legend, and the rest hold your faceted plots. We'll use patchwork's custom layout syntax for this:
# Split your faceted plot into a list of individual panels plot_panels <- plot_no_legend$facet$plot_env$data %>% distinct(constituent) %>% pull(constituent) %>% map(~ plot_no_legend %+% filter(your_data, constituent == .x)) # Define the 4x4 layout: "A" is the merged legend slot, letters B-O are your panels custom_layout <- " AABC AADE FGHI JKLM " # Combine everything into the final grid final_plot <- (plot_legend + plot_panels[[1]] + plot_panels[[2]] + plot_panels[[3]] + plot_panels[[4]] + plot_panels[[5]] + plot_panels[[6]] + plot_panels[[7]] + plot_panels[[8]] + plot_panels[[9]] + plot_panels[[10]] + plot_panels[[11]] + plot_panels[[12]] + plot_panels[[13]] + plot_panels[[14]]) + plot_layout(design = custom_layout) + plot_annotation(theme = theme(plot.margin = margin(10, 10, 10, 10))) # View the final plot final_plot
Quick Adjustments for Edge Cases:
- If you have exactly 16
constituentlevels, replace two of theplot_panelsentries with empty panels (useggplot() + theme_void()for blank slots) in positions 1 and 5 (first column, rows 1 and 2), then place the legend in one of those slots. - Tweak the
scale_shape_manualandscale_color_brewervalues to match the exact shapes/colors from your SigmaPlot figure.
内容的提问来源于stack exchange,提问作者Anonymous coward

