如何将元素长度不同的列表转换为数据框。

3

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

[1] 我有一个如下的列表:

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

现在我想将列表转换为像这样的数据框:

    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语言给我展示一个通用函数?


你在第二个问题上使用的方法是正确的。问题在于你如何编写“d”的输入:你需要将“d”添加为“d=list(c(1, 2))”。如果将其写成“d = list(1, 2)”,则会将“d”分散到最终列表中的两个元素中,如果在尝试将其放入数据框之前查看“mynewList”,就可以看到这一点。 - Accidental Statistician
4个回答

3

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 - Jiang Liang

0

这种方法将您的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

非常感谢。不错哦。这个方法没有改变每个元素的类型。 - Jiang Liang

0
关于更新的请求,我遇到了类似的问题,需要将不同长度的列绑定在一起。 我通过编写一个包装器来解决,它可以同时添加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

0

这是我使用基本 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初学者来说非常合适。 - Jiang Liang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接