使用mutate_at匹配指定列时遇“No tidyselect variables were registered”错误的解决方法
解决
mutate_at报错:No tidyselect variables were registered 我来帮你搞定这个问题!你遇到的报错主要是因为在mutate_at中传递列名变量的方式不对,再加上mutate_at其实已经是dplyr的旧语法了,我会给你两种解决方案:一种修复你原来的mutate_at写法,另一种是更推荐的现代dplyr语法。
先理清问题根源
你定义的vars_to_match是精确的列名列表,但你用了matches()(这是用来做正则模糊匹配的),虽然理论上拼接成正则也能匹配,但这种方式在tidyselect上下文中容易出现变量注册问题,导致报错。另外,从dplyr 1.0.0版本开始,官方已经推荐用across()取代mutate_at/mutate_if等旧函数,后者现在只处于维护状态。
方案1:修复mutate_at的写法
用all_of()来精确匹配你指定的列名,这是传递变量列名最可靠的方式:
library(dplyr) library(tidyr) # 数据准备(和你原来的一致) data(iris) my_Data <- iris %>% mutate(row = row_number()) %>% pivot_wider(names_from = Species, values_from = Sepal.Length:Petal.Width) # 标准化函数 Scale_Me <- function(x){ (x - mean(x, na.rm = TRUE)) / sd(x, na.rm = TRUE) } # 要处理的列名 vars_to_match <- c("Petal.Length_virginica", "Sepal.Length_virginica", "Sepal.Width_setosa") # 正确的mutate_at写法 my_Data %>% mutate_at( .vars = all_of(vars_to_match), .funs = list(Scaled = Scale_Me) # 用list指定新列的后缀,更清晰 )
这里all_of(vars_to_match)会精准定位你列出的列,避免正则匹配带来的不确定性,同时也能正确注册tidyselect变量,解决报错问题。
方案2:推荐使用mutate(across(...))现代语法
across()是dplyr现在主推的函数,功能更灵活,写法也更直观:
# 现代写法:用across处理指定列 my_Data %>% mutate( across(all_of(vars_to_match), Scale_Me, .names = "{.col}_scaled") )
all_of(vars_to_match):精准选择目标列Scale_Me:要应用的标准化函数.names = "{.col}_scaled":自定义新列名,{.col}会自动替换成原列名,生成类似Petal.Length_virginica_scaled的新列,可读性更强
额外说明:如果需要模糊匹配列
如果你确实需要根据列名的模式(比如包含"virginica")来选择列,那可以用matches(),写法如下:
# 匹配所有包含"virginica"的列 my_Data %>% mutate( across(matches("virginica"), Scale_Me) )
内容的提问来源于stack exchange,提问作者user113156
相关产品推荐
相关产品推荐

