R语言匹配规则列子集按行计算逻辑OR的报错解决方案
问题原因
你遇到的报错和逻辑问题来自两点:
- 上下文规则不匹配:
matches()属于tidyselect体系的列选择函数,只能运行在原生支持tidyselect选择语法的函数内部(比如select()、across()、if_any()等)。你在mutate()的普通计算表达式里直接嵌套select(matches()),既不符合选择器的运行上下文要求,select()返回的子数据框也无法直接参与逐行计算。 - 计算逻辑写反:逻辑OR运算的规则是「任意一个输入为TRUE,结果即为TRUE」,你原本写的
sum(...) == 0是判断所有值求和为0(即全为FALSE),和目标逻辑完全相反。
正确实现方法
方法1:最简洁写法(推荐,dplyr 1.0.0+版本支持)
直接用专为行方向逻辑判断设计的if_any()函数,它原生支持tidyselect选择语法,会逐行判断匹配到的列是否存在任意TRUE值,本身就是行级逻辑OR运算:
df %>% mutate(valid = if_any(matches("^c_")))
运行后输出结果符合预期:
# A tibble: 3 × 4 # Groups: id [3] id c_1 c_2 valid <dbl> <lgl> <lgl> <lgl> 1 1 TRUE FALSE TRUE 2 2 TRUE FALSE TRUE 3 3 FALSE TRUE TRUE
方法2:兼容旧版本dplyr的写法
如果你的dplyr版本较低没有if_any(),可以搭配across()选列+rowSums()做行计算:逻辑值TRUE会被识别为1、FALSE为0,行求和大于0即代表至少有一个列为TRUE,等价于逻辑OR:
df %>% mutate(valid = rowSums(across(matches("^c_"))) > 0)
方法3:自定义复杂行逻辑的通用写法
如果后续需要扩展更复杂的行判断规则,可以用pmap_lgl()逐行传入选中列的值做判断,兼容性最强:
df %>% mutate(valid = pmap_lgl(across(matches("^c_")), ~ any(c(...))))
注:以上写法都不会破坏你原数据的
group_by(id)分组结构,计算完成后分组属性会保留。
内容的提问来源于stack exchange,提问作者Ai4l2s
相关产品推荐
相关产品推荐

