3

我正在使用 Hadley 的 R4DS 书对 tidyverse 和 purrr 进行循环,并且对波浪号 ~ 符号和句点符号的确切用法有点困惑。

因此,在编写 for 循环或使用 map() 时,而不是写出 function(),看来您可以使用波浪号代替 ~。

这仅适用于 for 循环吗?

所以如下...

models <- mtcars %>% 
  split(.$cyl) %>% 
  map(~lm(mpg ~ wt, data = .))

此外,我被告知的时间段可用于“引用当前列表元素”。但我很困惑这意味着什么。这是否意味着,只有在循环时,句点才表示它指的是列表中被循环的元素?它与管道有什么区别?管道时,您将一行的结果管道传输到下一行代码。

因此,在上述情况下,mtcars 使用 split() 管道传输到第二行,但使用了句点。为什么?

下面的案例总结了我的困惑:

x <- c(1:10)

detect(x, ~.x > 5)

使用找到第一个匹配项的检测功能,我想我可以使用

detect(x, x >5)

但我收到一个错误,说 x >5 不是函数。所以我加了一个波浪号

detect(x, ~ x > 5)

并得到一个错误说它需要一个 TRUE 或 FALSE,而不是 10。所以如果你添加一个句点

detect(x, ~.x >5) 

突然它就像循环一样工作。那么 ~ 和 . 的关系/用法是什么?这里和如何。与简单的管道相比?

4

1 回答 1

6

这种整体被称为tidyverse非标准评估(NSE)。您可能会发现它~用于公式中以指示左侧依赖于右侧。

tidyverseNSE 中,~表示function(...). 因此,这两个表达式是等价的。

x %>% detect(function(...) ..1 > 5)
#[1] 6

x %>% detect(~.x > 5)
#[1] 6

~自动将函数的每个参数分配给.; .x, .y; 和..1,..2 ..3特殊符号。请注意,只有第一个参数变为..

map2(1, 2, function(x,y) x + y)
#[[1]]
#[1] 3

map2(1, 2, ~.x + .y)
#[[1]]
#[1] 3

map2(1, 2, ~..1 + ..2)
#[[1]]
#[1] 3

map2(1, 2, ~. + ..2)
#[[1]]
#[1] 3

map2(1, 2, ~. + .[2])
#[[1]]
#[1] NA

当有许多变量时,这种自动分配会非常有用。

mtcars %>% pmap_dbl(~ ..1/..4)
# [1] 0.19090909 0.19090909 0.24516129 0.19454545 0.10685714 0.17238095 0.05836735 0.39354839 0.24000000 0.15609756
#[11] 0.14471545 0.09111111 0.09611111 0.08444444 0.05073171 0.04837209 0.06391304 0.49090909 0.58461538 0.52153846
#[21] 0.22164948 0.10333333 0.10133333 0.05428571 0.10971429 0.41363636 0.28571429 0.26902655 0.05984848 0.11257143
#[31] 0.04477612 0.19633028

但除了我上面提到的所有特殊符号之外,参数还分配给.... 就像所有的 R 一样,...有点像参数的命名列表,所以你可以将它与with

mtcars %>% pmap_dbl(~ with(list(...), mpg/hp))
# [1] 0.19090909 0.19090909 0.24516129 0.19454545 0.10685714 0.17238095 0.05836735 0.39354839 0.24000000 0.15609756
#[11] 0.14471545 0.09111111 0.09611111 0.08444444 0.05073171 0.04837209 0.06391304 0.49090909 0.58461538 0.52153846
#[21] 0.22164948 0.10333333 0.10133333 0.05428571 0.10971429 0.41363636 0.28571429 0.26902655 0.05984848 0.11257143
#[31] 0.04477612 0.19633028

另一种思考为什么这样有效的方法是因为data.frames 只是list带有一些行名的 a :

a <- list(a = c(1,2), b = c("A","B"))
a
#$a
#[1] 1 2
#$b
#[1] "A" "B"
attr(a,"row.names") <- as.character(c(1,2))
class(a) <- "data.frame"
a
#  a b
#1 1 A
#2 2 B
于 2020-06-20T16:25:42.640 回答