使用dplyr的across函数后,列名为何显示为pos$cured和prop$cured?
使用dplyr的across汇总时出现嵌套列名的原因及解决方法
你的代码示例
n <- 500 durations <- c(3, 5, 6, 8, 10) prop_fever_resolve <- c(0.5, 0.6, 0.7, 0.8, 0.9) prop_urine_sterile <- c(0.8, 0.85, 0.88, 0.9, 0.93) prop_additional_abx <- c(0.2, 0.17, 0.14, 0.1, 0.05) duration_props <- data.frame(duration = durations, prop_fever_resolve = prop_fever_resolve, prop_urine_sterile = prop_urine_sterile, prop_additional_abx = prop_additional_abx) set.seed(6942069) data <- duration_props %>% slice_sample(n = n, replace = TRUE) %>% rowwise() %>% mutate(fever_resolve = sample(c(FALSE, TRUE), 1, prob = c(1 - prop_fever_resolve, prop_fever_resolve)), urine_sterile = sample(c(FALSE, TRUE), 1, prob = c(1 - prop_urine_sterile, prop_urine_sterile)), additional_abx = sample(c(FALSE, TRUE), 1, prob = c(1 - prop_additional_abx, prop_additional_abx)), cured = fever_resolve & urine_sterile & !additional_abx) data %>% group_by(across("duration")) %>% summarize(n = n(), pos = across("cured", sum), prop = pos / n)
问题原因
across()是为批量处理多列设计的,它的返回值是一个嵌套的tibble(数据框),而非单个数值向量。当你在summarize()里写pos = across("cured", sum)时,相当于把cured列的求和结果打包成了一个迷你数据框,后续计算prop = pos / n时,本质是用这个嵌套数据框除以标量n,结果依然是嵌套结构,最终就会出现pos$cured、prop$cured这种表示嵌套列的名称。
另外补充:group_by(across("duration"))其实没必要用across(),直接写group_by(duration)更简洁,因为你只分组单个列。
解决办法
方法1:直接不用across(推荐,因为只处理单个列)
既然只对cured一列求和,直接调用sum(cured)即可,完全不需要across():
data %>% group_by(duration) %>% summarize(n = n(), pos = sum(cured), prop = pos / n)
方法2:如果要保留across(比如后续扩展多列)
可以用.names参数指定输出列名,或者提取嵌套中的向量:
- 用
.names批量命名:
data %>% group_by(duration) %>% summarize(n = n(), across("cured", sum, .names = "pos"), across("pos", ~ .x / n, .names = "prop"))
- 用
pull()提取嵌套向量:
data %>% group_by(duration) %>% summarize(n = n(), pos = pull(across("cured", sum)), prop = pos / n)
内容的提问来源于stack exchange,提问作者jackahall
相关产品推荐
相关产品推荐

