如何在R语言中基于条件与出现次数为数据框分配二值之一
嘿,我来帮你搞定这个需求!首先先修正下你提供的可复现代码里的小问题(原代码中rep(0,10, each=9)的参数顺序有误,会导致生成的元素数量不对),修正后的可复现代码如下:
Scene2 = rep(c(1:10), times=9) myDF2 <- data.frame(Scene2) myDF2$Target <- rep(0, nrow(myDF2)) # 生成与数据框行数一致的0 myDF2$Target[myDF2$Scene2==7] <- 1 # 将Scene2=7的行Target设为1 myDF2$Trial <- rep(c(1:9), each=10) myDF2$Route <- rep(LETTERS[1:6], each=10, length=nrow(myDF2))
接下来针对你“基于条件和出现次数给指定列分配两个值之一”的需求,我分两种常见场景给出实现方法:
场景1:按分组统计条件总次数,给整组分值
比如我们按Trial分组,每个组里如果Target==1的总次数≥1,就给该组的新列NewCol赋值"Value1",否则赋值"Value2"。
用Base R实现
# 第一步:按Trial分组统计每组Target==1的次数 target_counts <- aggregate(Target ~ Trial, data=myDF2, FUN=sum) # 第二步:把统计结果合并回原数据框 myDF2 <- merge(myDF2, target_counts, by="Trial", suffixes=c("", "_count")) # 第三步:根据计数结果赋值 myDF2$NewCol <- ifelse(myDF2$Target_count >= 1, "Value1", "Value2") # 移除临时统计列(可选) myDF2$Target_count <- NULL
用dplyr(tidyverse)实现
如果你习惯用tidyverse的语法,代码会更简洁直观:
library(dplyr) myDF2 <- myDF2 %>% group_by(Trial) %>% # 按Trial分组 mutate( Target_count = sum(Target), # 统计每组Target==1的次数 NewCol = case_when( Target_count >= 1 ~ "Value1", # 满足条件赋值Value1 TRUE ~ "Value2" # 其他情况赋值Value2 ) ) %>% ungroup() %>% # 取消分组 select(-Target_count) # 移除临时列
场景2:按条件行的出现顺序(次数)赋值
另一种常见需求是:针对每个分组内满足Target==1的行,按它是第几次出现来赋值(比如第1次出现赋值"First",第2次及以后赋值"Subsequent",不满足条件的行赋值"None")。
用dplyr实现
library(dplyr) myDF2 <- myDF2 %>% group_by(Route) %>% # 这里按Route分组,你可以换成Trial或其他列 mutate( Target_seq = cumsum(Target), # 给每组内Target==1的行按出现顺序编号 NewCol = case_when( Target == 0 ~ "None", Target_seq == 1 ~ "First", Target_seq > 1 ~ "Subsequent" ) ) %>% ungroup() %>% select(-Target_seq) # 移除临时列
用Base R实现
# 给每个Route分组内的Target==1行按出现顺序编号 myDF2$Target_seq <- ave(myDF2$Target, myDF2$Route, FUN = cumsum) # 根据编号和条件赋值 myDF2$NewCol <- with(myDF2, ifelse(Target == 0, "None", ifelse(Target_seq == 1, "First", "Subsequent"))) # 移除临时列 myDF2$Target_seq <- NULL
如果你的需求有更具体的规则(比如不同的分组依据、次数阈值),只需要调整代码里的分组列、条件判断逻辑就行,非常灵活。
内容的提问来源于stack exchange,提问作者dede
相关产品推荐
相关产品推荐

