在R中折叠列表

3

假设我有一个列表

lst <- list(c("A1", "A1", "A1", "A1", "A1", "A1"), 
            c("", "R1", "R2", "R2", "R2", "R2"),
            c("", "", "", "U1", "U2", "U3"))

输出结果在哪里

[[1]]
[1] "A1" "A1" "A1" "A1" "A1" "A1"

[[2]]
[1] ""   "R1" "R2" "R2" "R2" "R2"

[[3]]
[1] ""   ""   ""   "U1" "U2" "U3"

现在,我希望有一个单一的向量,其中元素按以下方式组合。
out <- paste0(lst[[1]], lst[[2]], lst[[3]])

输出结果将会是什么?
[1] "A1"     "A1R1"   "A1R2"   "A1R2U1" "A1R2U2" "A1R2U3"

我该如何更加动态地完成这个任务(例如,对于更长/更短的列表)?我尝试使用sapply等方法,但都没有成功。

2个回答

4

您可以只用以下方式来完成此操作:

do.call("paste0", lst)
# [1] "A1"     "A1R1"   "A1R2"   "A1R2U1" "A1R2U2" "A1R2U3"

这将lst的所有列作为参数传递给paste0,因此它基本上就像执行:

paste0(list[[1]], list[[2]], list[[3]])

但无论 lst 中有多少个向量,它都能正常工作。

在基本的R语言中,do.call() 是我们最接近 Python "splat" 类操作符的方法。而 rlang 包则引入了三个感叹号的操作符,提供了另一种选择。但你必须显式地构建表达式并进行求值。

library(rlang)
eval_tidy(expr(paste0(!!!lst)))
# [1] "A1"     "A1R1"   "A1R2"   "A1R2U1" "A1R2U2" "A1R2U3"

很棒,需要研究一下 do.call。我承认我是从 Python 转过来的。一旦可能,我会接受答案的,谢谢。 - Jan
2
@Jan 可能有些额外的上下文信息会有帮助:do.call("rbind",list_of_data_frames) 可能是最常见的 do.call 用法。dplyrdata.table 都有专门(快速)的函数来实现这个特定的目的。如果你想尝试超越基本的 R,一些人会使用 purrr::pmap 来处理这种需要将函数映射到多个输入的任务。 - joran
@joran:谢谢@joran。首先,我想了解基本的R语言,未来逐步提高水平。有时候R的语法很奇怪(至少对我来说是这样)。如果您愿意,可以使用purrr发布答案,我会很高兴地点赞。 - Jan
2
@Jan 也可以看看 do.call 的好朋友 Reduce(paste0, lst)。我相信在 Python 中存在一个名字/行为几乎相同的函数,不过已经有一段时间了。 - lmo

1

为了补充MrFlick的答案,tidyverse风格的答案使用purrr::pmap

pmap_chr(lst, paste0)
# [1] "A1"     "A1R1"   "A1R2"   "A1R2U1" "A1R2U2" "A1R2U3"

这里使用的是一种变体的pmap(并行映射),它明确地返回一个字符向量。原始版本pmap(lst, paste0)返回一个与lst长度相同的列表,其中每个元素都是对paste0调用的输出。
[[1]]
[1] "A1"

[[2]]
[1] "A1R1"

[[3]]
[1] "A1R2"

[[4]]
[1] "A1R2U1"

[[5]]
[1] "A1R2U2"

[[6]]
[1] "A1R2U3"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接