R列表到dataframe

我有一个嵌套的数据列表。 它的长度是132,每个项目是一个长度为20的列表。是否有一个快速的方法来将这个结构转换成一个有132行和20列数据的数据框?

我是R新手,所以我想这可能是一个简单的方法。 我在这里search堆栈溢出,找不到类似的问题,所以我很抱歉,如果我错过了。 一些示例数据:

l <- replicate( 132, list(sample(letters, 20)), simplify = FALSE ) 

假设你的列表被称为l

 df <- data.frame(matrix(unlist(l), nrow=132, byrow=T)) 

上面的代码将所有的字符列转换为因素,为了避免这个问题,你可以在data.frame()调用中添加一个参数:

 df <- data.frame(matrix(unlist(l), nrow=132, byrow=T),stringsAsFactors=FALSE) 

rbind

 do.call(rbind.data.frame, your_list) 

编辑:以前的版本返回listdata.frame而不是vector(@IanSudbery在评论中指出)。

你可以使用plyr包。 例如表单的嵌套列表

 l <- list(a = list(var.1 = 1, var.2 = 2, var.3 = 3) , b = list(var.1 = 4, var.2 = 5, var.3 = 6) , c = list(var.1 = 7, var.2 = 8, var.3 = 9) , d = list(var.1 = 10, var.2 = 11, var.3 = 12) ) 

现在有4的长度和l中的每个列表包含长度3的另一个列表。现在你可以运行

  library (plyr) df <- ldply (l, data.frame) 

并应该得到与答案@Marek和@nico相同的结果。

data.frame(t(sapply(mylistlist,c)))

sapply将其转换为matrix。 data.frame将matrix转换为dataframe。

假设你的列表被称为L

 data.frame(Reduce(rbind, L)) 

data.table具有函数rbindlist ,它是do.call(rbind, list(...))的超快实现。

它可以listsdata.framesdata.tables作为input。

 library(data.table) ll <- list(a = list(var.1 = 1, var.2 = 2, var.3 = 3) , b = list(var.1 = 4, var.2 = 5, var.3 = 6) , c = list(var.1 = 7, var.2 = 8, var.3 = 9) , d = list(var.1 = 10, var.2 = 11, var.3 = 12) ) DT <- rbindlist(ll) 

这将返回一个data.tableinheritance自data.frame

如果你真的想要转换回data.frame使用as.data.frame(DT)

Reshape2的输出与上面的plyr例子相同:

 library(reshape2) l <- list(a = list(var.1 = 1, var.2 = 2, var.3 = 3) , b = list(var.1 = 4, var.2 = 5, var.3 = 6) , c = list(var.1 = 7, var.2 = 8, var.3 = 9) , d = list(var.1 = 10, var.2 = 11, var.3 = 12) ) l <- melt(l) dcast(l, L1 ~ L2) 

收益率:

  L1 var.1 var.2 var.3 1 a 1 2 3 2 b 4 5 6 3 c 7 8 9 4 d 10 11 12 

如果你几乎没有像素,你可以在1行w / recast()中完成。

更多的答案,以及这个问题的答案时间: 什么是最有效的方式来列表作为一个数据框?

最快捷的方式,不会产生列表而不是列表的数据框,这似乎是(来自Martin Morgan的回答):

 l <- list(list(col1="a",col2=1),list(col1="b",col2=2)) f = function(x) function(i) unlist(lapply(x, `[[`, i), use.names=FALSE) as.data.frame(Map(f(l), names(l[[1]]))) 

扩展@马立克的答案:如果你想避免string变成因素和效率不是一个问题尝试

 do.call(rbind, lapply(your_list, data.frame, stringsAsFactors=FALSE)) 

对于具有3个或更多级别的深度嵌套列表的一般情况,如从嵌套JSON中获取的列表:

 { "2015": { "spain": {"population": 43, "GNP": 9}, "sweden": {"population": 7, "GNP": 6}}, "2016": { "spain": {"population": 45, "GNP": 10}, "sweden": {"population": 9, "GNP": 8}} } 

考虑melt()的方法来首先将嵌套列表转换为高格式:

 myjson <- jsonlite:fromJSON(file("test.json")) tall <- reshape2::melt(myjson)[, c("L1", "L2", "L3", "value")] L1 L2 L3 value 1 2015 spain population 43 2 2015 spain GNP 9 3 2015 sweden population 7 4 2015 sweden GNP 6 5 2016 spain population 45 6 2016 spain GNP 10 7 2016 sweden population 9 8 2016 sweden GNP 8 

接着是dcast()然后再变成一个整齐的数据集,其中每个variables形成一列,每个观察形成一行:

 wide <- reshape2::dcast(tall, L1+L2~L3) # left side of the formula defines the rows/observations and the # right side defines the variables/measurements L1 L2 GNP population 1 2015 spain 9 43 2 2015 sweden 6 7 3 2016 spain 10 45 4 2016 sweden 8 9 

enframe()包有一个函数enframe() ,通过强制嵌套list对象到嵌套的tibble (“整洁的”数据框)对象来解决这个问题。 以下是R for Data Science的简要示例:

 x <- list( a = 1:5, b = 3:4, c = 5:6 ) df <- enframe(x) df #> # A tibble: 3 × 2 #> name value #> <chr> <list> #> 1 a <int [5]> #> 2 b <int [2]> #> 3 c <int [2]> 

由于在列表中有多个嵌套l ,因此可以使用unlist(recursive = FALSE)删除不必要的嵌套,以获得一个单独的层次结构列表,然后传递给enframe() 。 我使用tidyr::unnest()将输出放到一个单一级别的“整齐”数据框中,其中有两列(一个用于组name ,一个用于观察组value )。 如果你想要宽的列,你可以添加一个使用add_column()的列,重复132次的值的顺序。 然后spread()值。

 library(tidyverse) l <- replicate( 132, list(sample(letters, 20)), simplify = FALSE ) l_tib <- l %>% unlist(recursive = FALSE) %>% enframe() %>% unnest() l_tib #> # A tibble: 2,640 x 2 #> name value #> <int> <chr> #> 1 1 d #> 2 1 z #> 3 1 l #> 4 1 b #> 5 1 i #> 6 1 j #> 7 1 g #> 8 1 w #> 9 1 r #> 10 1 p #> # ... with 2,630 more rows l_tib_spread <- l_tib %>% add_column(index = rep(1:20, 132)) %>% spread(key = index, value = value) l_tib_spread #> # A tibble: 132 x 21 #> name `1` `2` `3` `4` `5` `6` `7` `8` `9` `10` `11` #> * <int> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> #> 1 1 dzlbijgwrpy #> 2 2 wshrikduafj #> 3 3 rvqsmujpfai #> 4 4 oyxnpifmhlt #> 5 5 pwvdkalrjqn #> 6 6 ikwocnmbveq #> 7 7 cdmiuoezvgp #> 8 8 fseopnkxczh #> 9 9 dgohxicytfj #> 10 10 yrfkdobuixs #> # ... with 122 more rows, and 9 more variables: `12` <chr>, `13` <chr>, #> # `14` <chr>, `15` <chr>, `16` <chr>, `17` <chr>, `18` <chr>, #> # `19` <chr>, `20` <chr> 

有时候你的数据可能是一个长度相同的向量列表。

 lolov = list(list(c(1,2,3),c(4,5,6)), list(c(7,8,9),c(10,11,12),c(13,14,15)) ) 

(内部向量也可以是列表,但是我正在简化以使其更容易阅读)。

然后你可以进行下面的修改。 请记住,您可以一次取消一个级别:

 lov = unlist(lolov, recursive = FALSE ) > lov [[1]] [1] 1 2 3 [[2]] [1] 4 5 6 [[3]] [1] 7 8 9 [[4]] [1] 10 11 12 [[5]] [1] 13 14 15 

现在使用你在其他答案中提到的方法:

 library(plyr) >ldply(lov) V1 V2 V3 1 1 2 3 2 4 5 6 3 7 8 9 4 10 11 12 5 13 14 15 

这是最后为我工作的:

do.call("rbind", lapply(S1, as.data.frame))

 l <- replicate(10,list(sample(letters, 20))) a <-lapply(l[1:10],data.frame) do.call("cbind", a) 

test1 < – list(c(a ='a',b ='b',c ='c'),c(a ='d',b ='e',c ='f'))as.data .frame(test1)abc 1 abc 2 def

test2 < – list(c('a','b','c'),c(a ='d',b ='e',c ='f'))

as.data.frame(test2)abc 1 abc 2 def

test3 < – list('Row1'= c(a ='a',b ='b',c ='c'),'Row2'= c(a ='d',var2 ='e',var3 = 'F'))

as.data.frame(test3)abc var2 var3 Row1 abc
Row2 def