首页 > 解决方案 > R基础管道进入`do.call`

问题描述

假设我有一个myList由一些data.frame对象组成的列表 ( ),并且我想使用方法将列表中的所有元素折叠成一个data.frame结构:rbinddo.call

set.seed(123)
myList <- list(
    a = data.frame(
        h1 = rnorm(5),
        h2 = rnorm(5)
    ),
    b = data.frame(
        h1 = rnorm(5),
        h2 = rnorm(5)
    )
)

使用magrittr' 的管道运算符 ( %>%),您可以执行以下操作,其中do.call( args) 中的第二个参数是由 a 表示的 lhs 表达式.

myList %>% do.call("rbind", .)

但是使用新的基础管道 ( |>) 会导致执行相同操作时出错:

myList |> do.call("rbind", .)
#> Error in do.call(myList, "rbind", .) : 
#>  second argument must be a list

将这个(和其他类似操作)管道到 R 的新基础管道运算符的正确方法是什么,其中 lhs 表达式不一定是方法中的第一个参数?

标签: r

解决方案


1) 命名参数 |>总是插入到第一个参数中并且不支持 dot 但这有效:

myList |> do.call(what = "rbind")

2)匿名函数调用虽然有点冗长,但这也有效:

myList |> (\(args) do.call("rbind", args))()

2a) 命名函数或像 do.call 一样定义 Do.call 但交换了前两个参数:

Do.call <- \(args, what, ...) do.call(what, args, ...)
myList |> Do.call("rbind")

2b)或定义一个接受第二个参数、函数以及第一个和剩余参数的函数。

Swap <- \(x, fun, y, ...) fun(y, x, ...)
myList |> Swap(do.call, "rbind")

3) myList 结构已知如果您知道 myList 恰好有两个组件并且它们被命名为 a 和 b 那么这也可以工作:

myList |> with(rbind(a, b))

4) 管道替代品当然,没有什么可以阻止继续使用 magrittr 管道。也可以使用Bizarro pipe,它不是真正的管道,但看起来像一个,只需要基础 R 即可:

myList ->.;
  do.call("rbind", .)

5) rbind Alternatives使用 dplyr 中的 bind_rows 或 data.table 中的 rbindlist 代替使用 rbind:

library(dplyr)
myList |> bind_rows()

library(data.table)
myList |> rbindlist()

6) do.call Alternatives 使用reduce from purrr 而不是do.call,至少在这个例子中是有效的。

library(purrr)
myList |> reduce(rbind)

推荐阅读