ggplot2对数尺度下stat_summary绘图错误及直连线解决方案
对数尺度下正确绘制几何均值与直线型个体连线的解决方案
问题背景
拥有配对的"before"和"post"数据集,需在对数尺度下完成两类可视化需求:
- 基于原始数据正确计算并展示几何均值和几何标准差
- 个体ID的前后配对连线在对数尺度上呈现直线效果
现有两种常规方法存在缺陷:
- 使用
scale_y_log10():stat_summary()会先对数据做对数转换再计算,导致几何均值、标准差结果失真(如"post"组实际几何均值大于1000,但图中显示偏小;"before"组标准差在对数尺度上不对称) - 使用
coord_trans(y="log10"):虽能基于原始数据正确统计,但个体连线在对数尺度下不是直线,可视化效果差
解决方案
核心思路:先对原始数值做对数转换,基于转换后的线性数据绘图,再将y轴刻度标签映射回原始数据的对数尺度格式。这样既保证统计量计算正确,又能让个体连线呈现直线效果。
具体步骤与代码实现
library(ggplot2) library(dplyr) library(ggpubr) # 原始数据 data_raw = data.frame( ID = c(1,2,3,4,5,6,7,8,9,10,11,12), Group = c(rep("before",12), rep("post",12)), Values = c(15,60,70,300,40,35,100,1520,102,172,141,103, 1200,130,118,158,199,5804,1258,4582,4052,3332,2202,5129) ) # 数据预处理:新增对数转换列(用log10方便后续y轴标签映射) data_processed <- data_raw %>% arrange(ID, Group) %>% mutate(log_Values = log10(Values)) # 绘制目标图形 ggplot(data_processed, aes(x = Group, y = log_Values)) + # 个体配对连线(对数转换后为直线,对应原始尺度的对数直线) geom_line(aes(group = ID), colour = "gray", linetype = 2, position = position_jitter(width = 0.25, seed = 1)) + geom_point(size = 1.2, position = position_jitter(width = 0.25, seed = 1)) + # 绘制几何均值(log转换后的均值对应原始数据的几何均值) stat_summary(fun = mean, geom = "crossbar", colour = "black") + # 绘制几何标准差上限:10^(均值+标准差) stat_summary(fun = function(x) mean(x) + sd(x), geom = "crossbar", width = 0.4, size = 0.1, colour = "black") + # 绘制几何标准差下限:10^(均值-标准差) stat_summary(fun = function(x) mean(x) - sd(x), geom = "crossbar", width = 0.4, size = 0.1, colour = "black") + # 将y轴刻度转换为原始数据的对数尺度格式(显示10^x) scale_y_continuous( breaks = seq(1, 4, by = 1), # 对应log10(10)=1到log10(10000)=4 labels = trans_format("log10", math_format(10^.x)) ) + theme(text = element_text(size = 20))
关键说明
- 统计量计算正确性:
- 几何均值 = (10^{\text{mean}(\log_{10}(\text{Values}))}),对应代码中
mean(log_Values)取指数后的值,直接用mean(log_Values)绘图后,y轴标签会自动映射为原始数值的几何均值 - 几何标准差上下限 = (10^{\text{mean}(\log_{10}(\text{Values})) \pm \text{sd}(\log_{10}(\text{Values}))}),代码中直接对
log_Values计算均值±标准差即可
- 几何均值 = (10^{\text{mean}(\log_{10}(\text{Values}))}),对应代码中
- 个体连线直线效果:
对Values做对数转换后,配对数据的前后变化在线性轴上是直线,对应到原始数据的对数尺度显示时,自然呈现对数尺度下的直线效果 - y轴标签可读性:
通过trans_format将对数刻度转换为10^x的数学格式,保持对数尺度的直观性
内容的提问来源于stack exchange,提问作者Jordan Lau
相关产品推荐
相关产品推荐

