如何使用tidyverse的cur_column()合并多列(SDQ量表场景)
合并SDQ量表不同年龄段条目列的解决方案
我有SDQ(长处与困难量表)的25个条目,需要将每个条目的2to4yrs版本列与5to17yrs版本列合并,最终保留2to4yrs列名,用5to17yrs列的非NA值填补对应2to4yrs列的NA值。
示例数据
library(tidyverse) df <- data.frame( sdq2to4yrs_item1 = c(1, NA, NA), sdq5to17yrs_item1 = c(NA, NA, 2), sdq2to4yrs_item2 = c(2, 2, NA), sdq5to17yrs_item2 = c(1, 2, 3) ) df #> sdq2to4yrs_item1 sdq5to17yrs_item1 sdq2to4yrs_item2 sdq5to17yrs_item2 #> 1 1 NA 2 1 #> 2 NA NA 2 2 #> 3 NA 2 NA 3
期望结果
data.frame( sdq2to4yrs_item1 = c(1, NA, 2), sdq2to4yrs_item2 = c(2, 2, 3) ) #> sdq2to4yrs_item1 sdq2to4yrs_item2 #> 1 1 2 #> 2 NA 2 #> 3 2 3
报错代码
尝试用以下代码实现但触发递归求值错误:
df %>% mutate( across( matches("2to4yrs"), ~ coalesce( !!!select(., matches( cur_column() %>% str_remove(".*yrs_") ) ) ) ) ) #> Error in local_error_context(dots = dots, .index = i, mask = mask): promise already under evaluation: recursive default argument reference or earlier problems?
解决方案
报错原因
原代码在coalesce中使用!!!select(., ...)时,会递归引用正在修改的数据框,触发promise求值冲突,导致报错。
方案1:长格式转换法(适合批量处理)
先转长格式按条目分组合并,再转回宽格式:
df %>% pivot_longer( everything(), names_to = c("age_group", "item"), names_pattern = "sdq(.*)_item(\\d+)", values_to = "value" ) %>% group_by(item) %>% summarise( value = coalesce(value[age_group == "2to4yrs"], value[age_group == "5to17yrs"]) ) %>% pivot_wider( names_from = item, names_prefix = "sdq2to4yrs_item", values_from = value )
方案2:直接匹配对应列(更简洁)
在across中提取条目编号,构造对应5to17yrs列名,直接合并:
df %>% mutate( across(matches("2to4yrs"), ~ { # 提取条目后缀(如item1、item2) item_suffix <- str_remove(cur_column(), "sdq2to4yrs_") # 构造对应5to17yrs列的列名 target_col <- sym(str_c("sdq5to17yrs_", item_suffix)) # 合并两列,保留非NA值 coalesce(., !!target_col) }) ) %>% # 可选:移除原5to17yrs列 select(-matches("5to17yrs"))
运行上述任意方案均可得到期望结果。
内容的提问来源于stack exchange,提问作者its.me.adam
相关产品推荐
相关产品推荐

