使用Rmisc包的summarySE汇总调研数据绘制ggplot误差棒遇问题
解决Rmisc::summarySE分组生成NaN及忽略问题列的问题
问题原因
你遇到的NaN是因为每个question+opinion组合只有1条观测数据,summarySE计算标准差(sd)、标准误(se)等统计量时,单个数值无法算出变异程度,因此返回NaN。而只按opinion分组时,自然会忽略question列,不符合你按问题拆分的需求。
解决方案
你的数据集里number是每个观点的回答计数,不需要用summarySE(它适用于有重复样本的场景),可以根据需求选择以下两种方式:
1. 绘制回答比例的误差棒
如果需要展示各观点占该问题总回答数的比例,并添加95%置信区间的误差棒:
library(dplyr) library(ggplot2) # 计算每个问题的总回答数、比例及比例的标准误 my_data <- my_data %>% group_by(question) %>% mutate(total = sum(number), prop = number / total, # 用二项分布近似计算比例的标准误 se_prop = sqrt(prop * (1 - prop) / total)) %>% ungroup() # 绘图 ggplot(my_data, aes(x = opinion, y = prop, fill = opinion)) + geom_col(position = position_dodge()) + geom_errorbar(aes(ymin = prop - 1.96*se_prop, ymax = prop + 1.96*se_prop), width = 0.2, position = position_dodge(0.9)) + facet_wrap(~question, scales = "free_y") + labs(y = "回答比例", x = "观点") + theme_bw()
2. 绘制回答计数的bootstrap置信区间
如果需要直接展示回答数量的置信区间,可以用bootstrap重抽样生成:
library(dplyr) library(ggplot2) library(boot) library(purrr) # 定义bootstrap重抽样函数 boot_count <- function(data, i) { # 从该问题的所有回答中重抽样 resampled_opinions <- sample(rep(data$opinion, data$number), replace = TRUE) count_table <- table(resampled_opinions) return(as.data.frame(count_table)) } # 对每个问题单独计算bootstrap置信区间 boot_results <- my_data %>% group_split(question) %>% map(function(df) { boot_obj <- boot(df, boot_count, R = 1000) # 提取每个观点的95%百分位数置信区间 ci_df <- map_dfr(unique(df$opinion), function(op) { ci <- boot.ci(boot_obj, type = "perc", index = which(unique(df$opinion) == op)) data.frame(opinion = op, lower = ci$percent[4], upper = ci$percent[5]) }) df %>% left_join(ci_df, by = "opinion") }) boot_data <- bind_rows(boot_results) # 绘图 ggplot(boot_data, aes(x = opinion, y = number, fill = opinion)) + geom_col(position = position_dodge()) + geom_errorbar(aes(ymin = lower, ymax = upper), width = 0.2, position = position_dodge(0.9)) + facet_wrap(~question, scales = "free_y") + labs(y = "回答数量", x = "观点") + theme_bw()
内容的提问来源于stack exchange,提问作者Nervous Optic Head
相关产品推荐
相关产品推荐

