在每个测量时点添加垂直直方图的散点图实现方案
在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
相关产品推荐
相关产品推荐

