【问题标题】:how to feed the result of a pipe chain (magrittr) to an object如何将管道链(magrittr)的结果提供给对象
【发布时间】:2014-11-16 12:32:06
【问题描述】:

这是一个相当简单的问题。但是我找不到每个 google/stackexchange 的答案并查看 magrittr 的文档。 您如何提供通过 %>% 连接的函数链的结果以创建向量?

我看到大多数人的做法是:

a <-
data.frame( x = c(1:3), y = (4:6)) %>%
sum()

但也有一个解决方案,我可以将结果通过管道链接到一个对象,可能是别名或类似的东西,有点像这样:

data.frame( x = c(1:3), y = (4:6)) %>%
sum() %>%
a <- ()

这将有助于将所有代码保持在相同的逻辑中,将结果向前“向下传递”。

【问题讨论】:

    标签: r magrittr


    【解决方案1】:

    试试这个:

    data.frame( x = c(1:3), y = (4:6)) %>% sum -> a
    

    【讨论】:

    • +1 我从没想过-&gt; 会有理由。现在有了!
    • 但是如果你只使用-&gt;,你就不能继续使用链:例如data.frame( x = c(1:3), y = (4:6)) %&gt;% sum -&gt; a %&gt;% exp给出一个错误,你将不得不使用括号(data.frame( x = c(1:3), y = (4:6)) %&gt;% sum -&gt; a) %&gt;% (exp),如果一个不小心这可能会导致意想不到的结果。
    • G. Grothendieck,我已经尝试过上面的代码(data.frame( x = c(1:3), y = (4:6)) %&gt;% (sum -&gt; a) %&gt;% exp),但它没有正确地将部分结果分配给a
    • (1) 继续链条不是一个好主意。如果你真的想通过它更好地分配一个变量,使其成为两个链。仍然可以这样写:data.frame( x = c(1:3), y = (4:6)) %&gt;% sum -&gt; a; a %&gt;% exp 以避免该问题。 (2) 部分赋值是副作用,函数式风格是为了避免副作用。
    • 怎么样:tee=function(v,n){assign(n,v,.GlobalEnv);v} 然后d %&gt;% whatever %&gt;% tee("part1") %&gt;% otherstuff $&gt;$ tee("part2") %&gt;% etcetc
    【解决方案2】:

    你可以这样做:

    data.frame( x = c(1:3), y = (4:6)) %>%  
    sum %>%  
    assign(x="a",value=.,pos=1)  
    

    有几点需要注意:

    您可以使用“。”告诉magrittr 被提出的对象属于哪个参数。默认情况下它是第一个,但这里我使用. 表示我希望它在第二个value 参数中。

    其次,我必须使用 pos=1 参数在全局环境中进行分配。

    【讨论】:

    • 您真的不应该将 assign 用于任何事情。这是不好的编码习惯。
    • @iShouldUseAName 你能扩展一下吗?这里有什么危险?
    【解决方案3】:

    您也可以使用&lt;&lt;- 运算符:

    data.frame( x = c(1:3), y = (4:6)) %>%
      sum() %>%
      `<<-`(a,.)
    

    编辑:我认为 John Paul 的建议是最安全的建议,您可以继续使用链对部分结果进行不同的分配。例如:

    data.frame( x = c(1:3), y = (4:6)) %>%  
      sum %>%  
      assign(x="a",value=., pos=1)  %>% 
      exp %>%
      assign(x="b",value=., pos=1) %>% 
      sqrt %>%
      assign(x="c", value=., pos=1)
    

    这将正确创建abc

    【讨论】:

    • 您确定它不适用于 &lt;- 吗?如果没有严格要求,最好不要使用&lt;&lt;-
    • @CarlWitthoft,不会的,&lt;- 运算符将分配给函数的本地环境,因此它不会在全局环境中创建变量。
    【解决方案4】:

    使用 pipeR 的 %&gt;&gt;% 这应该很容易。

    library(pipeR)
    data.frame( x = c(1:3), y = (4:6)) %>>%
      sum %>>%
      (~ a)
    

    pipeR 教程可能会有所帮助:http://renkun.me/pipeR-tutorial/ 分配:http://renkun.me/pipeR-tutorial/Pipe-operator/Pipe-with-assignment.html

    【讨论】:

      【解决方案5】:

      我喜欢做的(我在不记得的地方发现了这个技巧)是在我的管道链末端使用{.} -&gt; obj。这样,我只需插入一个新行就可以在链的末尾添加额外的步骤,而不必重新定位到 -&gt; 赋值运算符。

      您也可以使用(.) 而不是{.},但它看起来有点,奇怪

      例如,而不是这个:

        iris %>% 
          ddply(.(Species), summarise, 
                mean.petal = mean(Petal.Length),
                mean.sepal = mean(Sepal.Length)) -> summary
      

      这样做:

      iris %>% 
          ddply(.(Species), summarise, 
                mean.petal = mean(Petal.Length),
                mean.sepal = mean(Sepal.Length)) %>% 
          {.} -> summary
      

      它使您可以更轻松地查看管道数据的最终位置。此外,虽然看起来没什么大不了的,但添加另一个最后一步会更容易,因为您不需要将 -&gt; 移动到新行,只需在 {.} 之前添加新行并添加步骤。

      像这样:

      iris %>% 
          ddply(.(Species), summarise, 
                mean.petal = mean(Petal.Length),
                mean.sepal = mean(Sepal.Length)) %>% 
          arrange(desc(mean.petal)) %>%   # just add a step here
          {.} -> summary
      

      但这无助于保存中间结果。 John Paul 对使用 assign() 的回答很好,但打字有点长。您需要使用.,因为数据不是第一个参数,您必须将新参数的名称放在"" 中,并指定环境(pos = 1)。我似乎很懒惰,但使用%&gt;% 是关于速度

      所以我将assign() 包裹在一个小函数中,这会加快一点速度:

      keep <- function(x, name) {assign(as.character(substitute(name)), x, pos = 1)}
      

      所以现在你可以这样做了:

        keep <- function(x, name) {assign(as.character(substitute(name)), x, pos = 1)}
      
        iris %>% 
          ddply(.(Species), summarise, 
                mean.petal = mean(Petal.Length),
                mean.sepal = mean(Sepal.Length)) %>% keep(unsorted.data) %>% # keep this step
          arrange(mean.petal) %>%
          {.} -> sorted.data
      
      sorted.data
      #     Species mean.petal mean.sepal
      #1     setosa      1.462      5.006
      #2 versicolor      4.260      5.936
      #3  virginica      5.552      6.588
      
      unsorted.data
      #     Species mean.petal mean.sepal
      #1     setosa      1.462      5.006
      #2 versicolor      4.260      5.936
      #3  virginica      5.552      6.588
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-02
        • 1970-01-01
        • 2019-02-18
        • 1970-01-01
        • 1970-01-01
        • 2016-08-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多