You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用ggplot基于3D数组绘制带观测值折线的多面板箱线图

Solution: Multi-panel Boxplots with Observed Value Lines in ggplot2

Absolutely! This is totally doable with ggplot2, but first we need to reshape your matrix and 3D array into a tidy (long-form) data structure—since ggplot works best with this format. Let's walk through the step-by-step solution:

Step 1: Load Required Packages

We'll use the tidyverse suite (includes ggplot2, dplyr, and tidyr for data manipulation):

library(tidyverse)

Step 2: Reshape Observed Data

Convert your observed matrix into a data frame with explicit columns for month, region, and observed value:

# Convert observed matrix to tidy data frame
observed_df <- as.data.frame(observed) %>%
  # Add month column (1 to 6, since you have 6 rows)
  mutate(month = 1:n()) %>%
  # Reshape to long format
  pivot_longer(
    cols = -month,  # Keep month as identifier
    names_to = "region",  # Rename columns to "region"
    values_to = "observed"  # Values become the observed metric
  ) %>%
  # Clean up region names (e.g., "V1" → "Region 1")
  mutate(region = str_replace(region, "V", "Region "))

Step 3: Reshape Simulated Data

Your simul 3D array needs to be converted to a data frame with columns for month, region, simulation run, and simulated value:

# Convert 3D simul array to tidy data frame
simul_df <- as.data.frame.table(simul) %>%
  # Rename columns for clarity
  rename(
    month = Var1,
    region = Var2,
    sim_run = Var3,
    sim_value = Freq
  ) %>%
  # Convert month to integer (it comes as a factor from as.data.frame.table)
  mutate(
    month = as.integer(as.character(month)),
    region = str_replace(region, "V", "Region ")  # Match region names to observed data
  )

Step 4: Create the Multi-panel Plot

Now we'll build the ggplot: each panel is a region, with boxplots for simulated values per month, plus a red line/points for observed values.

ggplot(simul_df, aes(x = factor(month), y = sim_value)) +
  # Add boxplots for simulated values (one per month per region)
  geom_boxplot(fill = "lightblue", alpha = 0.7, outlier.size = 0.8) +
  # Add line for observed values (use observed_df explicitly)
  geom_line(
    data = observed_df,
    aes(x = factor(month), y = observed, group = 1),
    color = "darkred",
    linewidth = 1.2
  ) +
  # Add points for observed values to make them stand out
  geom_point(
    data = observed_df,
    aes(x = factor(month), y = observed),
    color = "darkred",
    size = 2
  ) +
  # Create a panel for each region
  facet_wrap(~region, ncol = 3) +  # Use ncol=1 for vertical panels, ncol=3 for horizontal
  # Customize labels and theme
  labs(
    x = "Month",
    y = "Value",
    title = "Simulated Value Distributions vs Observed Values"
  ) +
  theme_bw() +
  theme(
    plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
    axis.title = element_text(size = 12),
    strip.text = element_text(size = 11, face = "bold")
  )

Key Details:

  • factor(month): Converts month to a discrete variable, ensuring one boxplot per month (instead of treating month as continuous).
  • data = observed_df: We explicitly specify the observed data for the line/points since it comes from a different data frame than the boxplots.
  • group = 1: Ensures ggplot draws a single line connecting all observed points for a region (without this, it won't know how to group the points).
  • Facet Layout: Adjust ncol in facet_wrap() to change how panels are arranged (3 columns for side-by-side, 1 column for stacked).

内容的提问来源于stack exchange,提问作者thomas leon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:45:24