3

I have a list of matrix or matrix-like list. each matrix contains many NAs. Now I want to add all matrix up to a single matrix. (each matrix has the same dimension and dimnames)

a   
           V1          V2          V3           
      [1,]  NA        4         21
      [2,]  NA        NA        4 

b   
           V1          V2          V3            
      [1,]  NA       NA           1
      [2,]  5        0           12

# mylist = list(a,b)

after calculation, I want a result like

        V1          V2          V3            
  [1,]   NA       4           22
  [2,]   5        0           16   

SO I have two constraints:

constraint 1: keep (NA+NA)=NA
constraint 2: keep (NA+1) = 1

I have try the Reduce and apply(simplify2array(.list), c(1,2), sum, na.rm=T) functions as in the following page, but I cannot keep both constraints in the calculation.

Sum a list of matrices

Personally, using above example, I use the is.na to identify all the NA in each matrix, overlap logical values of each elements (a+b) , means if corresponding cells are all NAs, return length(mylist), say 2. then replace corresponding celss with NA

c = is.na(a)  return 

           V1          V2          V3           
      [1,] 1        0         0
      [2,] 1        1         0 

d = is.na(b)  return 

           V1          V2          V3            
      [1,]  1        1           0
      [2,]  0        0           0

identify.na = c + d return 
           V1          V2          V3            
      [1,]  2        1           0
      [2,]  1        1           0

result[identify.na==2] = NA

example is not the exactly code in R, just for example. Thanks in advance.

Community
  • 1
  • 1
Tao Zhang
  • 45
  • 4

1 Answers1

4

We can cbind the vectors to a matrix ('m1'), get the rowSums of 'm1' to create 'v2', and of logical matrix to create 'v1'. Replace the elements in 'v2' that are 0 in 'v1' to NA.

 m1 <- cbind(a, b)
 v1 <- rowSums(!is.na(m1))
 v2 <- rowSums(m1, na.rm=TRUE)
 v2[!v1] <- NA
 #[1] NA  1  5  0

Update

We can place the matrices in a list, replace, the NA elements with 0, get the sum using Reduce. We get the sum of logical matrix (non-NA elements) with the same method, negate it so that 0 values becomes TRUE and 1 as FALSE, replace the TRUE with NA (NA^..) and multiply with the first output.

l1 <- list(a1, b1)
res <- Reduce(`+`, lapply(l1, function(x)
                      replace(x, is.na(x), 0)))
res*NA^!Reduce(`+`, lapply(l1, function(x) !is.na(x)))
#     [,1] [,2] [,3]
#[1,]   NA    4   22
#[2,]    5    0   16

data

 a <- c(NA, 1, 2, -1)
 b <- c(NA, NA, 3, 1)
 a1 <- matrix(c(NA, NA, 4, NA, 21, 4), ncol=3)
 b1 <- matrix(c(NA, 5, NA, 0, 1, 12), ncol=3)
akrun
  • 874,273
  • 37
  • 540
  • 662