tilde运算符在R中用于连接paste0()函数的目的是什么?

huangapple go评论60阅读模式
英文:

What is the purpose of the tilde operator when used to append the paste0() function in R?

问题

以下是翻译好的部分:

不加波浪号时,代码如下:

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

不起作用,并报告未找到对象'.x'。但是,当在paste0之前添加波浪号时,代码如下:

betterLifeIndicators <- betterLifeIndicators |>
rename_with(~paste0(.x, "&quot;))

它可以正常工作。我对R相当新手,难以理解这里的机制。我不确定整个行:

rename_with(~paste0(.x, "&quot;))

如何实现其目的(在数据框的每个列名后附加括号)。

英文:

I am unsure as to how exactly the following line of code works, given that without the tilde:

betterLifeIndicators &lt;- betterLifeIndicators |&gt;   
rename_with(paste0(.x, &quot;)&quot;))

it doesn't work, citing that the object '.x' is not found. Yet when adding the tilde in front of paste0:

betterLifeIndicators &lt;- betterLifeIndicators |&gt;   
rename_with(~paste0(.x, &quot;)&quot;))

it works perfectly. I am quite new to R and I am struggling to understand the mechanism at work here. I am unsure as to how that whole line:

rename_with(~paste0(.x, &quot;)&quot;)) 

is achieving its purpose (appending a parenthesis to every column name in a data.frame).

This is a flaw in my understanding of R, but I would appreciate any help with understanding this whole situation since I would hate to move forward with my project while leaving such a hole in my understanding of the language.

答案1

得分: 1

这是一些关于tidyverse的内容,其中介绍了R中的"formula"对象和"rename_with()"函数的用法。这个函数需要传递至少两个参数:1) 一个数据框(data.frame),2) 一个用于重命名列的函数。 "rename_with()" 函数会将第二个参数转化为一个函数,可以通过传递自定义函数来实现相同的效果。

英文:

Eh, this is some tidyverse jungle, but you can try to think about it like so:

In standard R there is a type of object called "formula" which is created with a tilde like so:

f &lt;- ~ anythinig + can + be + here + paste(1, 2, 3)

We can check what is the class of this object and we get:

&gt; class(f)
[1] formula

Then, rename_with() is a function. It needs to be passed at least 2 arguments: 1) a data.frame, 2) a function that renames the columns:

&gt; 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

In R functions can choose what to do with their arguments. We can try to inspect what this particular function does:

&gt; rename_with
function (.data, .fn, .cols = everything(), ...) 
{
    UseMethod(&quot;rename_with&quot;)
}
&lt;bytecode: 0x7faad65f8510&gt;
&lt;environment: namespace:dplyr&gt;

Not that useful, it tells us that this function is a generic function, the real body of it is hidden in some other place. We can find it here:

&gt; dplyr:::rename_with.data.frame
function (.data, .fn, .cols = everything(), ...) 
{
    .fn &lt;- as_function(.fn)
    cols &lt;- tidyselect::eval_select(enquo(.cols), .data, allow_rename = FALSE)
    names &lt;- names(.data)
...

Now we see that the first step it does to the second argument (.fn) is transform it into a function with as_function(.fn).

This as_function() function is in another tidyverse package - "rlang" and we can find it there:

&gt; 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 &lt;- eval_tidy(call2(environment), env = quo_get_env(x))
        fn &lt;- new_function(pairlist2(... = ), quo_get_expr(x), mask)
        return(fn)
    }
    if (is_formula(x)) {
        if (length(x) &gt; 2) {
...

The relevant part for us is this is_formula call in the end of the part of output I showed. So basically rename_with has some clever(?) way to turn a formula into a function. But you can achieve the same thing by passing your own function:

iris |&gt; rename_with(function(x) paste0(x, &quot;)&quot;))

  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

The approach with tilde (creating a formula that is then turned into a function within rename_with) is just some syntax sugar. Under the hood the code then turns this formula into a function.

And your first approach:

betterLifeIndicators &lt;- betterLifeIndicators |&gt;   
rename_with(paste0(.x, &quot;)&quot;))

didn't work, because in your call the argument paste0(.x, &quot;)&quot;) is not yet in a final form - it needs to be evaluated, R interpreter tries to evaluate this statement first but fails to find .x and shows you an error.

huangapple
  • 本文由 发表于 2023年4月7日 01:14:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/75952121.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定