简体   繁体   English

如何将数据框的行绑定到列表列表中的单独元素中

[英]How to bind rows of dataframes in separate elements within a list of lists

Let's suppose I have a list of lists as follows: 假设我有一个列表列表,如下所示:

set.seed(111)
lst_1 = rep(list(list()), 3) 

lst_1[[1]] = list(data.frame(rnorm(5)), data.frame(rnorm(5)))
lst_1[[2]] = list(data.frame(rnorm(5)), data.frame(rnorm(5)))
lst_1[[3]] = list(data.frame(rnorm(5)), data.frame(rnorm(5)))

where each list element (1, 2 and 3) is a list which contains two data.frames. 其中每个列表元素(1、2和3)是一个包含两个data.frames的列表。

How can I sequentially bind the rows of the first data.frame within each (sub)list? 如何依次绑定每个(子)列表中第一个data.frame的行? ie lst_1[[1]][[1]] + lst_1[[2]][[1]] + lst_1[[3]][[1]] , and eventually do the same for the second data.frame ? lst_1[[1]][[1]] + lst_1[[2]][[1]] + lst_1[[3]][[1]] ,最后对第二个data.frame做同样的data.frame

Here is my desired output, which is achieved manually with a for loop, however my real list of lists is much larger: 这是我想要的输出,这是通过for循环手动实现的,但是我真正的列表列表要大得多:

lst_out = rep(list(list()), 2) 

for (i in 1:2) {
lst_out[[i]] = rbind(lst_1[[1]][[i]], lst_1[[2]][[i]], lst_1[[3]][[i]])
}

If I'm interpreting correctly, the base R solution should be pretty straight forward. 如果我的解释正确,那么基本的R解决方案应该很简单。 Map the rbind function over each part of the 3 inputs in lst_1 : rbind函数Maplst_1 3个输入的每个部分上:

do.call(Map, c(rbind, lst_1))

This is a slightly obscured way of calling the expanded Map line of: 这是调用扩展的Map行的一种稍微模糊的方法:

Map(rbind, lst_1[[1]], lst_1[[2]], lst_1[[3]])

Which starts to look a lot like your original for loop, and gives the same result as doing it via do.call : 它开始看起来很像您的原始for循环,并提供与通过do.call进行操作相同的结果:

identical(
  do.call(Map, c(rbind, lst_1)),
  Map(rbind, lst_1[[1]], lst_1[[2]], lst_1[[3]])
)
#[1] TRUE

Checks out with the intended result too: 也检查出预期的结果:

identical(lst_out, do.call(Map, c(rbind, lst_1)))
#[1] TRUE

I think the simplest way is to simply purrr::transpose the list, so that instead of three sublists with two dataframe elements, you have two sublists with three dataframe elements. 我认为最简单的方法是简单地purrr::transpose列表,这样就不用三个带有两个dataframe元素的子列表,而是两个带有三个dataframe元素的子列表。 This means that the dataframes to bind are all in the same sublist, so iteration is much simpler and we can map over the main list. 这意味着要绑定的数据帧都在同一个子列表中,因此迭代要简单得多,我们可以map到主列表上。 See below, noting that you can just load purrr as dplyr::bind_rows is just a bit faster and tibble::glimpse is for printing only. 见下文,并指出,你可以加载purrr作为dplyr::bind_rows只是快一点和tibble::glimpse仅用于打印。

library(tidyverse)
set.seed(111)
lst_1 = rep(list(list()), 3) 

lst_1[[1]] = list(data.frame(rnorm(5)), data.frame(rnorm(5)))
lst_1[[2]] = list(data.frame(rnorm(5)), data.frame(rnorm(5)))
lst_1[[3]] = list(data.frame(rnorm(5)), data.frame(rnorm(5)))

lst_1 %>%
  transpose %>%
  map(bind_rows) %>%
  glimpse
#> List of 2
#>  $ :'data.frame':    15 obs. of  1 variable:
#>   ..$ rnorm.5.: num [1:15] 0.235 -0.331 -0.312 -2.302 -0.171 ...
#>  $ :'data.frame':    15 obs. of  1 variable:
#>   ..$ rnorm.5.: num [1:15] 0.14 -1.497 -1.01 -0.948 -0.494 ...

Created on 2019-04-20 by the reprex package (v0.2.1) reprex软件包 (v0.2.1)创建于2019-04-20

Base R solution 基础R解决方案

set.seed(111)
lst_1 <- rep(list(list()), 3) 

lst_1[[1]] <- list(data.frame(rnorm(5)), data.frame(rnorm(5)))
lst_1[[2]] <- list(data.frame(rnorm(5)), data.frame(rnorm(5)))
lst_1[[3]] <- list(data.frame(rnorm(5)), data.frame(rnorm(5)))

lst_out_2 <- list()

for (i in 1:2) { 
  lst_out_2[[i]] <- do.call('rbind', sapply(lst_1, `[`, i))
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM