3

总结 我正在阅读一篇关于 dplyr 的跨函数主题的文章。看第一个使用例子,看到了之前没见过的操作符的使用。我不知道它们是否本质上是 dplyr 或其他包的一部分。无论哪种方式,我都不明白它们在代码中的用途。

代码示例:

starwars |>
    summarize(across(where(is.character), ~ length(unique(.x))))

结果是一个 1 x 8 的小标题。

我理解cross的第一个论点,令我困惑的是第二个论点。是什么~length(unique(.x))意思?.x 代码是什么意思?我知道长度被应用于 tibble 中的每个字符向量,但是“唯一”对代码片段有什么作用?

我自己尝试过什么来解决这个问题? 我曾尝试使用 Google 搜索 [R] ~ 运算符,但未收到相关结果。我还尝试了 rdrr.io、r-project.org 和 CRAN,但没有解决方案。以及 tidyverse.org 和 purrr 的文档——这是因为看到有人在他们的代码中使用相同的语法时引用了 purrr。

问题:

有人可以帮助我了解内部发生的事情吗?

4

2 回答 2

8

这称为 purr-style lambda,以波浪号开头~.x用于引用在.cols参数中选择的每个单独的列。所以:

# We can either use
starwars |> summarize(across(where(is.character), ~ length(unique(.x)))) 

# Or we can define our anonymous function like this
starwars |> summarize(across(where(is.character), function(x) length(unique(x)))) 

它们是等价的。但应该注意的是,您指定了要应用于starwars数据集中每一列的函数,该列属于 class character。为此,在此代码中,它使用where函数作为助手,它应用函数(此处is.character)以仅选择那些具有类字符的列。然后我们对它们中的每一个应用我们的匿名函数并将结果保存在单独的列中。所以.x这里代表了类字符的每一列。请注意,这|>是 R 新创建的本地管道运算符。我们通常%>%tidyverse包一起使用,但两者都在做同样的工作,将它的结果替换为它LHS的第一个参数,RHS这通常是(在这种情况下).data争论。这里还要提一件事,尽管它在下面被用于另一个目的。为了了解lambda-style-formula后端是如何解释的,我们可以使用as_mapper大多数 purrr 函数允许的各种函数规范背后的强大动力:

library(purrr)

> as_mapper(~ length(unique(.x)))
<lambda>
function (..., .x = ..1, .y = ..2, . = ..1) 
length(unique(.x))
attr(,"class")
[1] "rlang_lambda_function" "function" 

如果您注意它的输出,您会发现它被解释为我们通常使用的匿名函数。

有关更多信息,您可以阅读文档。

于 2021-07-05T00:13:44.100 回答
3

~是在tidyverse. ~length(unique(.x))将产生与 相同的结果function(.x) {length(unique(.x))}

这种编写函数的方式最有可能与purrrlibrary 一起使用,实际上,purrr::as_mapper()它可以识别这种语法并返回一个可以像R.

例如:函数f会告诉我有多少唯一值.x.x也可以称为 ...1。如果您有两个参数,则.x.y。最后有 n 个参数..1, ..2, ..3......n

require(purrr)
#> Loading required package: purrr

f <- as_mapper(~length(unique(.x)))

f2 <- as_mapper(~length(unique(.)))

f3 <- as_mapper(~length(unique(..1)))
  
f(mtcars$mpg) 
#> [1] 25
f2(mtcars$mpg)
#> [1] 25
f3(mtcars$mpg)
#> [1] 25

reprex 包于 2021-07-05 创建 (v2.0.0 )

另一个例子:

library(dplyr)
library(purrr)

#in all starwars columns that are character vectors, how many unique values are they?

starwars |>
  summarize(across(where(is.character), ~ length(unique(.x))))
#> # A tibble: 1 x 8
#>    name hair_color skin_color eye_color   sex gender homeworld species
#>   <int>      <int>      <int>     <int> <int>  <int>     <int>   <int>
#> 1    87         13         31        15     5      3        49      38

f <- as_mapper(~ if (is.character(.x)) length(unique(.x)) else NULL)

f_base <- function(.x) {if (is.character(.x)) length(unique(.x)) else NULL}

starwars %>% 
  map_dfc(f)
#> # A tibble: 1 x 8
#>    name hair_color skin_color eye_color   sex gender homeworld species
#>   <int>      <int>      <int>     <int> <int>  <int>     <int>   <int>
#> 1    87         13         31        15     5      3        49      38

starwars %>% 
  map_dfc(f_base)
#> # A tibble: 1 x 8
#>    name hair_color skin_color eye_color   sex gender homeworld species
#>   <int>      <int>      <int>     <int> <int>  <int>     <int>   <int>
#> 1    87         13         31        15     5      3        49      38

reprex 包于 2021-07-05 创建 (v2.0.0 )

于 2021-07-05T03:20:35.570 回答