转置列表列表

Mat*_*erg 17 r

我有一个包含列表条目的列表,我需要转置结构.原始结构是矩形,但子列表中的名称不匹配.

这是一个例子:

ax <- data.frame(a=1,x=2)
ay <- data.frame(a=3,y=4)
bw <- data.frame(b=5,w=6)
bz <- data.frame(b=7,z=8)
before <- list(  a=list(x=ax, y=ay),   b=list(w=bw, z=bz))
Run Code Online (Sandbox Code Playgroud)

我想要的是:

after  <- list(w.x=list(a=ax, b=bw), y.z=list(a=ay, b=bz))
Run Code Online (Sandbox Code Playgroud)

我不关心结果列表的名称(在任何级别).

显然,这可以明确地完成:

after <- list(x.w=list(a=before$a$x, b=before$b$w), y.z=list(a=before$a$y, b=before$b$z))
Run Code Online (Sandbox Code Playgroud)

但这很难看,只适用于2x2结构.这样做的惯用方法是什么?

Vic*_* K. 19

下面的代码将创建一个列表,其中包含每个列表的第i个元素before:

lapply(before, "[[", i)
Run Code Online (Sandbox Code Playgroud)

现在你必须这样做

n <- length(before[[1]]) # assuming all lists in before have the same length
lapply(1:n, function(i) lapply(before, "[[", i))
Run Code Online (Sandbox Code Playgroud)

它应该给你你想要的东西.它效率不高(每次列表多次传输),你可以通过保持指向当前列表元素的指针来提高效率,所以请确定这对你来说是否足够好.

  • 我会将 `1:n` 替换为 `seq_along(before[[1]])`,但除此之外,这也可以正常工作。列表可能并不总是 2x2,但它们不会很大(但是数据框很大)。 (2认同)
  • 那,如果长度为0,它不会返回错误的结果. (2认同)

ali*_*ire 9

purrr软件包现在使这个过程非常简单:

library(purrr)

before %>% transpose()

## $x
## $x$a
##   a x
## 1 1 2
## 
## $x$b
##   b w
## 1 5 6
## 
## 
## $y
## $y$a
##   a y
## 1 3 4
## 
## $y$b
##   b z
## 1 7 8
Run Code Online (Sandbox Code Playgroud)


edd*_*ddi 5

这是一个不同的想法 - 使用data.table可以存储data.frame的事实(事实上,考虑到你的问题,也许你甚至不需要使用列表列表,只能使用它们data.table):

library(data.table)

dt = as.data.table(before)
after = as.list(data.table(t(dt)))
Run Code Online (Sandbox Code Playgroud)

  • 这实际上并不需要data.table`as.list(data.frame(do.call(rbind,before)))`也可以. (5认同)