将具有相同结构的列表元素合并

4

我有一个列表,其中包含具有相同结构的内部列表,在我的情况下,它们是字符向量。现在我想要通过一个函数(在这种情况下仅为c)将这些内部列表组合成一个列表。一个最简示例:

list(
  list(one = "a", 
       two = "b", 
       three = "c"), 
  list(one = "d", 
       two = c("e", "f"), 
       three = "g")
  )

我想要的输出:

list(
  one = c("a", "d"),
  two = c("b", "e", "f"),
  three = c("c", "g")
)

我搜索了很长时间,有类似的问题,但是我没有找到完全符合我需求的答案。我也觉得对于类似问题的回答相当复杂。不要误解我的意思,当然,解决这个问题并不是什么大问题,但我无法想象没有真正优雅的方法或者一行代码能够实现这个。最好使用 tidyverse 语法。

3个回答

5

取消列表的一级,堆栈和解除堆栈:

unstack(stack(unlist(l, recursive = FALSE)))
# $one
# [1] "a" "d"
# 
# $two
# [1] "b" "e" "f"
# 
# $three
# [1] "c" "g"

unstack(stack(unlist(l, FALSE))) - Onyambu
这个方法通过了所有的测试用例!!+1。而且不需要分割,只需将df解除堆叠即可。 - Onyambu
@onyambu 谢谢编辑,不知怎么的我总是忘记了 unstack 的存在... - zx8754

3

在基本的 R 中,您可以使用 do.callMap。在列表中,do.call 尤其有用,可以按索引将函数应用于每个元素(例如检查 do.call(\(x, y) x + y, list(c(7, 9, 2), c(6, 2, 8))))。由于这是一个列表的列表,因此必须在顶部使用一个 apply* 函数(如 Map,它需要两个参数)来实现连接。这要求列表是对称的:

l <- list(
  list(one = "a", 
       two = "b", 
       three = "c"), 
  list(one = "d", 
       two = c("e", "f"), 
       three = "g")
)

do.call(Map, c(c, l))

# $one
# [1] "a" "d"
# 
# $two
# [1] "b" "e" "f"
# 
# $three
# [1] "c" "g"

在 tidyverse 语言中,可以使用 exec 来完成此操作:
library(purrr)
exec(Map, !!!c(c, l))

1
很好,非常感谢!你能稍微解释一下吗? - TobiSonne
2
这是一个很好的答案,但不幸的是,当列表在所有元素上不对称时,它会失败。例如,假设第二个列表中没有“two”,那么该方法就会失败。我更愿意建议使用“map(transpose(l), unlist)”。 - Onyambu

3

这里是另一种方法,使用首先使用transpose,然后使用map包装的unlist

library(purrr)

map(transpose(l), unlist)

输出:

$one
[1] "a" "d"

$two
[1] "b" "e" "f"

$three
[1] "c" "g"

1
太好了,太好了,太好了!到目前为止,这是我最喜欢的!:) 非常感谢你! - TobiSonne

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