波浪运算符在R中用于附加paste0()函数时的目的是什么?



我不确定下面这行代码是如何工作的,因为没有波浪:

betterLifeIndicators <- betterLifeIndicators |>   
rename_with(paste0(.x, ")"))

它不起作用,理由是对象'。没有找到X '。然而,当在paste0:

前面添加波浪线时
betterLifeIndicators <- betterLifeIndicators |>   
rename_with(~paste0(.x, ")"))

效果很好。我对R很陌生,我正在努力理解在这里工作的机制。我不确定整行是怎么写的

rename_with(~paste0(.x, ")")) 

达到了它的目的(在data.frame中的每个列名后面加上括号)。

这是我对R的理解上的一个缺陷,但是我将感谢任何帮助来理解整个情况,因为我不愿意在我对语言的理解上留下这样一个漏洞的同时继续我的项目。

嗯,这是一个整洁的丛林,但你可以试着这样想:

在标准R中有一种对象叫做"公式"。它是用像这样的波浪线创建的:

f <- ~ anythinig + can + be + here + paste(1, 2, 3)

我们可以检查这个对象的类是什么,得到:

> class(f)
[1] formula

rename_with()为函数。它需要传递至少2个参数:1)data.frame, 2)重命名列的函数:

> rename_with(iris, toupper)
SEPAL.LENGTH SEPAL.WIDTH PETAL.LENGTH PETAL.WIDTH SPECIES
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
在R中,函数可以选择如何处理它们的参数。我们可以试着检查这个函数的作用:
> rename_with
function (.data, .fn, .cols = everything(), ...) 
{
UseMethod("rename_with")
}
<bytecode: 0x7faad65f8510>
<environment: namespace:dplyr>

不是那么有用,它告诉我们这个函数是一个泛型函数,它的真正主体隐藏在其他地方。我们可以在这里找到:

> dplyr:::rename_with.data.frame
function (.data, .fn, .cols = everything(), ...) 
{
.fn <- as_function(.fn)
cols <- tidyselect::eval_select(enquo(.cols), .data, allow_rename = FALSE)
names <- names(.data)
...

现在我们看到,它对第二个参数(.fn)所做的第一步是将其转换为具有as_function(.fn)的函数。

这个as_function()函数在另一个tidyverse包中- "rlang"我们可以在这里找到它:

> rlang::as_function
function (x, env = global_env(), ..., arg = caller_arg(x), call = caller_env()) 
{
check_dots_empty0(...)
if (is_function(x)) {
return(x)
}
if (is_quosure(x)) {
mask <- eval_tidy(call2(environment), env = quo_get_env(x))
fn <- new_function(pairlist2(... = ), quo_get_expr(x), mask)
return(fn)
}
if (is_formula(x)) {
if (length(x) > 2) {
...

对我们来说,相关的部分是我所显示的输出部分末尾的is_formula调用。所以基本上rename_with有一些聪明的(?)方法将公式转化为函数。但是你也可以通过传递你自己的函数来达到同样的目的:

iris |> rename_with(function(x) paste0(x, ")"))
Sepal.Length) Sepal.Width) Petal.Length) Petal.Width) Species)
1           5.1          3.5           1.4          0.2   setosa
2           4.9          3.0           1.4          0.2   setosa
3           4.7          3.2           1.3          0.2   setosa
4           4.6          3.1           1.5          0.2   setosa
5           5.0          3.6           1.4          0.2   setosa
6           5.4          3.9           1.7          0.4   setosa

使用tilde的方法(创建一个公式,然后在rename_with中转换为函数)只是一些语法糖。下面的代码将这个公式转换为一个函数。

和你的第一个方法:

betterLifeIndicators <- betterLifeIndicators |>   
rename_with(paste0(.x, ")"))

没有工作,因为在你的调用中,参数paste0(.x, ")")还没有最终形式——它需要被求值,R解释器试图先求值这个语句,但没有找到.x,并向你显示一个错误。

最新更新