如何用dplyr的across获取分组后关联最大列值的其他列数据
解决dplyr分组汇总时across函数的问题
正确的across写法
你可以用以下两种方式实现目标,结果和逐列写法完全一致:
方式一:用across配合.data代词(明确分组上下文)
library(dplyr) data(iris) iris_summary <- iris %>% group_by(Species) %>% summarise( max_sep_length = max(.data$Sepal.Length), # 用.data明确引用分组内的Sepal.Length,避免上下文混淆 across(Sepal.Width:Petal.Width, ~ .x[which.max(.data$Sepal.Length)]), .groups = "drop" # 可选,取消分组状态,得到普通数据框 )
方式二:用slice_max先定位目标行(更直观)
这种写法先直接筛选出每组Sepal.Length最大的行,再整理列,逻辑更清晰,不容易出错:
iris_summary <- iris %>% group_by(Species) %>% slice_max(Sepal.Length, n = 1) %>% # 取每组Sepal.Length最大的1行 rename(max_sep_length = Sepal.Length) %>% # 重命名最大值列 select(Species, max_sep_length, Sepal.Width:Petal.Width) # 选择需要的列
你之前的across写法出问题的原因
你提到结果行数和原iris相同,核心问题是上下文引用歧义:在across的匿名函数中,Sepal.Length没有被正确识别为当前分组内的列,而是被当成了全局列,导致which.max(Sepal.Length)返回全局索引而非组内索引,最终summarise无法按组压缩结果。
用.data$Sepal.Length明确指定引用当前分组的列,就能解决这个问题;而slice_max的写法完全绕开了索引引用的坑,更适合新手或复杂场景。
验证结果
不管用哪种写法,最终的iris_summary都会是3行(对应3个物种),每行包含该物种的Sepal.Length最大值,以及对应的其他列数值,和你手动逐列编写的summarise结果完全一致。
内容的提问来源于stack exchange,提问作者emaoca
相关产品推荐
相关产品推荐

