R管道(%>%)不能与复制功能

时间:2017-04-07 16:15:04

标签: r pipe magrittr

我正在尝试学习管道功能(%>%) 当试图从这行代码转换到另一行时,它不起作用。

---- R代码 - 原始版本-----

set.seed(1014)
replicate(6,sample(1:8))
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    3    7    4    5    1
[2,]    2    8    4    2    4    2
[3,]    5    4    8    5    8    5
[4,]    3    1    2    1    1    7
[5,]    4    6    3    7    7    3
[6,]    6    5    1    3    3    8
[7,]    8    7    5    8    6    6
[8,]    7    2    6    6    2    4

---- R代码 - 用管道重新编码----

> sample(1:8) %>%  replicate(6,.)
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    7    7    7    7    7    7
[2,]    3    3    3    3    3    3
[3,]    2    2    2    2    2    2
[4,]    1    1    1    1    1    1
[5,]    5    5    5    5    5    5
[6,]    4    4    4    4    4    4
[7,]    8    8    8    8    8    8
[8,]    6    6    6    6    6    6

请注意,使用烟斗时,取样不起作用 相同的矢量。

1 个答案:

答案 0 :(得分:19)

这是可以预料的。复制需要一个表达式,但是当使用管道运算符时,您只需将调用结果粘贴到sample()replicate。所以你获得相同结果的6倍。

您必须使用quote()将表达式传递给复制而不是结果,但您不应忘记评估该表达式的每个重复。

quote(sample(c(1:10,-99),6,rep=TRUE)) %>% 
  replicate(6, .) %>%
  sapply(eval)

给出:

    [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    5    2   10   10    9    2
[2,]    4    3    1    3  -99    1
[3,]   10    2    3    8    2    4
[4,]  -99    1    6    2   10    3
[5,]    8  -99    1    9    4    6
[6,]    4   10    8    1  -99    8

这里会发生什么:

  • 管道发送和表达复制而不进行评估。
  • 复制复制该表达式并返回一个列表,其中包含该表达式的6倍但未对其进行评估。
  • sapply(eval)遍历列表并执行该列表中的每个表达式。

在您之前的问题中(即使用data.frame时),您可以完成例如:

quote(sample(c(1:10,-99),6,rep=TRUE)) %>% 
  replicate(6, .) %>%
  data.frame

现在函数data.frame将强制执行表达式,但最终还是会出现可怕的变量名,即表达式本身。

如果您想了解有关这些问题的更多信息,您将不得不深入了解所谓的“延迟评估”以及管道运营商如何处理这一问题。但老实说,在这种情况下,我真的看不到使用管道操作员的任何好处。它更具可读性。

根据Frank的评论:您可以使用管道和函数嵌套的混合来避免sapply。但为此,您必须在代码块中包含嵌套函数,否则管道操作符将无法正确处理它:

quote(sample(c(1:10,-99),6,rep=TRUE)) %>% {
  replicate(6, eval(.)) }

非常有趣,但imho不是很有用......