使用dplyr为任意列应用自定义函数报错的原因及解决方法问询
自定义trim_whitespace函数报错'island' not found的原因与修复
问题重现
library(tidyverse) library(palmerpenguins) trim_whitespace <- function(.data, ...) { .data |> mutate(across(..., \(x) str_remove_all(x, "\\s"))) } # 在字符列末尾添加空格 penguins_with_whitespace <- penguins |> mutate(across(c(species, island), \(x) paste0(x, " "))) penguins_with_whitespace |> trim_whitespace(species, island)
运行后报错:'island' not found
错误原因
问题出在整洁求值(tidy eval)的上下文绑定上:
- 你通过
...传递的species、island是裸列名,默认会在函数的全局环境中查找这些对象,而非传入的.data数据框内部环境。 across()需要识别数据框内的列选择器,但当前写法没有将列名的求值上下文绑定到数据框,导致R误认为你要找全局环境中名为species或island的独立对象,自然找不到。
修复方法
两种简洁的修复方式,核心都是让R明确你传递的是数据框内的列名:
方法1:使用准引用{{}}(推荐)
通过{{}}(准引用语法)捕获...中的列名,将它们的求值上下文绑定到目标数据框:
trim_whitespace <- function(.data, ...) { .data |> mutate(across({{...}}, \(x) str_remove_all(x, "\\s"))) }
方法2:使用enquos()和!!!(展开引用)
先通过enquos()捕获...中的所有列名引用,再用!!!(展开操作符)传递给across():
trim_whitespace <- function(.data, ...) { target_cols <- enquos(...) .data |> mutate(across(!!!target_cols, \(x) str_remove_all(x, "\\s"))) }
修复后再次执行penguins_with_whitespace |> trim_whitespace(species, island),即可正确去除指定列的空格。
内容的提问来源于stack exchange,提问作者dzegpi
相关产品推荐
相关产品推荐

