l <- list(a = list(var.1 = 1, var.2 = 2, var.3 = 3)
, b = list(var.1 = 4, var.2 = 5)
, c = list(var.1 = 7, var.3 = 9)
, d = list(var.1 = 10, var.2 = 11, var.3 = NA))
df <- dplyr::bind_rows(l)
df <- purrr::map_df(l, dplyr::bind_rows)
df <- purrr::map_df(l, ~.x)
# all create the same data frame:
# A tibble: 4 x 3
var.1 var.2 var.3
<dbl> <dbl> <dbl>
1 1 2 3
2 4 5 NA
3 7 NA 9
4 10 11 NA
您还可以混合矢量和数据框:
library(dplyr)
bind_rows(
list(a = 1, b = 2),
data_frame(a = 3:4, b = 5:6),
c(a = 7)
)
# A tibble: 4 x 2
a b
<dbl> <dbl>
1 1 2
2 3 5
3 4 6
4 7 NA
8
tibble 包有一个函数 enframe() ,它通过将嵌套的 list 对象强制转换为嵌套的 tibble ("tidy"数据帧)对象来解决此问题 . 以下是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() 来取消输出到单级"tidy"数据框,它有两列(一组用于组 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 d z l b i j g w r p y
#> 2 2 w s h r i k d u a f j
#> 3 3 r v q s m u j p f a i
#> 4 4 o y x n p i f m h l t
#> 5 5 p w v d k a l r j q n
#> 6 6 i k w o c n m b v e q
#> 7 7 c d m i u o e z v g p
#> 8 8 f s e o p n k x c z h
#> 9 9 d g o h x i c y t f j
#> 10 10 y r f k d o b u i x s
#> # ... 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>
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() 然后再次变宽到一个整洁的数据集,其中每个变量形成一个列,每个观察形成一行:
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
17 回答
假设您的列表列表名为
l
:以上将所有字符列转换为因子,为避免这种情况,您可以向data.frame()调用添加一个参数:
您可以使用
plyr
包 . 例如,表单的嵌套列表现在长度为4,
l
中的每个列表都包含另一个长度为3的列表 . 现在你可以运行了并且应该得到与答案@Marek和@nico相同的结果 .
data.frame(t(sapply(mylistlist,c)))
sapply
将其转换为矩阵 .data.frame
将矩阵转换为数据帧 .随着
rbind
编辑:以前的版本返回
list
的list
而不是向量(如评论中指出的@IanSudbery) .test2 < - list(c('a','b','c'),c(a ='d',b ='e',c ='f'))
test3 < - list('Row1'= c(a ='a',b ='b',c ='c'),'row2'= c(a ='d',var2 ='e',var3 = 'F'))
这最终对我有用:
do.call("rbind", lapply(S1, as.data.frame))
Reshape2产生的输出与上面的plyr示例相同:
收益率:
如果你几乎没有像素,你可以在1行w / recast()中完成所有这些操作 .
更多答案,以及这个问题答案的时间安排:What is the most efficient way to cast a list as a data frame?
最快的方法是,不会产生带有列表而不是列的向量的数据帧(来自Martin Morgan的答案):
延伸@ Marek的答案:如果你想避免字符串被转化为因素和效率不是一个值得关注的尝试
假设您的列表名为
L
,有时您的数据可能是相同长度的矢量列表的列表 .
(内部向量也可以是列表,但我正在简化以使其更容易阅读) .
然后您可以进行以下修改 . 请记住,您可以一次取消一个级别:
现在使用其他答案中提到的您最喜欢的方法:
根据列表的结构,有一些
tidyverse
选项可以很好地处理不等长度列表:您还可以混合矢量和数据框:
tibble
包有一个函数enframe()
,它通过将嵌套的list
对象强制转换为嵌套的tibble
("tidy"数据帧)对象来解决此问题 . 以下是R for Data Science的简短示例:由于列表中有多个嵌套
l
,因此可以使用unlist(recursive = FALSE)
删除不必要的嵌套以获取单个分层列表,然后传递给enframe()
. 我使用tidyr::unnest()
来取消输出到单级"tidy"数据框,它有两列(一组用于组name
,一组用于组value
的观察) . 如果您想要宽的列,可以使用add_column()
添加一个列,只重复值的顺序132次 . 然后只是spread()
的值 .包
data.table
具有rbindlist
函数,它是do.call(rbind, list(...))
的超快实现 .它可以采用
lists
,data.frames
或data.tables
列表作为输入 .这将返回
data.table
继承自data.frame
.如果 really 想要转换回data.frame,请使用
as.data.frame(DT)
对于深层嵌套列表的一般情况 with 3 or more levels ,就像从嵌套JSON获得的那样:
考虑
melt()
的方法首先将嵌套列表转换为高格式:然后是
dcast()
然后再次变宽到一个整洁的数据集,其中每个变量形成一个列,每个观察形成一行:此方法使用
tidyverse
包( purrr ) .列表:
将其转换为数据框(更具体地说是
tibble
):