如何按ID分组,以B=apple时的A值为阈值生成output列
按ID分组创建output列的解决方案
需求说明
为数据框df1新增output列,规则如下:
- 按
ID分组 - 每组内,若该行
A值大于等于该组中B == "apple"对应的A值,output为1;否则为0
示例数据
df1 <- data.frame(ID = c("a", "a", "a", "b", "b", "b", "b", "c", "c", "c"), A = c(2, 1, 8, 4, 3, 12, 9, 142, 13, 8), B = c("apple", "orange", "kiwi", "orange", "apple", "kiwi", "pear", "kiwi", "apple", "orange"))
预期结果:
ID A B output 1 a 2 apple 1 2 a 1 orange 0 3 a 8 kiwi 1 4 b 4 orange 1 5 b 3 apple 1 6 b 12 kiwi 1 7 b 9 pear 1 8 c 142 kiwi 1 9 c 13 apple 1 10 c 8 orange 0
解决方案
1. tidyverse(dplyr)方案
利用group_by实现分组,在组内提取B == "apple"的A值并比较:
library(dplyr) df1 <- df1 %>% group_by(ID) %>% mutate(output = as.integer(A >= A[B == "apple"])) %>% ungroup()
2. Base R方案
方法一:使用ave函数(简洁高效)
ave支持分组计算,直接在原数据框上新增列:
df1$output <- with(df1, ave(A, ID, FUN = function(x, b) { apple_val <- x[b == "apple"] as.integer(x >= apple_val) }, B = B))
方法二:拆分-处理-合并
通过split拆分数据框,逐个处理分组后合并:
# 按ID拆分数据框 df_groups <- split(df1, df1$ID) # 逐个分组处理 df_groups <- lapply(df_groups, function(group) { apple_a <- group$A[group$B == "apple"] group$output <- as.integer(group$A >= apple_a) group }) # 合并分组并重置行名 df1 <- do.call(rbind, df_groups) rownames(df1) <- NULL
原代码问题说明
你之前尝试的df1$A >= df1$A[df1$B== "apple" & df1$ID == "a"]仅针对ID="a"的情况,没有实现按ID分组的逻辑,因此无法正确处理其他ID的行。
内容的提问来源于stack exchange,提问作者Kent0603
相关产品推荐
相关产品推荐

