如何在R中按ID分组为dataframe添加基于条件的指定值列
问题与解决方案:按分组条件填充新列
问题背景
有一个包含分组变量ID的数据框xmpl,需要添加新列a1_momo,要求每个ID分组的所有行都填充该分组中符合BM == 1 & W2 == 0 & dt == 1条件的行对应的a1值;如果分组无符合条件的行,或者符合条件的行的a1为NA,则该分组所有行的a1_momo填NA。
示例数据
xmpl <- data.frame(ID = c(1,1,1,1,1,2,2,2,2,3), BM = c(0,0,1,1,1,0,0,1,1,1), W2 = c(0,0,0,0,1,0,0,0,1,0), dt = c(1,2,1,2,1,1,2,2,1,1), a1 = c(3,2,1,2,2,3,2,2,3,NA))
数据框预览:
> xmpl ID BM W2 dt a1 1 1 0 0 1 3 2 1 0 0 2 2 3 1 1 0 1 1 4 1 1 0 2 2 5 1 1 1 1 2 6 2 0 0 1 3 7 2 0 0 2 2 8 2 1 0 2 2 9 2 1 1 1 3 10 3 1 0 1 NA
期望结果
> xmpl ID BM W2 dt a1 a1.momo 1 1 0 0 1 3 1 2 1 0 0 2 2 1 3 1 1 0 1 1 1 4 1 1 0 2 2 1 5 1 1 1 1 2 1 6 2 0 0 1 3 NA 7 2 0 0 2 2 NA 8 2 1 0 2 2 NA 9 2 1 1 1 3 NA 10 3 1 0 1 NA NA
用户疑问
用户想先生成按ID分组的单行数据框,再通过merge合并回原数据框,但不知道替代aggregate的工具,同时对ifelse结合多条件取值有疑问:
- 这个思路可行吗?需要用什么
[package::function]替代aggregate? - 使用
ifelse时,如何基于其他单元格的值填充新列?
解决方案
问题1:思路可行性与替代工具
你的思路完全可行,推荐用**dplyr包的分组操作**实现,既可以生成分组数据框再合并,也能直接在原数据框添加新列,效率更高:
方法1:生成分组数据框后合并
# 加载dplyr包 library(dplyr) # 生成按ID分组的目标数据框xmpl.2 xmpl.2 <- xmpl %>% group_by(ID) %>% summarise(a1 = ifelse(any(BM == 1 & W2 == 0 & dt == 1), a1[BM == 1 & W2 == 0 & dt == 1], NA)) %>% ungroup() # 合并回原数据框 xmpl <- merge(xmpl, xmpl.2, by = "ID", suffixes = c("", ".momo"))
方法2:直接在原数据框添加新列(更简洁)
无需拆分合并,直接按ID分组后把符合条件的a1值广播到整组:
library(dplyr) xmpl <- xmpl %>% group_by(ID) %>% mutate(a1.momo = ifelse(any(BM == 1 & W2 == 0 & dt == 1), a1[BM == 1 & W2 == 0 & dt == 1], NA)) %>% ungroup()
如果不想用dplyr,也可以用基础R的ave函数:
xmpl$a1.momo <- ave(xmpl$a1, xmpl$ID, FUN = function(x, BM, W2, dt) { idx <- which(BM == 1 & W2 == 0 & dt == 1) if(length(idx) == 0) NA else x[idx] }, BM = xmpl$BM, W2 = xmpl$W2, dt = xmpl$dt)
问题2:ifelse结合多条件取值的用法
在分组场景中,ifelse的逻辑如下:
- 先判断当前分组是否存在符合条件的行:用
any(BM == 1 & W2 == 0 & dt == 1)返回布尔值 - 如果存在,提取该分组中符合条件的行对应的
a1值:a1[BM == 1 & W2 == 0 & dt == 1](每个分组只有0或1个符合条件的行,直接取索引即可) - 如果不存在,返回
NA
当符合条件的行的a1本身是NA时,提取结果也会是NA,正好满足ID=3这类场景的需求。
内容的提问来源于stack exchange,提问作者2day.
相关产品推荐
相关产品推荐

