R 如何将列表列表转换为数据帧-不相同列表
我有一个列表,其中每个元素都是一个命名列表,但每个元素都不相同。我读过关于如何将列表列表转换为数据帧和数据帧的解决方案,但当列表不相同时,所有这些都不起作用 示例-注意,我也有混合类型,如果解决方案将所有内容强制为character,这是很好的R 如何将列表列表转换为数据帧-不相同列表,r,R,我有一个列表,其中每个元素都是一个命名列表,但每个元素都不相同。我读过关于如何将列表列表转换为数据帧和数据帧的解决方案,但当列表不相同时,所有这些都不起作用 示例-注意,我也有混合类型,如果解决方案将所有内容强制为character,这是很好的 lisnotOK <- list(list(a=1, b=2, c="hi"), list(b=2, c="hello", d="nope")) 任何使用rbind,或试图将lisnotOK放入矩阵的解决方案都将失败,而上面链接的帖子中的任何示例
lisnotOK <- list(list(a=1, b=2, c="hi"), list(b=2, c="hello", d="nope"))
任何使用rbind
,或试图将lisnotOK
放入矩阵的解决方案都将失败,而上面链接的帖子中的任何示例都不起作用,即使我尝试使用rbind\u all
或rbind.fill
一种解决方案是丑陋的for循环,其中每个连续列表都更改为一个数据帧,并使用rbind\u all
绑定到一个数据帧
有人知道一个有效的解决方案吗?使用
lappy
将列表元素转换为数据。frame
s和rbind\u all
:
rbind_all(lapply(lisnotOK,data.frame))
a b c d
1 1 2 hi <NA>
2 NA 2 hello nope
Warning message:
In rbind_all(lapply(lisnotOK, data.frame)) :
Unequal factor levels: coercing to character
考虑到生成的矩阵都是相同类型(例如,
字符
),您可以尝试编写自己的函数,如下所示:
list2mat <- function(inList) {
UL <- unlist(inList)
Nam <- unique(names(UL))
M <- matrix(NA_character_,
nrow = length(inList), ncol = length(Nam),
dimnames = list(NULL, Nam))
Row <- rep(seq_along(inList), sapply(inList, length))
Col <- match(names(UL), Nam)
M[cbind(Row, Col)] <- UL
M
}
这应该很快,因为所有内容都是预先分配的,并且您正在使用矩阵索引
更新:基准(因为你说效率是个问题)
fun1任何在绑定前对列表的每个元素使用data.frame(.)
的函数都会非常低效(更不用说没有必要了)。下面是另一种使用data.table
的rbindlist
(来自v1.9.3)的方法,您可以从中获得
它适用于列表列表(如本问题中)、data.frames和data.tables
如果不是这样,那么我就使用Ananda的list2mat
函数(如果您的类型都相同的话)
Ananda的L2
数据基准:
fun1 <- function(inList) ldply(inList, as.data.frame)
fun2 <- function(inList) list2mat(inList)
fun3 <- function(inList) rbindlist(inList, fill=TRUE)
fun4 <- function(inList) rbind_all(lapply(inList, as.data.frame))
microbenchmark(fun1(L2), fun2(L2), fun3(L2), fun4(L2), times = 10)
# Unit: milliseconds
# expr min lq median uq max neval
# fun1(L2) 1927.857847 2161.432665 2221.999940 2276.241366 2366.649614 10
# fun2(L2) 12.039652 12.167613 12.361629 12.483751 16.040885 10
# fun3(L2) 1.225929 1.374395 1.473621 1.510876 1.858597 10
# fun4(L2) 1435.153576 1457.053482 1492.334965 1548.547706 1630.443430 10
fun1这很好,不幸的是我发现它在我的实际列表中不起作用,因为有些元素包含NULL。但这很容易在另一圈中修复。@akrun,为什么?ldply
有什么特别之处?@akrun,这是因为您没有查看ldply
的代码。按照这种逻辑,我的代码就是list2mat(lisnotOK)
:-)+1。这是一个巨大的差异。不确定这是否适用于'rbindlist(,fill=TRUE)。我没有data.table的新版本要测试。感谢更新的基准测试。我没有意识到,rbindlist
是这样工作的——或者是1.9.3中的一个更新(因此您指定了版本号)?@AnandaMahto,rbind
从1.9.2开始就有fill=TRUE
,但它是在R中实现的。在1.9.3中,所有内容都被移到了C,并且rbist
被修饰。您可以阅读更多。rbindlist中的fill=TRUE
参数万岁!
list2mat <- function(inList) {
UL <- unlist(inList)
Nam <- unique(names(UL))
M <- matrix(NA_character_,
nrow = length(inList), ncol = length(Nam),
dimnames = list(NULL, Nam))
Row <- rep(seq_along(inList), sapply(inList, length))
Col <- match(names(UL), Nam)
M[cbind(Row, Col)] <- UL
M
}
list2mat(lisnotOK)
# a b c d
# [1,] "1" "2" "hi" NA
# [2,] NA "2" "hello" "nope"
fun1 <- function(inList) ldply(inList, data.frame)
fun2 <- function(inList) list2mat(inList)
library(microbenchmark)
microbenchmark(fun1(lisnotOK), fun2(lisnotOK))
# Unit: microseconds
# expr min lq median uq max neval
# fun1(lisnotOK) 4193.808 4340.0585 4523.3000 4912.233 7600.341 100
# fun2(lisnotOK) 163.784 182.3865 211.2515 236.910 363.489 100
L2 <- unlist(replicate(1000, lisnotOK, simplify=FALSE), recursive=FALSE)
microbenchmark(fun1(L2), fun2(L2), times = 10)
# Unit: milliseconds
# expr min lq median uq max neval
# fun1(L2) 3032.71572 3106.79006 3196.17178 3306.11756 3609.67445 10
# fun2(L2) 24.16817 24.86991 25.65569 27.44128 29.41908 10
require(data.table) ## 1.9.3
rbindlist(lisnotOK, fill=TRUE)
# a b c d
# 1: 1 2 hi NA
# 2: NA 2 hello nope
fun1 <- function(inList) ldply(inList, as.data.frame)
fun2 <- function(inList) list2mat(inList)
fun3 <- function(inList) rbindlist(inList, fill=TRUE)
fun4 <- function(inList) rbind_all(lapply(inList, as.data.frame))
microbenchmark(fun1(L2), fun2(L2), fun3(L2), fun4(L2), times = 10)
# Unit: milliseconds
# expr min lq median uq max neval
# fun1(L2) 1927.857847 2161.432665 2221.999940 2276.241366 2366.649614 10
# fun2(L2) 12.039652 12.167613 12.361629 12.483751 16.040885 10
# fun3(L2) 1.225929 1.374395 1.473621 1.510876 1.858597 10
# fun4(L2) 1435.153576 1457.053482 1492.334965 1548.547706 1630.443430 10