【问题标题】:%>% .$column_name equivalent for R base pipe |>%>% .$column_name 等效于 R 基管道 |>
【发布时间】:2021-08-20 07:17:27
【问题描述】:

我经常使用 dplyr 管道将列从 tibble 转换为向量,如下所示

iris %>% .$Sepal.Length
iris %>% .$Sepal.Length %>% cut(5)

如何使用最新的 R 内置管道符号 |> 来做同样的事情

iris |> .$Sepal.Length
iris |> .$Sepal.Length |>  cut(5)
Error: function '$' not supported in RHS call of a pipe

【问题讨论】:

  • 为什么使用iris %>% .$Sepal.Length 而不是iris$Sepal.Length ?...
  • cut(iris$Sepal.Length, 5)
  • @Cath 实际链条要长得多。所以在得到向量之后,我还想用它做更多的事情,比如把它用作cut()的输入等等
  • 请提供“更长的链”以更好地表示问题。
  • @zx8754 在这个问题的上下文中真的不相关。

标签: r dataframe dplyr


【解决方案1】:

我们可以使用getElement()

iris |> getElement('Sepal.Length') |> cut(5)

【讨论】:

  • 谢谢,我也喜欢这个答案,这是迄今为止最简洁的。我等了一会儿,看看是否还有其他答案。再次感谢
  • iris |> with(Sepal.Length)
【解决方案2】:

在基础管道中,没有为管道中传递的数据提供占位符。这是magrittr 管道和基础 R 管道之间的区别之一。您可以使用匿名函数来访问该对象。

iris |> {\(x) x$Sepal.Length}()

【讨论】:

  • 我明白了,这比我预期的要长,但很高兴知道。谢谢@Ronak
  • Iswrapping in parethesis iris |> ((x) x$Sepal.Length)() |> cut(5) 这样和使用{}一样吗?
  • 我没有使用过这样的括号,但我认为它的工作方式相同。
  • @jpdugo17 唯一的区别是{} 可以包含多个表达式(由换行符或; 分隔),并且它保留了值的自动打印可见性。 …当然它使用视觉上不同的分隔符,这可以使嵌套表达式(如本例)更具可读性。
【解决方案3】:

$|>中的直接用法目前是disabled。也许一个原因可能是写作

iris$Sepal.Length

而不是

library(magrittr)
iris %>% .$Sepal.Length

如果仍然需要调用$(或|>中的其他禁用函数),除了创建函数之外,还有一个选项,类似于@jay-sf的解决方案,使用$ via函数::base::`$` 或将其置于刹车($)

iris |> (`$`)("Sepal.Length") |> cut(5)
iris |> base::`$`("Sepal.Length") |> cut(5)

#iris |> base::`[[`("Sepal.Length") |> cut(5) #Alternative
#iris |> base::`[`(,"Sepal.Length") |> cut(5) #Alternative

也可以使用当前需要激活的PIPEBIND。这允许在基管中有一个占位符。

Sys.setenv(`_R_USE_PIPEBIND_` = TRUE)
iris |> . => (`$`)(., "Sepal.Length") |> cut(5)

另一种选择是使用 bizarro 管道 ->.;。有人称它为joke 其他人clever use of existing syntax

iris ->.; .$Sepal.Length |> cut(5)

这会在.GlobalEnv 中创建或覆盖.rm(.) 可以用来删除它。或者,它可以在local 中处理:

local({iris ->.; .$Sepal.Length |> cut(5)})

在这种情况下,它会在 iris. 环境中生成两个相同的对象,但只要它们未修改它们指向相同的地址。

tracemem(iris)
#[1] "<0x556871bab148>"
tracemem(.)
#[1] "<0x556871bab148>"

【讨论】:

  • 澄清一下,现在我们在环境中有两个相同的对象iris.
  • 好极了,但 Bizzarro Pipe 文章指出,虽然这可行,但它只是一个“笑话”,不应在实践中使用。
  • @tpetzoldt 至少 g-grothendieck 将其描述为 clever use of existing syntax
  • @zx8754 感谢您的评论。我补充说,这些对象只要不被修改就指向同一个地址
  • @GKi “聪明”≠“好”。我希望没有人实际上建议在实践中使用它。
【解决方案4】:

有趣的例子和很好的答案,让我添加另一个版本:在这种情况下,我通常使用select然后unlist。这遵循“speaking R”范式,并且与运算符%&gt;%|&gt; 的工作方式相同:

library("dplyr")
iris %>% select(Sepal.Length) %>% unlist() %>% cut(5)

iris |> select(Sepal.Length) |> unlist() |> cut(5)

请注意,select 来自 dplyr,而从 @jpdugo17 引入的pull 更好。

如果我们使用通常的“base R”索引,它也很短并且适用于两个世界:

iris[["Sepal.Length"]] |> cut(5)

iris$Sepal.Length |> cut(5)

感谢@zx8754 的评论,当然也可以在没有任何管道的情况下使用base R

cut(iris$Sepal.Length, 5)

...但我认为 OP 只是想指出管道的差异。我猜它是在更大的背景下应用的,iris 只是一个例子。

【讨论】:

  • iris |> subset(TRUE, Sepal.Length) |> unlist() |> cut(5) 在保留在基础 R 中时也能做到这一点。
  • 嗯。老实说,我看不到 select(…) |&gt; unlist() 成语的好处。它比使用with(…)pull(…) 更详细。我错过了什么?
  • @KonradRudolph 以防万一,无论出于何种原因,只有基本功能可用。而且因为 tidyverse 已经有了 magrittr 的管道,所以在我看来它更好也更受欢迎。
  • @jpdugo17 那么在这种情况下使用with
  • with 当然可以,但据我了解 OP,这个问题的主要动机是探索 %&gt;%|&gt; 之间的差异。我个人的印象是,这对于将来如何使用管道有更多的了解是非常必要的。
【解决方案5】:

这也是一种选择:

iris |> dplyr::pull(Sepal.Length) |> cut(5)

编辑:

我想知道为什么不允许使用反引号调用函数。

iris |> `[`(, 'Sepal.Length')
#>Error: function '[' not supported in RHS call of a pipe 

正如@Hugh 所指出的,反引号是允许的,但有些函数是不允许的。

这是从wch Github提取的黑名单函数列表

"if", "while", "repeat", "for", "break", "next", "return", "function",
"(", "{",
"+", "-", "*", "/", "^", "%%", "%/%", "%*%", ":", "::", ":::", "?", "|>",
"~", "@", "=>",
"==", "!=", "<", ">", "<=", ">=",
"&", "|", "&&", "||", "!",
"<-", "<<-", "=",
"$", "[", "[[",
"$<-", "[<-", "[[<-",
0

【讨论】:

  • 如果我们可以从 dplyr 使用 pull 为什么不使用管道呢?该问题表明仅在 baseR 中工作的案例
  • @jpdugo17 感谢您的回答,我也可以看到自己使用此解决方案,因为我想避免经常使用'...'。但我认为getElement() 解决方案更接近纯baseR 解决方案。再次感谢
  • 被列入黑名单的不是反引号,而是[ 运算符。您可以在 names.c 中看到黑名单:github.com/wch/r-source/blob/…
  • @Hugh 管道代码禁止使用这些名称的事实令人难以置信,而且似乎没有任何充分的理由。
  • @KonradRudolph 有充分的理由,但很难解释。请参阅邮件列表中 Luke 的讨论
【解决方案6】:

我知道这个问题已经结束。我们使用符号名称而不是字符名称的其他 Base R 解决方案可能包括:

 iris |>
    with(Sepal.Length)


 iris |>
    subset(select = Sepal.Length)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-07
    • 1970-01-01
    • 1970-01-01
    • 2021-03-27
    • 2016-06-26
    • 2017-04-11
    • 1970-01-01
    • 2017-03-07
    相关资源
    最近更新 更多