如何在数据掩码中使用rlang::exec替代invoke实现列表拼接?
解决方法
要在mutate中用rlang::exec替代已弃用的invoke实现需求,核心是让!!!在数据掩码环境内展开参数,避免pick提前求值报错。可以用rlang::inject包裹表达式:
library(tidyverse) df <- tibble::tribble( ~Condition, ~Age...2, ~Age...3, ~Age...4, 1, 18, NA, NA, 1, 19, NA, NA, 2, NA, 20, NA, 2, NA, 21, NA, 3, NA, NA, 22, 3, NA, NA, 23 ) # 正确用法:用inject让!!!在数据掩码内展开 mutate(df, new = inject(coalesce(!!!pick(starts_with("Age")))))
运行结果与invoke版本一致,生成预期的new列:
# A tibble: 6 × 5 Condition Age...2 Age...3 Age...4 new <dbl> <dbl> <dbl> <dbl> <dbl> 1 1 18 NA NA 18 2 1 19 NA NA 19 3 2 NA 20 NA 20 4 2 NA 21 NA 21 5 3 NA NA 22 22 6 3 NA NA 23 23
失败原因解析
- 直接使用
exec(coalesce, pick(...))时,pick返回的是完整数据框,exec会将其作为单个参数传给coalesce,导致new列变成嵌套数据框,不符合需求。 - 使用
exec(coalesce, !!!pick(...))时,!!!在mutate解析参数阶段就会展开,此时pick还未进入数据掩码环境(mutate的延迟求值机制导致),因此触发“pick必须在数据掩码动词内使用”的报错。
inject的作用是延迟表达式求值,让!!!在mutate的数据掩码环境中执行,此时pick能正确识别当前数据框的列,!!!也能将pick返回的列列表拆分为coalesce的多个独立参数。
内容的提问来源于stack exchange,提问作者dufei
相关产品推荐
相关产品推荐

