R:将列表转换为data.frame

R:将列表转换为data.frame,r,list,dataframe,R,List,Dataframe,其中一些元素为NULL,而其他元素可以具有多个子元素,例如,第三个元素具有子元素[[1]]和[[2]] 我想将这些列表元素组合成一个类似这样的data.frame(为了方便起见,我省略了Score2到Score6列的内容): 我尝试了以下操作,但出现了错误 Gender ID Class Score1 Score2 ... Score6 1 Female 1 A 21.60 2 Female 2 A 25.58 3 Male 2 A

其中一些元素为
NULL
,而其他元素可以具有多个子元素,例如,第三个元素具有子元素
[[1]]
[[2]]

我想将这些列表元素组合成一个类似这样的data.frame(为了方便起见,我省略了Score2到Score6列的内容):

我尝试了以下操作,但出现了错误

  Gender ID Class Score1 Score2 ... Score6
1 Female  1     A  21.60     
2 Female  2     A  25.58    
3   Male  2     A  18.31    
4 Female  3     A  27.16    
5   Male  3     A  14.67    
试试这个:

> ldply(mylist, data.frame)
  Gender ID Class Score1 Score2 Score3 Score4    Score5    Score6 Gender.1 ID.1 Class.1 Score1.1 Score2.1 Score3.1 Score4.1  Score5.1  Score6.1
1 Female  1     A  21.60  39.61   8.85  13.66  2.650000  6.947368     <NA> <NA>    <NA>       NA       NA       NA       NA        NA        NA
2 Female  2     A  25.58  55.01   1.66   3.60 15.272727 15.583333   Female    3       A    27.16    58.39     1.66     3.60 16.272727 16.583333
3   Male  2     A  18.31  36.28   2.13   4.24  8.571429  8.454545     Male    3       A    14.67    29.07     2.13     4.24  6.857143  6.818182

ll您只需使用两个
tidyverse
函数即可完成此操作
purrr::reduce
允许您在列表或向量中应用函数,而
dplyr::bind_rows
就像一个扩展的、更智能的
rbind

请注意,正如我在评论中所说,您会收到关于将字符向量与因子向量绑定的警告,但这只是一个警告,而不是错误

purrr::reduce(mylist,dplyr::bind_行)
#>绑定行中的警告(x,.id):绑定字符和因子向量,
#>强制转换为字符向量
...
#>性别ID类分数1分2分3分4分5分6
#>1女1 A 21.60 39.61 8.85 13.66 2.650000 6.947368
#>2女2 A 25.58 55.01 1.66 3.60 15.272727 15.583333
#>3男2 A 18.31 36.28 2.13 4.24 8.571429 8.4545
#>4女3 A 27.16 58.39 1.66 3.60 16.272727 16.583333
#>5男3 A 14.67 29.07 2.13 4.24 6.857143 6.818182

我提出了一个名为
unlist\u的广义
unlist
函数,除非
unlist
类似,但有以下区别:

  • 它有一个
    谓词
    参数,用于保持某些子元素不变(如果安装了
    purrr
    ,则支持公式表示法)
  • 将参数传递给
    谓词
  • keep_null
    用于保留(默认)或删除
    null
    元素
unlist
类似,它的特点是参数
recursive
use.names
具有相同的默认值。默认情况下,参数设置为
TRUE
,它还具有一个
keep_null
参数,我默认设置为
TRUE

ll <- unlist(lapply(mylist, function(x) if(is.data.frame(x)) list(x) else x), recursive = FALSE)
do.call(rbind, ll)
  Gender ID Class Score1 Score2 Score3 Score4    Score5    Score6
1 Female  1     A  21.60  39.61   8.85  13.66  2.650000  6.947368
2 Female  2     A  25.58  55.01   1.66   3.60 15.272727 15.583333
3   Male  2     A  18.31  36.28   2.13   4.24  8.571429  8.454545
4 Female  3     A  27.16  58.39   1.66   3.60 16.272727 16.583333
5   Male  3     A  14.67  29.07   2.13   4.24  6.857143  6.818182
然后就可以直接对结果调用
bind\u行(dfs\u new)
do.call(rbind,dfs\u new)

unlist_unless(dfs, is.data.frame, keep_null = FALSE)
# [[1]]
# Sepal.Length Sepal.Width Petal.Length
# 1          5.1         3.5          1.4
# 
# [[2]]
# Sepal.Length Sepal.Width Petal.Length
# 2          4.9           3          1.4
# 
# [[3]]
# Sepal.Length Sepal.Width Petal.Length
# 3          4.7         3.2          1.3
# 
# [[4]]
# Sepal.Length Sepal.Width Petal.Length
# 4          4.6         3.1          1.5

unlist_unless(dfs, is.data.frame, recursive = FALSE)
# [[1]]
# Sepal.Length Sepal.Width Petal.Length
# 1          5.1         3.5          1.4
# 
# [[2]]
# NULL
# 
# [[3]]
# Sepal.Length Sepal.Width Petal.Length
# 2          4.9           3          1.4
# 
# [[4]]
# Sepal.Length Sepal.Width Petal.Length
# 3          4.7         3.2          1.3
# 
# [[5]]
# [[5]][[1]]
# Sepal.Length Sepal.Width Petal.Length
# 4          4.6         3.1          1.5
# 
# 
# [[6]]
# NULL

这些是警告,不是错误。您没有在
df
中获得所需的数据帧吗?@camille,没有,我不相关:
> ldply(mylist, data.frame)
  Gender ID Class Score1 Score2 Score3 Score4    Score5    Score6 Gender.1 ID.1 Class.1 Score1.1 Score2.1 Score3.1 Score4.1  Score5.1  Score6.1
1 Female  1     A  21.60  39.61   8.85  13.66  2.650000  6.947368     <NA> <NA>    <NA>       NA       NA       NA       NA        NA        NA
2 Female  2     A  25.58  55.01   1.66   3.60 15.272727 15.583333   Female    3       A    27.16    58.39     1.66     3.60 16.272727 16.583333
3   Male  2     A  18.31  36.28   2.13   4.24  8.571429  8.454545     Male    3       A    14.67    29.07     2.13     4.24  6.857143  6.818182
ll <- unlist(lapply(mylist, function(x) if(is.data.frame(x)) list(x) else x), recursive = FALSE)
do.call(rbind, ll)
  Gender ID Class Score1 Score2 Score3 Score4    Score5    Score6
1 Female  1     A  21.60  39.61   8.85  13.66  2.650000  6.947368
2 Female  2     A  25.58  55.01   1.66   3.60 15.272727 15.583333
3   Male  2     A  18.31  36.28   2.13   4.24  8.571429  8.454545
4 Female  3     A  27.16  58.39   1.66   3.60 16.272727 16.583333
5   Male  3     A  14.67  29.07   2.13   4.24  6.857143  6.818182
unlist_unless <- function(x, predicate = function(x) FALSE, ..., recursive = TRUE,  use.names = TRUE, keep_null = TRUE){
  if(inherits(predicate, "formula")) {
    if (requireNamespace("purrr")) predicate <- purrr::as_mapper(predicate) else
      stop("Package `purrr` needs to be installed to use formula notation")
  }

  unlist(lapply(x, function(y){
    if(predicate(y, ...) || (keep_null && is.null(y)))
      list(y)
    else if (is.list(y) && recursive)
      unlist_unless(y, predicate = predicate, ..., keep_null=keep_null, use.names = use.names)
    else y}),
    recursive = FALSE,
    use.names = use.names)
}
df <- head(iris)[1:3]
dfs<- list(df[1,],
             NULL,
             list(df[2,],
                  df[3,],
                  list(df[4,]),
                  NULL))

unlist_unless(dfs, is.data.frame)
# [[1]]
# Sepal.Length Sepal.Width Petal.Length
# 1          5.1         3.5          1.4
# 
# [[2]]
# NULL
# 
# [[3]]
# Sepal.Length Sepal.Width Petal.Length
# 2          4.9           3          1.4
# 
# [[4]]
# Sepal.Length Sepal.Width Petal.Length
# 3          4.7         3.2          1.3
# 
# [[5]]
# Sepal.Length Sepal.Width Petal.Length
# 4          4.6         3.1          1.5
# 
# [[6]]
# NULL
unlist_unless(dfs, is.data.frame, keep_null = FALSE)
# [[1]]
# Sepal.Length Sepal.Width Petal.Length
# 1          5.1         3.5          1.4
# 
# [[2]]
# Sepal.Length Sepal.Width Petal.Length
# 2          4.9           3          1.4
# 
# [[3]]
# Sepal.Length Sepal.Width Petal.Length
# 3          4.7         3.2          1.3
# 
# [[4]]
# Sepal.Length Sepal.Width Petal.Length
# 4          4.6         3.1          1.5

unlist_unless(dfs, is.data.frame, recursive = FALSE)
# [[1]]
# Sepal.Length Sepal.Width Petal.Length
# 1          5.1         3.5          1.4
# 
# [[2]]
# NULL
# 
# [[3]]
# Sepal.Length Sepal.Width Petal.Length
# 2          4.9           3          1.4
# 
# [[4]]
# Sepal.Length Sepal.Width Petal.Length
# 3          4.7         3.2          1.3
# 
# [[5]]
# [[5]][[1]]
# Sepal.Length Sepal.Width Petal.Length
# 4          4.6         3.1          1.5
# 
# 
# [[6]]
# NULL
do.call(rbind,unlist_unless(dfs, is.data.frame))

# Sepal.Length Sepal.Width Petal.Length
# 1          5.1         3.5          1.4
# 2          4.9         3.0          1.4
# 3          4.7         3.2          1.3
# 4          4.6         3.1          1.5


# or
library(dplyr)
unlist_unless(dfs, is.data.frame) %>% bind_rows
#   Sepal.Length Sepal.Width Petal.Length
# 1          5.1         3.5          1.4
# 2          4.9         3.0          1.4
# 3          4.7         3.2          1.3
# 4          4.6         3.1          1.5