【问题标题】:How to convert a list with different length element to a dataframe如何将具有不同长度元素的列表转换为数据框
【发布时间】:2023-03-22 03:46:01
【问题描述】:

在这里,当我有一个循环时,我经常遇到这种问题。第一个解决了。

[1] 我有一个这样的列表:

myList <- list(a = c(1, 2, 3), b = c(4, 5, 6, 7), c= c(9,10))

现在我想将列表转换为这样的 data.frame:

    Value
a   1, 2, 3
b   4, 5, 6, 7
c   9, 10

有没有人通过基本 R 向我展示一般功能?

[2]新问题出现:

mynewList <- list(a = c(1, 2, 3, "f"), b = c(4, 5, 6), c= c(9,10), d=list(1,2))

我想将 mynewlist 转换为这样的数据框:

    a   b   c   d 
1   1   4   9  1
2   2   5  10  2
3   3   6  na  na
4   f   na na  na

我之前使用过以下命令,它可以在没有 d 元素的情况下工作。但它现在不起作用。

df<-data.frame(lapply(myList, "length<-" , max(lengths(myList))))

有没有人通过基本 R 向我展示一般功能?

【问题讨论】:

  • 您用于问题 2 的方法是正确的。问题在于您如何编写d 的条目:您需要将d 添加为d=list(c(1, 2))。将其写为d = list(1, 2) 会将d 传播到最终列表中的两个元素上,如果您在尝试将其放入data.frame 之前查看mynewList 可以看出这一点。

标签: r list dataframe


【解决方案1】:

1。我们可以使用sapplypaste

df <- data.frame(Value = sapply(myList, paste, collapse = ','))

输出:

    Value
a   1,2,3
b 4,5,6,7
c    9,10

2。我们可以在应用最大长度之前unlist 每个列表元素:

df <- data.frame(lapply(mynewList, function(x) {
  x <- unlist(x)
  length(x) <- max(lengths(mynewList))
  return(x)
}))

输出:

  a  b  c  d
1 1  4  9  1
2 2  5 10  2
3 3  6 NA NA
4 f NA NA NA

【讨论】:

  • 你知道如何解决我的新问题吗? @avid_user
【解决方案2】:

这种方法将您的Value 保留为一个列表:

myDF <- data.frame(t(rbind(myList)))

myDF
#      myList
#a    1, 2, 3
#b 4, 5, 6, 7
#c      9, 10

str(myDF)
#'data.frame':  3 obs. of  1 variable:
# $ myList:List of 3
#  ..$ a: num  1 2 3
#  ..$ b: num  4 5 6 7
#  ..$ c: num  9 10

【讨论】:

  • 非常感谢。好东西。这个方法没有改变每个元素的类型。
【解决方案3】:

关于更新的请求,我遇到了类似的问题,将不同长度的列绑定在一起。 我通过编写cbind 的包装解决了问题,该包装还添加了NA 值。

cbind.NA <- function (...) {
   myDFs <- list(...)
   myDFs <- lapply(myDFs, as.matrix)
   n <- max(sapply(myDFs, nrow)) 
   do.call(cbind, lapply(myDFs, function(x) rbind(x, matrix(,n-nrow(x), ncol(x)))))
}

因为你有rows 和一个列表,所以你需要使用rbind 并将列表的元素转换为data.frame,然后再将它们绑定在一起。

newDF <- data.frame()
for(i in 1:length(myList)){
   tmp <- as.data.frame(myList[[i]])
   names(tmp) <- names(myList[i])
   newDF <- cbind.NA(newDF,tmp) 
}

newDF
      a b  c
[1,]  1 4  9
[2,]  2 5 10
[3,]  3 6 NA
[4,] NA 7 NA

t(newDF)
   [,1] [,2] [,3] [,4]
a    1    2    3   NA
b    4    5    6    7
c    9   10   NA   NA

【讨论】:

    【解决方案4】:

    这是我能用基础 R 想出的最简单的解决方案。

    cbindlist = function(list_obj){
    
      lengths = unlist(lapply(list_obj, length))
      NA_lengths = sapply(lengths, function(x) max(lengths) - x)
      cols = names(list_obj)
    
      out = data.frame(sapply(1:length(list_obj), function(x) c(list_obj[[x]], rep(NA, NA_lengths[x]))))
      colnames(out) = cols
    
      return(out)
    }
    

    它适用于您的两个示例:

    lista = list(a = c(1, 2, 3), b = c(4, 5, 6, 7), c = c(9,10))
    newlista = list(a = c(1, 2, 3, "f"), b = c(4, 5, 6), c= c(9,10), d=list(1,2))
    
    > cbindlist(lista)
       a b  c
    1  1 4  9
    2  2 5 10
    3  3 6 NA
    4 NA 7 NA
    
    > cbindlist(newlista)
      a  b  c  d
    1 1  4  9  1
    2 2  5 10  2
    3 3  6 NA NA
    4 f NA NA NA
    

    【讨论】:

    • 非常感谢。这种方式非常清晰,重要的是,非常适合我这个R初学者。
    猜你喜欢
    • 2018-08-07
    • 2017-10-31
    • 2013-09-30
    • 1970-01-01
    • 2021-10-21
    • 2020-02-13
    • 1970-01-01
    • 1970-01-01
    • 2023-02-18
    相关资源
    最近更新 更多