2016-01-21 15 views
5

Ich habe zwei Listen und ich möchte sie in Bezug auf NA konsistent machen. Put NA Wenn NA in einer der beiden Listen ist, ohne sich in der Struktur der Liste zu ändern.Wie behandelt man NA in zwei Listen?

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) 

habe ich versucht, dies aber ohne Erfolg bis[is.na(lis)]=NA

gewünschte Ausgabe:

> 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 

Antwort

3

Hier ist eine Option:

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) 

Es gibt jedoch schneller sein kann/effizientere Ansätze aufgrund der zahlreichen Map und lapply Anrufe.


Für den Fall von> 2 Listen können Sie die folgende Methode verwenden (unter der Annahme, dass jede Liste die gleiche Länge hat):

# 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) 

Jetzt ist Ihre ursprünglichen Listen im globalen Umfeld verändert werden.

Probendaten:

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

Ersetzen die erste Zeile mit: 'z <- Map (funct ion (...) {dots <- as.list (...); arr <- do.call (abind, c (Punkte, entlang = 3)); apply (arr, 1: 2, beliebig)}, lapply (lis, is.na), lapply (bis, is.na)) '. Ich denke, das sollte funktionieren. Wahrscheinlich langsamer. Benötigt das 'abind'-Paket. Key ersetzt '|' durch 'any'. – Bazz

+0

@Bazz, bitte gehen Sie voran und fügen Sie es Ihrer Antwort hinzu. Ich werde sehen, ob ich eine andere Annäherung –

+0

finden kann, es ist eine Anpassung Ihrer Antwort, nicht meins. 'as.list' sollte nur' liste' sein. – Bazz

4

Map Verwenden einer Liste von Matrizen mit den NA Positionen als NA zu erzeugen:

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

Dann:

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

Schöne Option, ich habe unsere Lösungen bewertet und sie erscheinen gleich schnell (+1) –

+0

Vielen Dank. Ich werde die "Map" -Funktion im Hinterkopf behalten - das ist neu für mich. – Bazz

+0

Es ist einfach 'mapply' mit' simplify = FALSE' –