list 将列表转换为数据框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4227223/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 01:34:35  来源:igfitidea点击:

Convert a list to a data frame

rlistdataframe

提问by Btibert3

I have a nested list of data. Its length is 132 and each item is a list of length 20. Is there a quickway to convert this structure into a data frame that has 132 rows and 20 columns of data?

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

Here is some sample data to work with:

以下是一些可以使用的示例数据:

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

采纳答案by nico

Assuming your list of lists is called l:

假设您的列表列表被称为l

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

The above will convert all character columns to factors, to avoid this you can add a parameter to the data.frame() call:

以上将所有字符列转换为因子,为避免这种情况,您可以向 data.frame() 调用添加一个参数:

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

回答by Marek

With rbind

rbind

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

Edit: Previous version return data.frameof list's instead of vectors (as @IanSudbery pointed out in comments).

编辑:以前的版本回报data.framelist的载体,而不是(如@IanSudbery在评论中指出)。

回答by mropa

You can use the plyrpackage. For example a nested list of the form

您可以使用该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)
      )

has now a length of 4 and each list in lcontains another list of the length 3. Now you can run

现在长度为 4 并且每个列表都l包含另一个长度为 3 的列表。现在您可以运行

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

and should get the same result as in the answer @Marek and @nico.

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

回答by Alex Brown

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

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

sapplyconverts it to a matrix. data.frameconverts the matrix to a data frame.

sapply将其转换为矩阵。 data.frame将矩阵转换为数据框。

回答by jdeng

assume your list is called L,

假设你的名单被称为L

data.frame(Reduce(rbind, L))

回答by mnel

The package data.tablehas the function rbindlistwhich is a superfast implementation of do.call(rbind, list(...)).

该包data.table具有rbindlist超快实现的功能do.call(rbind, list(...))

It can take a list of lists, data.framesor data.tablesas input.

它可以采取的一个列表 listsdata.framesdata.tables作为输入。

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)

This returns a data.tableinherits from data.frame.

这将返回一个data.table继承自data.frame.

If you reallywant to convert back to a data.frame use as.data.frame(DT)

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

回答by Matt Dancho

The tibblepackage has a function enframe()that solves this problem by coercing nested listobjects to nested tibble("tidy" data frame) objects. Here's a brief example from R for Data Science:

tibble包具有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]>

Since you have several nests in your list, l, you can use the unlist(recursive = FALSE)to remove unnecessary nesting to get just a single hierarchical list and then pass to enframe(). I use tidyr::unnest()to unnest the output into a single level "tidy" data frame, which has your two columns (one for the group nameand one for the observations with the groups value). If you want columns that make wide, you can add a column using add_column()that just repeats the order of the values 132 times. Then just spread()the values.

由于您的列表中有多个嵌套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     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>

回答by sbha

Depending on the structure of your lists there are some tidyverseoptions that work nicely with unequal length lists:

根据列表的结构,有一些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

You can also mix vectors and data frames:

您还可以混合向量和数据框:

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

回答by Hyman Ryan

Reshape2 yields the same output as the plyr example above:

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)

yields:

产量:

  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

If you were almost out of pixels you coulddo this all in 1 line w/ recast().

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

回答by SavedByJESUS

This method uses a tidyversepackage (purrr).

此方法使用tidyverse包 ( purrr)。

The list:

列表:

x <- as.list(mtcars)

Converting it into a data frame (a tibblemore specifically):

将其转换为数据框(tibble更具体地说):

library(purrr)
map_df(x, ~.x)