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

如何使用lattice绘制带误差棒和散点的柱状图?

Lattice实现带误差棒和抖动散点的分组柱状图

完全可以实现你想要的效果,你的原始代码存在三个核心问题:

  • 直接用原始数据绘制柱状图,导致每个原始值都生成了柱子,而非分组均值
  • panel.xyplot的参数传递错误,无法获取原始数据的坐标
  • 误差棒基于原始数据计算,而非统计量的标准误

实现步骤

  1. 预处理数据:先计算每个dose+supp组合的均值和标准误(误差棒用),同时把dose转为因子方便x轴定位
  2. 设置分组偏移:让同一剂量下的两个分组柱子错开,避免重叠
  3. 自定义Panel函数:依次绘制柱状图、误差棒、抖动散点

完整代码

library(lattice)
library(dplyr)

# 转换dose为因子,方便分组定位
ToothGrowth$dose_f <- factor(ToothGrowth$dose, levels = c(0.5, 1, 2))

# 计算分组统计量:均值+标准误
summary_df <- ToothGrowth %>%
  group_by(dose_f, supp) %>%
  summarise(
    mean_len = mean(len),
    se_len = sd(len)/sqrt(n()),
    .groups = "drop"
  )

# 定义分组柱子的偏移宽度
dodge_width <- 0.3

# 绘制图形
barchart(mean_len ~ dose_f, 
         data = summary_df,
         groups = supp,
         ylab = "牙齿长度",
         xlab = "剂量 (mg)",
         main = "不同剂量和补充剂下的牙齿生长情况",
         col = c("#00AFBB", "#E7B800"),
         panel = function(x, y, groups, subscripts, ...) {
           # 计算每个分组柱子的x偏移位置
           x_pos <- as.numeric(x) + ifelse(groups[subscripts] == "OJ", -dodge_width/2, dodge_width/2)
           
           # 绘制分组柱状图
           panel.barchart(x_pos, y, ...)
           
           # 绘制误差棒(均值±标准误)
           se_vals <- summary_df$se_len[subscripts]
           # 误差棒竖线
           panel.segments(x0 = x_pos, y0 = y - se_vals,
                          x1 = x_pos, y1 = y + se_vals,
                          col = "black")
           # 误差棒两端的短横线
           panel.segments(x0 = x_pos - dodge_width/4, y0 = y - se_vals,
                          x1 = x_pos + dodge_width/4, y1 = y - se_vals,
                          col = "black")
           panel.segments(x0 = x_pos - dodge_width/4, y0 = y + se_vals,
                          x1 = x_pos + dodge_width/4, y1 = y + se_vals,
                          col = "black")
           
           # 绘制原始数据的抖动散点
           # 计算原始数据的x位置(加上分组偏移)
           raw_x <- as.numeric(ToothGrowth$dose_f) + ifelse(ToothGrowth$supp == "OJ", -dodge_width/2, dodge_width/2)
           # 抖动x轴(幅度不超过分组偏移)
           raw_x_jitter <- jitter(raw_x, amount = dodge_width/3)
           panel.xyplot(raw_x_jitter, ToothGrowth$len, 
                        col = ifelse(ToothGrowth$supp == "OJ", "#00AFBB", "#E7B800"),
                        pch = 16, cex = 0.8, alpha = 0.6)
         },
         # 添加图例
         key = list(space = "right",
                    text = list(c("橙汁", "维生素C")),
                    rectangles = list(col = c("#00AFBB", "#E7B800"), fill = c("#00AFBB", "#E7B800")))
)

替代方案(不用dplyr)

如果不想用dplyr,可以用base R计算统计量:

# 用base R计算分组统计量
summary_df <- aggregate(len ~ dose + supp, data = ToothGrowth, 
                        function(x) c(mean = mean(x), se = sd(x)/sqrt(length(x))))
summary_df <- do.call(data.frame, summary_df)
colnames(summary_df) <- c("dose", "supp", "mean_len", "se_len")
summary_df$dose_f <- factor(summary_df$dose, levels = c(0.5, 1, 2))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 13:10:28