Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R: Easier way to change 0s in list of matrices into NAs?

Tags:

list

r

na

I want to convert all 0s in the matrices of a list into NAs. I figured out a way how to achieve this task. However, it is too complex and I think there should be an easy way how to do it. Here some example data:

ABlue <- list("111.2012"=matrix(c(1, 0, 6, 0, 1, 0),
                            nrow = 1, byrow = T),
          "112.2012"=matrix(c(6, 2, 2, 0, 3, 1),
                            nrow = 1, byrow = T),
          "111.2011"=matrix(c(3, 2, 0, 0, 1, 9),
                            nrow = 1, byrow = T),
          "112.2011"=matrix(c(1, 2, 0, 0, 7, 0),
                            nrow = 1, byrow = T))
CNTRYs <- c("USA", "GER", "UK", "IT", "CND", "FRA")
ABlue <- lapply(ABlue  , "colnames<-",  CNTRYs ) # gets names from Country list

Important is that the original matrices already have Country names as colnames, so it would be nice to match with this list (ABlue).

Here the way I use until now:

ABlue.df<-data.frame(do.call("rbind",ABlue)) # two step approach to replace 0 with NA according to: "http://stackoverflow.com/questions/22870198/is-there-a-more-efficient-way-to-replace-null-with-na-in-a-list"
ABlue.df.withNA <- sapply(ABlue.df, function(x) ifelse(x == 0, NA, x))
ABlueNA <- split(ABlue.df.withNA, 1:NROW(ABlue.df.withNA)) # is again a list (of vectors)  
names(ABlueNA) <- names(ABlue) # list with old names
ABlueNAdf <- lapply(ABlueNA, function(x) as.data.frame(x)) # turned into list of dfs of one column
ABlueNAdfT <- lapply(ABlueNAdf, function(x) t(x)) # transponed to list of dfs of one row and 206 cols
ABlueNAdfTnam <- lapply(ABlueNAdfT  , "colnames<-",  CNTRYs ) # gets names from Country list
ABlueNAdfTnam <- lapply(ABlueNAdfTnam  , "rownames<-",  1:NROW(ABlueNAdfTnam[1]) )
ABlue2 <- ABlueNAdfTnam

Ideas how to reduce lines and complexity? Thanks

Edit: I want to have the same structure as in the original data!

like image 210
N.Varela Avatar asked Dec 18 '15 09:12

N.Varela


1 Answers

You can use replace, like this:

lapply(ABlue, function(x) replace(x, x == 0, NA))
# $`111.2012`
#      USA GER UK IT CND FRA
# [1,]   1  NA  6 NA   1  NA
# 
# $`112.2012`
#      USA GER UK IT CND FRA
# [1,]   6   2  2 NA   3   1
#
# $`111.2011`
#      USA GER UK IT CND FRA
# [1,]   3   2 NA NA   1   9
#
# $`112.2011`
#      USA GER UK IT CND FRA
# [1,]   1   2 NA NA   7  NA

Or, as @roland suggested:

lapply(ABlue, function(x) {x[x == 0] <- NA; x})

Or, if you have a pipe addiction:

library(purrr)
ABlue %>% map(~ replace(.x, .x == 0, NA))
like image 153
A5C1D2H2I1M1N2O1R2T1 Avatar answered Oct 03 '22 03:10

A5C1D2H2I1M1N2O1R2T1