如何在dplyr中基于多列匹配生成新列?
在tidyverse中按多列优先级生成新列的解决方法
你可以通过以下几种tidyverse的方式实现需求,核心是按行判断多列中是否存在目标值,并遵循优先级顺序匹配:
方法1:rowwise + case_when(直观易读)
利用rowwise()让dplyr按行处理数据,结合case_when()按优先级顺序判断条件:
library(dplyr) a <- data.frame(var1 = c("one", "two", "three"), var2 = c("three", "one", "three"), var3 = c("three", "two", NA)) a <- a %>% rowwise() %>% mutate( result = case_when( # 优先级最高:只要行内有"one"就返回1,na.rm忽略NA any(c(var1, var2, var3) == "one", na.rm = TRUE) ~ 1, # 次之:行内无"one"但有"two"返回2 any(c(var1, var2, var3) == "two", na.rm = TRUE) ~ 2, # 兜底:其余情况(含"three"或NA)返回3 TRUE ~ 3 ) ) %>% ungroup() # 取消行处理模式,避免后续操作受影响 print(a)
输出结果:
var1 var2 var3 result 1 one three three 1 2 two one two 1 3 three three <NA> 3
方法2:pmap逐行处理(灵活通用)
用pmap_dbl()遍历每行数据,将每行元素转为向量后用基础逻辑判断:
a <- a %>% mutate( result = pmap_dbl(., ~ { row_vals <- c(...) # 将当前行的所有列转为向量 if ("one" %in% row_vals) 1 else if ("two" %in% row_vals) 2 else 3 }) )
关键注意点
- 优先级顺序必须从高到低写:
case_when()或if-else会匹配第一个满足的条件,所以"one"的判断要放在最前面。 na.rm = TRUE:避免NA值干扰any()的判断(比如第三行的NA不会影响我们识别出存在"three")。
内容的提问来源于stack exchange,提问作者Giulio Centorame
相关产品推荐
相关产品推荐

