2015-04-03 93 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 

我不知道這是多快還是多慢。