如何用dplyr按ID分组并通过多条件判断新增TEST列?
解决方案:用dplyr处理分组后的回答组合逻辑
你的原始数据是长格式(每个ID对应3行,每行是一个问题的回答),以下提供两种高效处理方式,替代易出错的嵌套ifelse:
方法1:转宽格式后用case_when判断(逻辑更直观)
先将数据转换为宽格式(每个ID一行,包含三个问题的回答),再用case_when定义规则,结构清晰易维护。
步骤1:加载依赖包
library(dplyr) library(tidyr)
步骤2:转换为宽格式
假设你的Question列(或问题标题列)取值为Q1、Q2、Q3,用来区分三个问题:
df_wide <- df %>% pivot_wider( id_cols = ID, names_from = Question, # 若用"问题标题"列区分,改为`names_from = "问题标题"` values_from = Answer )
步骤3:根据回答组合生成TEST列
df_result <- df_wide %>% mutate( TEST = case_when( # 规则1:全部回答No → TEST=A Q1 == "No" & Q2 == "No" & Q3 == "No" ~ "A", # 规则2:Q1=No,Q2和Q3=Yes → TEST=B Q1 == "No" & Q2 == "Yes" & Q3 == "Yes" ~ "B", # 可继续添加其他规则,示例: Q1 == "Yes" & Q2 == "No" & Q3 == "No" ~ "C", # 未匹配的情况设为默认值 TRUE ~ "Other" ) )
步骤4(可选):合并回原始长格式
若需保留原始数据的行结构,将TEST列关联回去:
df_final <- df %>% left_join(df_result %>% select(ID, TEST), by = "ID")
方法2:直接分组判断(无需转换格式)
如果不想改变数据结构,可直接按ID分组,通过索引定位对应问题的回答:
df_final <- df %>% group_by(ID) %>% mutate( TEST = case_when( # 全部回答No all(Answer == "No") ~ "A", # Q1=No,Q2和Q3=Yes (Answer[Question == "Q1"] == "No") & all(Answer[Question %in% c("Q2", "Q3")] == "Yes") ~ "B", # 补充其他规则 TRUE ~ "Other" ) ) %>% ungroup()
注意事项
- 确保每个ID的3个问题回答无缺失、无重复行,否则需先通过
filter()或complete()处理数据; case_when按顺序判断,优先级高的规则要写在前面;- 若问题标识不是
Q1/Q2/Q3,替换为实际的Question或问题标题列取值即可。
内容的提问来源于stack exchange,提问作者LM CT
相关产品推荐
相关产品推荐

