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

ggplot2中facet_wrap结合geom_density_ridges时第二个分面不显示问题

问题:ggplot2分面绘图仅显示b0分面,b1分面缺失

我正在处理一份CSV数据,读取后命名为datplot,其head()输出如下:

> head(datplot)
# A tibble: 6 × 3
  bta   electrode  value
  <chr> <chr>      <dbl>
1 b0    Fz         3.03 
2 b0    Cz         1.78 
3 b0    Pz        -1.05 
4 b0    Fz         3.78 
5 b0    Cz         2.82 
6 b0    Pz        -0.242

数据里的bta变量有"b0"和"b1"两个取值,对应不同分布的数值。我想用facet_wrap做双分面绘图,但结果只显示"b0"的分面,"b1"分面直接缺失了。

初始代码及问题表现

一开始用的ggplot代码是这样的:

time <- "225"
col <- c("#004d8d", "#cc2701", "#e5b400")

p1 <- datplot %>% ggplot(mapping = aes(x=value, y=factor(electrode, level = c('Fz','Cz','Pz')), group = electrode, color = electrode)) +
    scale_y_discrete() +
    geom_rect(data=data.frame(), inherit.aes = FALSE, mapping = aes(
      ymin = 0, ymax = Inf, xmin = -0.1 * min(stdev), xmax = 0.1 * max(stdev)), fill = "black", alpha = 0.1) +
    geom_density_ridges(data= subset(datplot, bta='b0'), scale = -0.5, alpha=0.2, show.legend = FALSE,
                        quantile_lines = TRUE, quantiles = c(0.025, 0.5, 0.975), 
                        vline_color = alpha("white", 0.3), aes(fill = electrode)) +
    #plotb1
    geom_density_ridges(data= subset(datplot, bta='b1'),scale = -0.5, alpha=0.5, show.legend = FALSE,
                         quantile_lines = TRUE, quantiles = c(0.025, 0.5, 0.975), 
                         vline_color = alpha("white", 0.6), aes(fill = electrode)) +
    facet_wrap(~bta) +
    scale_color_manual(values = col, breaks = c("Fz", "Cz", "Pz")) +   
    scale_fill_manual(values = col, breaks = c("Fz", "Cz", "Pz")) +
    labs(title=sprintf('%s ms.',time)) +
    ylab("Electrode") +
    xlab(TeX(r'(Signal (µV) Posteriors   $\beta_1\cdot x\; (x=1)$)')) +
    theme_light() +
    theme(axis.text = element_text(size = 14)) +
    theme(axis.title = element_text(size = 16)) +
    theme(plot.title = element_text(size = 20)) +
    coord_flip(xlim = c(-8, 8), ylim = c(0.4,3.05), expand = FALSE, clip = "on")
  p1

运行后只显示"b0"的分面,但单独绘制"b1"的数据是正常的,说明问题出在同时用两个geom_density_ridges加facet_wrap的逻辑上。

更新后的尝试

按照建议取消了手动子集数据,直接用完整的datplot绘图,代码如下:

p1 <- datplot %>% ggplot(mapping = aes(x=value, y=factor(electrode, level = c('Fz','Cz','Pz')), group = electrode, color = electrode)) +
    scale_y_discrete() +
    geom_rect(data=data.frame(), inherit.aes = FALSE, mapping = aes(
      ymin = 0, ymax = Inf, xmin = -0.1 * min(stdev), xmax = 0.1 * max(stdev)), fill = "black", alpha = 0.1) +
    geom_density_ridges(data= datplot, scale = -0.5, alpha=0.5, show.legend = FALSE,
                        quantile_lines = TRUE, quantiles = c(0.025, 0.5, 0.975), 
                        vline_color = alpha("white", 0.3), aes(fill = electrode)) +
    facet_wrap(~bta) +
    scale_color_manual(values = col, breaks = c("Fz", "Cz", "Pz")) +   
    scale_fill_manual(values = col, breaks = c("Fz", "Cz", "Pz")) +
    labs(title=sprintf('%s ms.',time)) +
    ylab("Electrode") +
    xlab(TeX(r'(Signal (µV) Posteriors   $\beta_1\cdot x\; (x=1)$)')) +
    theme_light() +
    theme(axis.text = element_text(size = 14)) +
    theme(axis.title = element_text(size = 16)) +
    theme(plot.title = element_text(size = 20)) +
    coord_flip(xlim = c(-8, 8), ylim = c(0.4,3.05), expand = FALSE, clip = "on")
  p1

结果还是只显示"b0"分面,求解决办法。


解决方案

问题根源有两个,逐个解决:

1. coord_flip的ylim限制导致b1分面被裁剪

你设置的ylim = c(0.4,3.05)是基于b0数据的范围,但b1数据的y轴(因为coord_flip,实际对应原x轴的翻转)可能超出这个范围,ggplot会直接隐藏没有有效绘图区域的分面。

解决: 要么移除coord_flip里的ylim参数,要么根据所有数据的实际范围调整,比如改成ylim = c(0.4, 3.5)(具体数值看b1数据的分布)。

2. 初始代码手动子集与分面逻辑冲突

初始代码里给两个geom_density_ridges分别指定b0和b1的子集,再加上facet_wrap(~bta),会导致每个分面里只有对应geom的数据,而ggplot分面是基于全局数据分组的,这种手动子集的操作会让b1分面里没有b0的geom数据,b0分面里没有b1的geom数据,再加上ylim限制,直接触发了分面隐藏。

正确做法: 不要手动子集数据,让facet_wrap自动按bta分组,如果需要区分b0和b1的透明度,把bta映射到alpha美学即可:

time <- "225"
col <- c("#004d8d", "#cc2701", "#e5b400")

p1 <- datplot %>% 
  ggplot(aes(x = value, 
             y = factor(electrode, level = c('Fz','Cz','Pz')), 
             group = interaction(electrode, bta),  # 确保每个电极+bta组合单独计算密度
             color = electrode,
             fill = electrode,
             alpha = bta)) +  # 将bta映射到透明度
  scale_y_discrete() +
  # 注意这里要明确stdev的来源,比如如果stdev是datplot的列,改成min(datplot$stdev)
  geom_rect(data = data.frame(), inherit.aes = FALSE, 
            aes(ymin = 0, ymax = Inf, 
                xmin = -0.1 * min(stdev), 
                xmax = 0.1 * max(stdev)), 
            fill = "black", alpha = 0.1) +
  geom_density_ridges(scale = -0.5, show.legend = FALSE,
                      quantile_lines = TRUE, quantiles = c(0.025, 0.5, 0.975), 
                      vline_color = alpha("white", 0.3)) +
  scale_alpha_manual(values = c("b0" = 0.2, "b1" = 0.5)) +  # 给不同bta设置透明度
  facet_wrap(~bta) +
  scale_color_manual(values = col, breaks = c("Fz", "Cz", "Pz")) +   
  scale_fill_manual(values = col, breaks = c("Fz", "Cz", "Pz")) +
  labs(title = sprintf('%s ms.', time)) +
  ylab("Electrode") +
  xlab(TeX(r'(Signal (µV) Posteriors   $\beta_1\cdot x\; (x=1)$)')) +
  theme_light() +
  theme(axis.text = element_text(size = 14),
        axis.title = element_text(size = 16),
        plot.title = element_text(size = 20)) +
  coord_flip(xlim = c(-8, 8), expand = FALSE, clip = "on")  # 移除ylim限制
p1

额外注意:stdev变量的来源

代码里geom_rect用到了stdev,如果这个变量不是全局变量或者不在datplot中,会报错,建议明确指定,比如min(datplot$stdev)(假设stdev是datplot的列)。


内容的提问来源于stack exchange,提问作者Unai Vicente

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 17:45:28