R语言aggregate函数使用问题:按KCL_ID提取最小DAYS对应BMI
解决R语言中按KCL_ID分组提取最小DAYS并匹配对应BMI的问题
嗨,我懂你碰到的麻烦了——直接用aggregate()函数的话,很容易踩个坑:如果直接对DAYS和BMI同时用min聚合,得到的BMI会是该分组里的最小值,而不是对应最小DAYS那一行的BMI,这完全不是你想要的结果对吧?下面给你几个贴合需求的解决办法:
方法1:用aggregate配合合并(纯base R,贴合你的初始需求)
先通过aggregate提取每个KCL_ID对应的最小DAYS,再把这个结果和原数据合并,筛选出匹配的行:
# 假设你的原始数据框是df df <- data.frame( KCL_ID = c(21L, 21L, 21L, 22L, 22L, 22L), DAYS = c(1449, 1814, 582, 582, 947, 183), BMI = c(26.4, 28.7, 32, 25.3, 25.2, 25.7) ) # 第一步:提取每个KCL_ID的最小DAYS min_days_group <- aggregate(DAYS ~ KCL_ID, data = df, FUN = min) # 第二步:合并回原数据,筛选对应行 result <- merge(df, min_days_group, by = c("KCL_ID", "DAYS")) # 若同一KCL_ID存在多个相同的最小DAYS,可去重 result <- unique(result)
运行后你会得到每个KCL_ID对应最小DAYS的完整行数据,包括正确匹配的BMI。
方法2:用by函数直接筛选行(base R更简洁写法)
用by按KCL_ID分组,每组里直接找到DAYS最小的那一行,再合并结果:
result <- do.call(rbind, by(df, df$KCL_ID, function(group) { # 找到当前组中DAYS最小的行 group[which.min(group$DAYS), ] }))
这个方法一步到位,不需要额外合并操作,代码也更紧凑。
方法3:用dplyr(tidyverse风格,更易读)
如果你习惯用tidyverse工具包,dplyr的写法会更直观:
library(dplyr) result <- df %>% group_by(KCL_ID) %>% # 按KCL_ID分组 filter(DAYS == min(DAYS)) %>% # 筛选出组内DAYS最小的行 ungroup() # 取消分组
这种写法逻辑清晰,后期维护和修改都很方便。
为什么直接用aggregate(cbind(DAYS,BMI)~KCL_ID, df, min)不行?
因为aggregate()会对每一列单独应用聚合函数——它会计算该分组DAYS的最小值,同时计算该分组BMI的最小值,这两个值大概率来自不同的行,自然就无法匹配到你要的对应关系啦。
内容的提问来源于stack exchange,提问作者Tseng
相关产品推荐
相关产品推荐

