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

如何在一张图中可视化两组差异极大的分布数据?

解决极端偏态数据与正态分布数据的并列可视化问题

这个场景我太熟悉了——当一组数据有大量极端集中的数值(比如你的组a里95个值都是1),常规的箱线图和小提琴图确实会掉链子:箱线图直接挤在顶部,啥细节都看不到;小提琴图则会因为1处的密度太高,呈现出异常的形态。下面给你几个实用的可视化方案,结合你的示例数据来实现:

方案1:抖动散点+自定义统计标注(最直观)

既然组a的大部分值集中在1,我们可以保留抖动散点展示原始数据,同时给两组添加关键统计量(比如中位数、四分位距),再标注组a中等于1的样本数,这样既能看到原始数据,又能清晰对比两组差异。

library(tidyverse)

# 预处理数据,计算各组统计量
d_summary <- d %>%
  group_by(var) %>%
  summarize(
    median_val = median(val),
    q1_val = quantile(val, 0.25),
    q3_val = quantile(val, 0.75),
    count_1 = sum(val == 1)
  )

d %>%
  ggplot(aes(x = var, y = val)) +
  geom_jitter(width = 0.2, alpha = 0.6, size = 1.5) +  # 抖动散点展示原始数据分布
  # 添加中位数线和四分位距竖线
  geom_segment(data = d_summary, aes(x = as.numeric(var)-0.15, xend = as.numeric(var)+0.15, y = median_val, yend = median_val), color = "red", size = 1) +
  geom_segment(data = d_summary, aes(x = as.numeric(var), xend = as.numeric(var), y = q1_val, yend = q3_val), color = "red", size = 1) +
  # 标注组a中1的数量
  geom_text(data = filter(d_summary, var == "a"), aes(x = var, y = 0.9, label = paste0("n=1: ", count_1)), color = "darkblue", size = 4) +
  labs(title = "抖动散点+统计标注对比", x = "组别", y = "响应值") +
  theme_minimal()

这个方案的优势是保留了原始数据的全貌,统计线快速展示集中趋势,极端值的数量也一目了然,不会让人误解分布。

方案2:分面密度曲线+散点补充

如果想更清晰地展示两组的分布形态,用分面的密度曲线是个好选择——既能看到组b的正态分布,又能在组a的分面里用散点补充极端值的数量信息。

d %>%
  ggplot(aes(x = val)) +
  geom_density(fill = "lightblue", alpha = 0.6) +
  # 给组a的散点单独放在底部,避免遮挡密度曲线
  geom_jitter(data = filter(d, var == "a"), aes(y = 0.5), width = 0, height = 0.2, alpha = 0.5) +
  facet_wrap(~var, ncol = 1) +
  labs(title = "分面密度曲线对比", x = "响应值", y = "密度") +
  theme_minimal()

分面的方式避免了两组分布差异过大导致的视觉干扰,密度曲线清晰展示组b的形态,组a的散点则直观呈现了大量1的存在。

方案3:优化小提琴图,突出极端值

如果你还是想保留小提琴图的形式,可以通过调整参数解决宽度异常的问题,再配合散点和文本标注补充关键信息:

d %>%
  ggplot(aes(x = var, y = val)) +
  geom_violin(scale = "count", width = 0.8) +  # scale="count"让宽度对应样本数,避免极端密度导致的异常宽度
  geom_jitter(width = 0.1, alpha = 0.7, size = 1) +
  # 直接标注组a的极端值情况
  geom_text(aes(x = "a", y = 0.8, label = "95个值为1"), color = "darkred", size = 4) +
  labs(title = "优化后的小提琴图+抖动散点", x = "组别", y = "响应值") +
  theme_minimal()

scale="count"参数让小提琴宽度对应每组样本数,而非密度,避免了组a在1处的极高密度导致的异常形态,散点和文本则补充了原始数据的细节。

方案4:横向点图展示分布

点图可以把每个样本点整齐排列,直观看到组a的点几乎都堆叠在1,组b的点呈正态分布的形态:

d %>%
  ggplot(aes(x = val, y = var)) +
  geom_dotplot(binaxis = "x", stackdir = "center", dotsize = 0.8) +
  labs(title = "横向点图对比分布", x = "响应值", y = "组别") +
  theme_minimal()

横向布局让两组的分布对比非常直观,不需要额外标注就能看出两组的核心差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 17:14:09