2016-01-21 44 views
5

我有兩份名單,我想使他們在NA方面是一致的。把NA放在兩個列表中的一個列表中,而不改變列表結構中的其他內容。如何處理兩個列表中的NA?

set.seed(123) 
m1 <- matrix(nrow=2,ncol=2,data=runif(4)) 
m1[1,1] <- NA 
m2 <- matrix(nrow=2,ncol=2,data=runif(4)) 
m2[1,2] <- NA 
lis <- list(m1, m2) 
m1 <- matrix(nrow=2,ncol=2,data=runif(4)) 
m2 <- matrix(nrow=2,ncol=2,data=runif(4)) 
m2[2,1] <- NA 
bis <- list(m1, m2) 

我試過,但沒有成功bis[is.na(lis)]=NA

所需的輸出:

> lis 
[[1]] 
      [,1]  [,2] 
[1,]  NA 0.9568333 
[2,] 0.4566147 0.4533342 

[[2]] 
     [,1]  [,2] 
[1,] 0.9404673  NA 
[2,] 0.0455565  NA 

    > bis 
[[1]] 
     [,1]  [,2] 
[1,]  NA 0.9568333 
[2,] 0.4566147 0.4533342 

[[2]] 
     [,1]  [,2] 
[1,] 0.6775706  NA 
[2,] 0.5726334  NA 

回答

3

這裏有一個選項:

z <- Map("|", lapply(lis, is.na), lapply(bis, is.na)) 
bis <- Map(function(mat, idx) {mat[idx] <- NA; mat}, bis, z) 
lis <- Map(function(mat, idx) {mat[idx] <- NA; mat}, lis, z) 

但是,有可能更快/更有效的方法由於衆多Maplapply個電話。


> 2頁列出了可以使用下面的方法(假設每個列表具有相同的長度)的情況下:

# create a named list - naming is important if you want to 
# assign them back to the global environment later on 
mylist <- list(lis = lis, bis = bis, kis = kis) 

n <- max(lengths(mylist)) 
z <- lapply(1:n, function(i) { 
    Reduce(`+`, Map(function(y) is.na(y[[i]]), mylist))>0 
}) 

mylist <- lapply(mylist, function(mat) { 
    Map(function(m, idx) {m[idx] <- NA; m}, mat, z) 
}) 

# to assign them back to the global environment, run: 
list2env(mylist, envir = .GlobalEnv) 

現在你原來的列表是在全球環境中進行修改。

樣本數據:

set.seed(123) 
n <- 4 
lis <- list(
    m1 = matrix(nrow=n,ncol=n,data=sample(c(NA, 1:10), n*n, TRUE)), 
    m2 = matrix(nrow=n,ncol=n,data=sample(c(NA, 1:10), n*n, TRUE)) 
) 
bis <- list(
    m1 = matrix(nrow=n,ncol=n,data=sample(c(NA, 1:10), n*n, TRUE)), 
    m2 = matrix(nrow=n,ncol=n,data=sample(c(NA, 1:10), n*n, TRUE)) 
) 
kis <- list(
    m1 = matrix(nrow=n,ncol=n,data=sample(c(NA, 1:10), n*n, TRUE)), 
    m2 = matrix(nrow=n,ncol=n,data=sample(c(NA, 1:10), n*n, TRUE)) 
) 
+0

替換第一行與:'z < - 地圖(功能ion(...){dots < - as.list(...); arr < - do.call(abind,c(dots,along = 3));適用(arr,1:2,任何)},lapply(lis,is.na),lapply(bis,is.na))'。我認爲這應該工作。雖然可能比較慢。需要'abind'軟件包。關鍵是用'any'替換'|'。 – Bazz

+0

@Bazz,請繼續並將其添加到您的答案。我會看看我是否可以找到不同的方法 –

+0

它是你的答案的改編,而不是我的答案。 'as.list'應該只是'list'。 – Bazz

4

使用Map創建作爲NANA位置矩陣的列表:

naposmtx <- Map(function(mtx1, mtx2){ 
    nasmtx <- mtx1 + mtx2 # because NA + non-NA = NA 
    nasmtx[!is.na(nasmtx)] <- 0 
    nasmtx 
}, lis, bis) 

然後:

lis <- Map(`+`, lis, naposmtx) 
bis <- Map(`+`, bis, naposmtx) 
+0

不錯的選擇,我基準我們的解決方案,他們似乎同樣快(+1) –

+0

謝謝。我會記住'Map'函數 - 這對我來說是新的。 – Bazz

+0

它只是'mapply' with'simplify = FALSE' –