R语言dplyr分组聚合自定义函数的行名长度错误问题
问题分析与修复方案
错误原因
- 你在函数中直接使用传入的
x和y是全局向量(整个数据集的列),并非分组后的子集,导致计算的中位数、求和结果都是全局值,而非分组统计值。 binom.confint()返回的是包含多列的数据框,直接放入summarise()中会让每个分组对应一个数据框对象,而summarise()默认要求每个汇总结果长度为1,当分组样本量不同时,就会触发「row.names长度不符」的错误。
修复方案1:使用dplyr非标准求值(推荐)
修改函数接收数据框和列名,通过{{}}语法实现分组内的正确计算,同时拆分置信区间结果为单独列:
library(dplyr) library(binom) set.seed(123) df = data.frame( Group = c("A","A","A","A","A","B","B","B","B","B", "B"), Con = runif(11, min = 10, max = 60), YN = rbinom(11, 1, 0.5) ) cf = function(data, con_col, yn_col){ data %>% group_by(Group) %>% summarise( median = median({{con_col}}), n = n(), YN_n = sum({{yn_col}}), YN_perc = mean({{yn_col}})*100, # 用mean替代sum/n()更简洁 # 拆分置信区间为上下限列 CI_lower = binom.confint(sum({{yn_col}}), n(), conf.level = 0.95, method = "exact")$lower, CI_upper = binom.confint(sum({{yn_col}}), n(), conf.level = 0.95, method = "exact")$upper ) %>% ungroup() # 可选:取消分组,返回普通数据框 } # 调用函数 cf(df, Con, YN)
修复方案2:保持传入向量的方式
如果需要保留传入向量的调用逻辑,可通过cur_data()获取分组后的数据集,提取对应列进行计算:
library(dplyr) library(binom) set.seed(123) df = data.frame( Group = c("A","A","A","A","A","B","B","B","B","B", "B"), Con = runif(11, min = 10, max = 60), YN = rbinom(11, 1, 0.5) ) cf = function(x, y){ df %>% group_by(Group) %>% summarise( median = median(cur_data()[[deparse(substitute(x))]]), n = n(), YN_n = sum(cur_data()[[deparse(substitute(y))]]), YN_perc = sum(cur_data()[[deparse(substitute(y))]])/n()*100, CI_lower = binom.confint(sum(cur_data()[[deparse(substitute(y))]]), n(), conf.level = 0.95, method = "exact")$lower, CI_upper = binom.confint(sum(cur_data()[[deparse(substitute(y))]]), n(), conf.level = 0.95, method = "exact")$upper ) %>% ungroup() } # 调用函数 cf(df$Con, df$YN)
关键修复点
- 分组内列引用:确保所有计算基于分组后的子集列,而非全局向量。
- 拆分置信区间:将
binom.confint()返回的多列数据框拆分为单独的上下限列,保证summarise()的每个结果都是长度为1的值,避免嵌套数据框导致的行名错误。
内容的提问来源于stack exchange,提问作者Dylan Li
相关产品推荐
相关产品推荐

