2015-04-03 88 views
7

假设我们有一个嵌套列表:R:在嵌套列表替换值

test <- list(
    list(a = 1, b = 2, c = NULL), 
    list(a = NULL, b = 2, c = 3)) 

如何更换,说所有的NULL值,NA保存数据的结构?所以当我试图将数据框从列表中移出时,我不会失去价值/结构。如:

data.frame(matrix(unlist(test), nrow = 2, byrow = T)) 

    X1 X2 
1 1 2 
2 2 3 

所需的输出是一样的东西:

X1 X2 X3 
1 1 2 NA 
2 NA 2 3 

有建议做这种方式:

rbind.fill(lapply(test, function(f) { 
    as.data.frame(Filter(Negate(is.null), f)) 
})) 

这是不太矢量,因为我想。显然,尺寸和性能是一个问题。需要考虑的一种解决方法是同时替换所有NULL值,因为它可以一次完成整个数据帧。然后是unlist()matrix()的列表。

我不确定表现的收益(如果有的话)。也许好老lapply()并不是那么糟糕。

+0

要替换整个列表中的NULL值,我们必须访问里面的元素。使用'data.table 1.9.5',你可以在更新的代码中使用'rbindlist(lapply(....),fill = TRUE)'。 – akrun 2015-04-03 07:46:26

+0

..这要求lapply基本结束与原来的答案相同的性能? – 2015-04-03 07:49:24

+0

我没有检查基准,但我认为rbindlist会更快。 – akrun 2015-04-03 07:50:22

回答

4

我们可以使用stri_list2matrix

library(stringi) 
m1 <- matrix(as.numeric(t(sapply(test, stri_list2matrix))), ncol=3) 
m1 
# [,1] [,2] [,3] 
#[1,] 1 2 NA 
#[2,] NA 2 3 

这可以转换为data.frame

as.data.frame(m1) 
+0

只是好奇 - 是否有替代值的选项,而不是应用循环类函数?在'data.table'包中还有其他一些选项,如'rbind.all' ...它确实达到了结果,但是路线并不是我所期望的。 – 2015-04-03 07:29:56

+0

经过对不同案例的测试后,这似乎是最普遍的做法。 – 2015-04-03 08:37:03

+0

@ A.Val。你有没有尝试过使用这种方法和'rbindlist'的一些基准测试 – akrun 2015-04-03 08:41:36

1

如果你知道这只是个级别列表中,您可以通过使用两个循环测试is.null每个元素周期。

test <- list(
    list(a = 1, b = 2, c = NULL), 
    list(a = NULL, b = 2, c = 3) 
) 

# get structure fyi 
str(test) 
# tells you the highest level list length 
length(test) 

for(i in 1:length(test)) 
    for(j in 1:length(test[[i]])) # second level 
     if(is.null(test[[i]][[j]])) test[[i]][[j]]<-NA 

编辑:然后当然做你以前做的事情。

+0

Loop是一个明显的答案,我想不惜一切代价避免,可能我应该扩展我的问题一点来澄清。 – 2015-04-03 07:34:00

2

如下回答中发现here,这里是一个(有点扭曲)的方式在base R去:

data.frame(matrix(as.numeric(as.character(unlist(test, recursive=F))), nrow=length(test), byrow=T)) 

# X1 X2 X3 
#1 1 2 NA 
#2 NA 2 3 
+0

好的方式去! – 2015-04-03 10:04:30

+0

@ColonelBeauvel,谢谢,虽然我这里唯一的功劳就是找到了正确的SO页面;-) – Cath 2015-04-03 10:11:52

0

一种不同的方法通过dputdget和剪贴板。

test <- list(
    list(a = 1, b = 2, c = NULL), 
    list(a = NULL, b = 2, c = 3)) 

dput(test,file="clipboard-1024") 
tmp=dget(textConnection(gsub("NULL","NA",readChar(con="clipboard-1024",file.info("clipboard-1024")$size)))) 
data.frame(matrix(unlist(tmp), nrow = 2, byrow = T)) 

# X1 X2 X3 
#1 1 2 NA 
#2 NA 2 3 

我不知道这是多快还是多慢。