如何在tidyr::gather中动态设置键或值?gather_()与matches兼容问题
解决tidyr动态设置gather键/值且配合matches的问题
我太懂这个坑了——旧版的gather_()作为标准评估函数,确实没法直接和matches()这类tidyselect工具配合,之前我也踩过类似的坑。下面给你几个实用的解决方案,亲测有效:
方案1:切换到pivot_longer()(强烈推荐)
tidyr早就把gather()标记为“软弃用”了,主推的pivot_longer()原生支持动态参数+tidyselect函数,完美解决你的需求。不管是动态指定键名、值名,还是用matches()匹配列,都能直接搞定:
library(tidyr) # 先搞个示例数据 df <- tibble(id = 1:3, temp_2020 = 22:24, temp_2021 = 25:27, temp_2022 = 28:30) # 动态参数:比如要匹配的列模式、自定义键/值列名 target_pattern <- "temp_\\d+" dynamic_key_name <- "year" dynamic_value_name <- "temperature" # 直接用pivot_longer实现动态操作 df %>% pivot_longer( cols = matches(target_pattern), # 直接用matches匹配列 names_to = dynamic_key_name, # 动态设置键列名 values_to = dynamic_value_name # 动态设置值列名 )
这个方法不需要额外的转换,语法更直观,也是tidyverse官方推荐的方向。
方案2:如果必须用gather()系列函数
要是你因为项目兼容性等原因必须用gather()或gather_(),可以先把matches()的结果转换成列名字符串向量,再结合rlang的解引用操作符来传递动态参数:
# 第一步:把matches匹配的列转换成字符串向量 selected_cols <- names(df)[grepl(target_pattern, names(df))] # 用gather的话,用!!解引用动态键/值名,all_of()传递列向量 df %>% gather(key = !!dynamic_key_name, value = !!dynamic_value_name, all_of(selected_cols)) # 用gather_的话(不推荐,已被淘汰),直接传字符串参数就行 df %>% gather_(key_col = dynamic_key_name, value_col = dynamic_value_name, gather_cols = selected_cols)
为什么之前的方法不行?
gather_()是标准评估函数,只接受字符串类型的参数;但matches()返回的是tidyselect的选择对象(不是纯字符串),所以直接传会报错。先把匹配结果转换成列名字符串,就能让gather_()识别了。而gather()结合!!操作符,则是用非标准评估的方式让动态变量被正确解析。
内容的提问来源于stack exchange,提问作者Andre Elrico
相关产品推荐
相关产品推荐

