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

如何镜像由半眼图、散点、箱线图组成的双组复合统计图

实现双组复合统计图的左右对称镜像布局

问题背景

已使用ggplot2绘制包含stat_halfeye、geom_jitter、geom_boxplot的双组(C、I组)复合统计图,当前效果满足需求,但需要将其修改为左右对称的镜像布局,让两组的密度半眼、箱线图和散点分别向两侧展开。

解决方案

核心是针对两组分别调整各图层的位置偏移方向,并设置stat_halfeye的显示方向,实现对称布局。以下是修改后的完整代码:

library(ggplot2)
library(wesanderson)
library(ggsignif)
library(ggdist)

# 数据准备
dat1 <- as.data.frame(c(175.070, 279.760, 310.120, 454.370, 356.190, 398.720, 394.790, 427.940, 450.090, 452.240, 344.630, 374.450, 401.810,
          366.250, 455.150, 455.150, 284.820, 325.640, 437.840, 455.150, 455.150, 454.900, 433.970, 346.830, 455.050, 455.150,
          448.740, 455.150, 455.000, 455.150, 243.920, 295.660, 282.430, 305.190, 368.580, 348.440, 437.100, 453.180, 454.100,
          44.464, 420.280, 455.150, 427.250, 101.490, 454.100, 454.810, 323.690, 454.410, 235.160, 294.870, 455.150, 330.460,
          289.610, 236.310, 454.810, 299.020,  29.289,  39.988, 348.340, 455.150, 439.540, 409.910, 440.310, 433.090, 455.150,
          198.890, 454.100, 346.370, 261.780, 280.760, 427.180, 455.150, 233.740, 334.040, 452.240, 411.890, 378.310, 354.410,
          347.670, 439.970))
colnames(dat1) = "value"

dat1$group <- rep(c('C','I'), c(40, nrow(dat1)-40)) # 简化分组赋值,替代原循环
dat1$group <- factor(dat1$group, levels = c('C','I'))

pltt <- rev(wes_palette(n=2, name="Darjeeling1"))

# 绘制镜像对称图
p_mirrored <- ggplot(dat1, aes(x=group, y=value, color=group, fill=group)) +
  scale_fill_manual(values=pltt, guide = "none") +
  scale_color_manual(values=pltt, guide = "none") +
  # 为两组分别设置半眼方向和位置偏移
  stat_halfeye(
    aes(side = ifelse(group == "C", "left", "right")), # C组左半眼,I组右半眼
    adjust = .33, width = .6, alpha=0.3,
    position = position_nudge(x = ifelse(dat1$group == "C", -0.3, 0.3))
  ) +
  # 散点分别向两侧偏移
  geom_jitter(
    shape=16, alpha=0.5,
    position = position_jitter(
      width = ifelse(dat1$group == "C", -0.1, 0.1),
      height = 0
    )
  ) +
  # 箱线图分别向两侧偏移
  geom_boxplot(
    width=0.05, outlier.shape = NA, fill=alpha(0.2),
    position = position_nudge(x = ifelse(dat1$group == "C", -0.2, 0.2))
  ) +
  # 保持显著性标记位置不变
  geom_signif(
    comparisons = list(c("C", "I")), tip_length = -0.01, y_position = -0.5,
    map_signif_level=TRUE, test="wilcox.test", color = "black"
  ) +
  ylim(0,460) +
  theme(
    legend.position = "none",
    axis.text=element_text(size=10),
    axis.title=element_text(size=12),
    plot.title = element_text(hjust = 0.5, size=14, face="bold")
  ) +
  theme_light() +
  ggtitle("Data distribution (Mirrored)")

print(p_mirrored)

关键修改说明

  • stat_halfeye:通过side映射指定C组显示左半密度眼、I组显示右半密度眼,同时用position_nudge让两组的半眼分别向左右偏移
  • geom_jitter:调整散点的抖动方向,让C组散点向左、I组向右,对应各自的半眼位置
  • geom_boxplot:同样用position_nudge让两组箱线图分别向左右偏移,保持与半眼的对齐
  • 简化了原数据分组的赋值代码,去掉冗余循环

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 16:05:26