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

在每个测量时点添加垂直直方图的散点图实现方案

在ggplot2中为散点图添加时点垂直分布直方图

嘿,这个需求我之前帮人解决过好几次,在ggplot2里实现起来有两种靠谱的路径——用现成工具包或者自定义编码,我给你一步步讲清楚:

一、用现成工具包:ggside(最便捷的方案)

ggside是专门为ggplot2设计的扩展包,能轻松在主图的侧边(上下左右)添加辅助绘图,正好满足你在每个测量时点旁添加垂直分布直方图的需求。

步骤1:准备数据(模拟你的场景)

先构造一份包含测量时点、数值以及置信区间的模拟数据,你可以替换成自己的真实数据:

library(tidyverse)

# 模拟测量数据:4个时点,每个时点50个观测值
set.seed(123)
df <- tibble(
  time = rep(1:4, each = 50),
  value = rnorm(200, mean = rep(c(1, 2, 3, 2.5), each = 50), sd = rep(c(0.5, 0.6, 0.7, 0.5), each = 50))
)

# 计算每个时点的置信区间和均值
ci_df <- df %>%
  group_by(time) %>%
  summarise(
    ymin = quantile(value, 0.025),  # 95%置信区间下限
    ymax = quantile(value, 0.975),  # 95%置信区间上限
    ymean = mean(value)             # 均值
  )

步骤2:绘制带垂直直方图的散点图

用ggside的geom_ysidehistogram在主图右侧添加每个时点的垂直直方图(也可以调整到左侧):

library(ggside)

ggplot(df, aes(x = factor(time), y = value)) +
  # 绘制散点(用jitter避免重叠)
  geom_jitter(alpha = 0.3, color = "steelblue") +
  # 添加置信区间线和均值点
  geom_errorbar(data = ci_df, aes(x = factor(time), ymin = ymin, ymax = ymax), width = 0.2) +
  geom_point(data = ci_df, aes(y = ymean), color = "red", size = 2) +
  # 每个时点右侧添加垂直直方图
  geom_ysidehistogram(aes(fill = factor(time)), bins = 6, position = "identity", alpha = 0.5) +
  # 调整侧边直方图的大小(0.2表示占主图宽度的20%)
  theme(ggside.panel.scale = 0.2) +
  labs(x = "测量时点", y = "测量值") +
  guides(fill = "none")  # 去掉直方图的图例,避免重复

这个方案的好处是几乎不用手动处理数据,ggside会自动帮你对齐每个时点的分布绘图。

二、自定义编码(无需额外工具包)

如果你不想安装新包,也可以用基础ggplot2函数手动实现,核心思路是先计算每个时点的直方图数据,再用矩形图层叠加到主图上。

步骤1:计算直方图数据

先把每个时点的数值分箱,计算每个箱子的计数,再标准化计数以适配主图的坐标轴范围:

hist_df <- df %>%
  group_by(time) %>%
  mutate(
    # 给数值分箱(这里设6个箱子,你可以根据需求调整)
    bin = cut(value, breaks = seq(min(df$value), max(df$value), length.out = 7), include.lowest = TRUE),
    # 计算每个箱子的中点
    bin_mid = (as.numeric(sub("\\((.*),.*\\]", "\\1", bin)) + as.numeric(sub(".*,(.*)\\]", "\\1", bin)))/2
  ) %>%
  # 统计每个时点、每个箱子的观测数
  count(time, bin, bin_mid) %>%
  ungroup() %>%
  mutate(
    # 把直方图放在每个时点的右侧(避免和散点重叠)
    x_pos = time + 0.2,
    # 标准化计数,让直方图高度适配主图的y轴范围
    count_norm = n / max(n) * (max(df$value) - min(df$value)) * 0.1
  )

步骤2:叠加直方图到主图

用geom_rect绘制垂直的直方图矩形:

ggplot() +
  # 先绘制散点和置信区间
  geom_jitter(data = df, aes(x = time, y = value), alpha = 0.3, color = "steelblue") +
  geom_errorbar(data = ci_df, aes(x = time, ymin = ymin, ymax = ymax), width = 0.2) +
  geom_point(data = ci_df, aes(x = time, y = ymean), color = "red", size = 2) +
  # 绘制自定义垂直直方图
  geom_rect(data = hist_df, 
            aes(xmin = x_pos - count_norm/2, xmax = x_pos + count_norm/2, 
                ymin = bin_mid - (diff(unique(bin_mid))[1]/2), 
                ymax = bin_mid + (diff(unique(bin_mid))[1]/2),
                fill = factor(time)),
            alpha = 0.5) +
  labs(x = "测量时点", y = "测量值") +
  guides(fill = "none") +
  # 调整x轴范围,确保直方图完整显示
  scale_x_continuous(breaks = 1:4, limits = c(0.8, 4.4))

这个方案需要手动调整位置和大小,但好处是不依赖第三方包,适合环境受限的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:37:34