如何用tidy-select在mutate中创建可扩展的汇总变量?
解决方案:用
if_any或rowwise()+c_across实现可扩展的逐行汇总 你遇到的问题是any(all_of(variables))无法按行处理选中的列——any函数默认会把整个列的所有值作为输入,而非逐行判断。下面提供两种符合你需求的可扩展写法:
方法一:使用if_any(推荐)
if_any是tidyverse专门为逐行多列判断设计的函数,直接支持tidy-select语法,无需额外行分组处理:
variables = c("v1", "v2") tst = tribble( ~ID, ~time, ~v1, ~v2, "1a", 1, T, F, "1b", 1, F, T, "1c", 1, F, F, "1a", 2, T, F, "1b", 2, T, T, "1c", 2, F, F ) tst %>% group_by(ID, time) %>% mutate(any_v = if_any(all_of(variables), ~.x)) %>% ungroup()
扩展性验证(新增v3)
当数据和variables向量新增v3时,完全不需要修改mutate部分的代码:
# 新增v3变量 variables = c("v1", "v2", "v3") tst = tribble( ~ID, ~time, ~v1, ~v2, ~v3, "1a", 1, T, F, F, "1b", 1, F, T, T, "1c", 1, F, F, F, "1a", 2, T, F, T, "1b", 2, T, T, F, "1c", 2, F, F, F ) # 复用原有代码,无需修改mutate调用 tst %>% group_by(ID, time) %>% mutate(any_v = if_any(all_of(variables), ~.x)) %>% ungroup()
if_any的逻辑是:对每行中选中的列,判断是否有任意一列满足~.x(因原变量是逻辑型,~.x等价于判断值为TRUE),直接返回逐行的判断结果。
方法二:使用rowwise() + c_across
如果习惯用any函数,可以结合rowwise()让代码按行处理,再用c_across提取每行的指定列值:
tst %>% group_by(ID, time) %>% rowwise() %>% mutate(any_v = any(c_across(all_of(variables)))) %>% ungroup()
c_across(all_of(variables))会把每行中指定的列转换成一个逻辑向量,再用any()判断该向量是否包含TRUE,rowwise()确保这个判断是逐行执行的。
内容的提问来源于stack exchange,提问作者user23942556
相关产品推荐
相关产品推荐

