R语言按分组取列最大值对应行的另一列值生成新列
问题说明
处理包含多分组的数据框时,需要实现以下逻辑:
- 按分组字段拆分数据
- 定位每个分组内指定列(示例中为
val1)取最大值的行 - 提取该行另一列(示例中为
val2)的取值,为分组内所有行填充生成新列(示例中为val3)
示例输入
item group val1 val2 <chr> <dbl> <dbl> <dbl> 1 a 1 1 1 2 b 1 2 3 3 c 1 3 2 4 d 2 1 0 5 e 2 2 1
预期输出
分组1中val1最大值为3,对应行val2取值为2,分组1所有行val3填充2;分组2中val1最大值为2,对应行val2取值为1,分组2所有行val3填充1,结果如下:
item group val1 val2 val3 <chr> <dbl> <dbl> <dbl> <dbl> 1 a 1 1 1 2 2 b 1 2 3 2 3 c 1 3 2 2 4 d 2 1 0 1 5 e 2 2 1 1
原有代码问题
原代码运行后val3全为NA,存在两个明确问题:
- 构造测试数据时把
val1、val2存为了字符型,直接做最大值计算会按文本规则排序,结果不符合数值计算预期 max(val1)["val2"]逻辑错误:max(val1)仅返回分组内val1的最大数值(单个值),不存在val2列属性,用列名索引自然返回NA
原错误代码片段:
data %>% group_by(group) %>% mutate(val3 = max(val1)["val2"]) -> data
解决方案
使用tidyverse框架下的分组操作,通过which.max()匹配最大值所在行位置,直接提取对应位置的val2即可,可运行代码如下:
library(tidyverse) # 构造测试数据(注意数值列存为numeric类型,不要存为字符型) item <- c("a", "b", "c", "d", "e") group <- c("1", "1", "1", "2", "2") val1 <- c(1, 2, 3, 1, 2) val2 <- c(1, 3, 2, 0, 1) data <- tibble( item = item, group = group, val1 = val1, val2 = val2 ) # 分组计算生成val3 data %>% group_by(group) %>% mutate(val3 = val2[which.max(val1)]) %>% ungroup() -> data
逻辑说明
group_by(group)按分组字段拆分数据which.max(val1)返回当前分组内val1取最大值的行的位置索引val2[位置索引]直接提取对应行的val2取值,mutate会自动将这个单值填充到分组内的所有行- 最后加
ungroup()解除分组状态,避免后续操作受分组规则影响
特殊场景适配
如果单个分组内存在多行val1等于最大值的并列情况,which.max()会默认返回第一个匹配到的最大值行位置。如果需要对并列最大值做聚合处理,可以调整逻辑,例如并列时取对应val2的均值:
data %>% group_by(group) %>% mutate(val3 = mean(val2[val1 == max(val1)])) %>% ungroup()
运行上述基础代码后得到的结果和预期输出完全一致。
内容的提问来源于stack exchange,提问作者alternativegeometry
相关产品推荐
相关产品推荐

