Search code examples
rmatrixmedian

Elementwise Median of 3 matrices in R


I have 3 matrices storing triplicate measurements in each matrix (matrix 1, measurement 1, matrix 2 measurement 2, .....)

They have the following structure:

> a1
            ACTIN       18S      TET1      TET2      TET3
Control 25.943441  22.62984      <NA> 34.063107 34.034756
Sample1  24.48504  20.04858      <NA>  32.37173 32.341072
Sample2 25.265867 19.680647 28.086248  33.76187  33.41289
Sample3 24.441484 18.146513      <NA> 32.811428  31.22825
> a2
            ACTIN       18S      TET1      TET2      TET3
Control 25.980696 22.393877      <NA> 34.548923   33.7815
Sample1 24.263775 20.073978  27.23082  32.27775 32.343292
Sample2  25.25487 19.680494 27.214449  33.70534  33.48968
Sample3  24.26332 18.108198      <NA> 32.769787  31.19895
> a3
            ACTIN       18S      TET1      TET2      TET3
Control 25.937397 22.429556 30.020935  33.98415 33.858604
Sample1  24.44776 20.090088 28.328804 32.317287 32.291912
Sample2 25.148333 19.537455      <NA>  33.83607   33.3961
Sample3 24.242998 18.335524      <NA> 32.788536 31.147346

I would like to create a new matrix with the medians of the 3 measurements. Idealy with the 1st column staying the same. Giving NA if there is not a value (the Undetermined) is prefered

I would like to have a matrix with the medians, so something like this:

median(a1[i,j], a2[i,j], a2[i,j])

I tried the following: 2 for loops cycling over the arrays:

med<-matrix(NA, nrow(a1), ncol(a1))    
for(i in ncol(a1)){
      for(j in nrow(a1)){
        med[i,j]<-median(a1[i,j], a2[i,j], a2[i,j])
      }
    }

but this gives me values that are clearly not the median and I feel it is overly complicated.

Thanks!


Solution

  • You can use mapply and reshape the resulting matrix. Assuming your data is initially a character matrix which I infer from <NA>, a reproducible solution would be like:

    dat <- mapply(function(...) median(as.numeric(c(...))), a1, a2, a3)
    # this gives a warning message but you can ignore this which comes up when it converts the character `NA` to numeric `NA`;
    matrix(dat, nrow(a1), ncol(a1), dimnames = dimnames(a1))
    
    #            ACTIN     X18S TET1     TET2     TET3
    # Control 25.94344 22.42956   NA 34.06311 33.85860
    # Sample1 24.44776 20.07398   NA 32.31729 32.34107
    # Sample2 25.25487 19.68049   NA 33.76187 33.41289
    # Sample3 24.26332 18.14651   NA 32.78854 31.19895
    

    Data:

    a1 <- structure(c("25.94344", "24.48504", "25.26587", "24.44148", "22.62984", 
    "20.04858", "19.68065", "18.14651", "<NA>", "<NA>", "28.086248", 
    "<NA>", "34.06311", "32.37173", "33.76187", "32.81143", "34.03476", 
    "32.34107", "33.41289", "31.22825"), .Dim = 4:5, .Dimnames = list(
        c("Control", "Sample1", "Sample2", "Sample3"), c("ACTIN", 
        "X18S", "TET1", "TET2", "TET3")))
    
    a2 <- structure(c("25.98070", "24.26377", "25.25487", "24.26332", "22.39388", 
    "20.07398", "19.68049", "18.10820", "<NA>", "27.23082", "27.214449", 
    "<NA>", "34.54892", "32.27775", "33.70534", "32.76979", "33.78150", 
    "32.34329", "33.48968", "31.19895"), .Dim = 4:5, .Dimnames = list(
        c("Control", "Sample1", "Sample2", "Sample3"), c("ACTIN", 
        "X18S", "TET1", "TET2", "TET3")))
    
    a3 <- structure(c("25.93740", "24.44776", "25.14833", "24.24300", "22.42956", 
    "20.09009", "19.53746", "18.33552", "30.020935", "28.328804", 
    "<NA>", "<NA>", "33.98415", "32.31729", "33.83607", "32.78854", 
    "33.85860", "32.29191", "33.39610", "31.14735"), .Dim = 4:5, .Dimnames = list(
        c("Control", "Sample1", "Sample2", "Sample3"), c("ACTIN", 
        "X18S", "TET1", "TET2", "TET3")))