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

Y轴为log10刻度的柱状图stat_summary均值显示错误求助

问题解决:微生物计数log10刻度柱状图的均值修正

问题描述

要绘制微生物计数的柱状图(误差棒为标准差)并叠加散点图,数据包含Steel/Copper两种材料、T0/T+1h/T+2h三个时间点。因部分原始数据为0,已替换为1以便在log轴上显示,但绘制后Copper组全部、Steel组部分的柱状图均值显示异常,推测与Y轴log10转换有关。

问题根源

当前代码中stat_summary(fun=mean)计算的是原始数据的算术均值,但微生物计数这类右偏分布的数据,在log10刻度轴上应该使用几何均值才合理:

  • 算术均值会被大量小值(替换后的1)拉低,在log轴上显示位置远低于真实数据的集中趋势
  • 基于原始数据计算的标准差,在log轴上同样不适用,应该基于log转换后的数据计算标准差再转换回原始尺度

修正方案

步骤1:提前计算每组的几何统计量

按Material分组,计算几何均值、log转换后的标准差,再推导误差棒的上下限:

  • 几何均值:exp(mean(log(CFU)))
  • 误差棒上限:exp(mean(log(CFU)) + sd(log(CFU)))
  • 误差棒下限:exp(mean(log(CFU)) - sd(log(CFU))),同时确保下限不小于1(匹配替换后的最小数值)

步骤2:重构ggplot代码

用提前计算好的统计量绘制柱状图和误差棒,散点图保留原始数据的抖动显示。

完整修正代码

library(ggplot2)
library(dplyr)
library(scales)

# 原始数据
Material<-c("Copper T0", "Copper T0","Copper T0","Copper T0","Copper T0","Copper T0","Copper T0","Copper T0","Copper T0",
             "Copper T+1h","Copper T+1h","Copper T+1h","Copper T+1h","Copper T+1h","Copper T+1h","Copper T+1h","Copper T+1h","Copper T+1h",
             "Copper T+2h","Copper T+2h","Copper T+2h","Copper T+2h","Copper T+2h","Copper T+2h","Copper T+2h","Copper T+2h","Copper T+2h",
             "Steel T0", "Steel T0","Steel T0","Steel T0","Steel T0","Steel T0","Steel T0","Steel T0","Steel T0",
             "Steel T+1h", "Steel T+1h","Steel T+1h","Steel T+1h","Steel T+1h","Steel T+1h","Steel T+1h","Steel T+1h","Steel T+1h",
             "Steel T+2h","Steel T+2h","Steel T+2h","Steel T+2h","Steel T+2h","Steel T+2h","Steel T+2h","Steel T+2h","Steel T+2h")
CFU<-c(1,1,1,1,1,1,1,1,12500,
       1,1,1,1,1,1,1,1,12500,
       1,1,1,1,1,1,1,1,12500,
       262500,137500,437500,112500,37500,62500,250000,225000,50000,
       50000,112500,37500,62500,75000,1,12500,87500,1,
       1,1,25000,12500,1,1,137500,150000,112500)
data3<-data.frame(Material,CFU)

# 计算每组的几何统计量
summary_stats <- data3 %>%
  group_by(Material) %>%
  summarise(
    geom_mean = exp(mean(log(CFU))),
    log_sd = sd(log(CFU)),
    ymin = pmax(exp(mean(log(CFU)) - log_sd), 1),  # 下限不小于1
    ymax = exp(mean(log(CFU)) + log_sd)
  ) %>%
  mutate(Material = factor(Material, levels = c("Steel T0", "Steel T+1h", "Steel T+2h", "Copper T0", "Copper T+1h", "Copper T+2h"))) %>%
  arrange(Material)

# 绘图
ggplot() +
  # 柱状图:用提前计算的几何均值
  geom_col(data = summary_stats, aes(x = Material, y = geom_mean, fill = Material), 
           color = "black", show.legend = FALSE) +
  # 误差棒:用几何标准差的上下限
  geom_errorbar(data = summary_stats, aes(x = Material, ymin = ymin, ymax = ymax), 
                width = 0.2) +
  # 散点图:原始数据抖动显示
  geom_point(data = data3, aes(x = factor(Material, levels = levels(summary_stats$Material)), y = CFU), 
             position = position_jitter(width = 0.2), color = "black", show.legend = FALSE) +
  # Y轴log10刻度设置
  scale_y_continuous(trans = 'log10', expand = c(0, 0.0001),
                     breaks = trans_breaks("log10", function(x) 10^x, n = 8),
                     labels = trans_format("log10", math_format(10^.x))) +
  # 主题设置
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
        panel.background = element_blank(), axis.line = element_line(colour = "darkgrey"),
        axis.title.x = element_blank(), axis.ticks.x = element_blank()) +
  # 填充色设置
  scale_fill_manual(values = c("sienna3", "sienna3", "sienna3", 
                               "lightslategrey", "lightslategrey", "lightslategrey")) +
  # Y轴标签
  ylab(bquote(CFU.cm^-2))

关键说明

  • 用dplyr分组计算统计量,确保每组的均值和误差棒符合log刻度下的分布特征
  • 误差棒下限设置为不小于1,避免出现小于替换值的不合理数值
  • Y轴标签修正为CFU(原代码误写为PFU),如果确实是PFU可改回

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 19:57:09