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

下面是一些示例数据:

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

当前回答

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

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

其他回答

对于像从嵌套JSON中获得的3级或更多级别的深度嵌套列表的一般情况:

{
"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(),然后再次扩大到一个整洁的数据集,其中每个变量组成一个a列,每个观察值组成一行:

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

根据列表的结构,有一些tidyverse选项可以很好地处理长度不等的列表:

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

你可以使用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相同的结果。

一个简短的(但可能不是最快的)方法是使用基底r,因为数据帧只是一个长度相等的向量的列表。因此,你的输入列表和一个30 x 132 data.frame之间的转换将是:

df <- data.frame(l)

从这里我们可以将其转置为132 x 30的矩阵,并将其转换回数据帧:

new_df <- data.frame(t(df))

一句话:

new_df <- data.frame(t(data.frame(l)))

行名看起来很讨厌,但是您总是可以用

行名称(new_df) <- 1:nrow(new_df)