【问题标题】:Pipe result to multiple parameters (with R 4.1+)管道结果到多个参数(使用 R 4.1+)
【发布时间】:2021-09-05 07:37:06
【问题描述】:

使用magrittr pipe (%>%),我偶尔会将结果传递给多个参数,例如

ds <- 
  datasets::airquality |> 
  head() 

ds %>%
  # ds |> 
  knitr::kable(
    x           = .,
    col.names   = tolower(colnames(.)),
    format      = "markdown"
  )

结果

| ozone| solar.r| wind| temp| month| day|
|-----:|-------:|----:|----:|-----:|---:|
|    41|     190|  7.4|   67|     5|   1|
|    36|     118|  8.0|   72|     5|   2|
|    12|     149| 12.6|   74|     5|   3|
|    18|     313| 11.5|   62|     5|   4|
|    NA|      NA| 14.3|   56|     5|   5|
|    28|      NA| 14.9|   66|     5|   6|

但是R's new native pipe (|&gt;, introduced in 4.1.0) 不支持这个。将 %&gt;% 替换为 |&gt; 会引发此错误:

Error in knitr::kable(head(datasets::airquality), x = ., col.names = tolower(colnames(.)),  : 
  object '.' not found

release notes中的描述(我的重点):

R 现在提供简单的本机正向管道语法 |>。前向管道的简单形式在右侧调用中插入左侧作为第一个参数。作为语法转换的管道实现是由 Jim Hester 和 Lionel Henry 的建议推动的。

除了定义一个新的(匿名或显式)函数来包装下面提出的 rhs(右侧)函数之外,还有其他方法使用|&gt;吗?

【问题讨论】:

标签: r pipe


【解决方案1】:

Jumping Rivers 的博客描述了如何使用匿名函数和新的本地管道 (a) 将值传递给不是第一个参数的参数,以及 (b) 将值传递给多个参数。对于上面的问题:

ds |>
  {\(x) 
    knitr::kable(
      x           = x,
      col.names   = tolower(colnames(x)),
      format      = "markdown"
    )
  }()                                      # Don't forget the parentheses.

这利用了R 4.1.0 release 功能。

R 现在提供了用于创建函数的简写符号,例如(x) x + 1 被解析为函数(x) x + 1。

这比明确定义函数要简单一些

kable2 <- function (x) {
  knitr::kable(
    x           = x,
    col.names   = tolower(colnames(x)),
    format      = "markdown"
  )
}

ds |>
  kable2()

注意:如果您收到以下错误,您可能在定义匿名函数后忘记了()ie,左右括号)。

错误:管道的 RHS 调用不支持函数“{”

【讨论】:

  • 如果您想更接近原始语法,可以使用\(.) 吗?
  • 哦,是的,这确实有效,而且更相似。你觉得对其他人来说更直观的是什么?
【解决方案2】:

正如 Keith McNulty 在最近的 Medium post 中所解释的, 用于 ”。”新的 R 本机管道中的引用已被删除。相反,您必须按照您的建议使用中间函数,但也要利用 原生 |&gt; 管道进入第一个 unnamed 参数。

所以,如果你没有使用 col.names 参数,

library(dplyr)
ds <- datasets::airquality |> head()

ds %>%
  knitr::kable(
    x           = .,
    format      = "markdown"
  )

可以替换为

ds |>
  knitr::kable(
    format      = "markdown"
  )

因为xkable 的第一个未命名参数

处理第二个“.”参考,您可以先使用一个函数(在这种情况下为dplyr::rename_with

ds |> 
  dplyr::rename_with(tolower) |>
  knitr::kable(
    format      = "markdown"
  )
| ozone | solar.r | wind | temp | month | day |
|------:|--------:|-----:|-----:|------:|----:|
|    41 |     190 |  7.4 |   67 |     5 |   1 |
|    36 |     118 |  8.0 |   72 |     5 |   2 |
|    12 |     149 | 12.6 |   74 |     5 |   3 |
|    18 |     313 | 11.5 |   62 |     5 |   4 |
|    NA |      NA | 14.3 |   56 |     5 |   5 |
|    28 |      NA | 14.9 |   66 |     5 |   6 |

reprex package (v2.0.0) 于 2021 年 6 月 29 日创建

【讨论】:

  • 感谢您指出一些转换可能最好放在kable() 之前(或任何需要管道两个输出的函数)。作为记录,实际的列重命名功能比我的示例要复杂一些;我使用了tolower(),因为它比gsub("_", " ", colnames(.))更容易理解
猜你喜欢
  • 2017-10-08
  • 1970-01-01
  • 2020-04-03
  • 2017-06-11
  • 2018-10-08
  • 2016-09-21
  • 1970-01-01
  • 2016-07-25
相关资源
最近更新 更多