简体   繁体   中英

Replace the elements in a matrix with NA for those with row and column names not stored in a dataframe

Suppose I have a matrix rmatrix defined below:

set.seed(10)
rmatrix  <-  matrix(sample(0:100, 16), ncol=4)
dimnames(rmatrix) <- list(rownames(rmatrix, do.NULL = FALSE, 
   prefix = "row"), colnames(rmatrix, do.NULL = FALSE, prefix = "col"))
rmatrix

     col1 col2 col3 col4
row1   51    8   57   10
row2   30   21   39   52
row3   42   26   59   31
row4   67   25  100   36

A dataframe df stores some combinations of the row and column names of rmatrix :

df <- data.frame(r = c('row1', 'row1', 'row3', 'row4', 'row4', 'row4'), 
   c = c('col2', 'col4', 'col3', 'col3', 'col1', 'col2'))
df
     r    c
1 row1 col2
2 row1 col4
3 row3 col3
4 row4 col3
5 row4 col1
6 row4 col2

How to change any element in rmatrix to NA if its names are not in df ? Thanks!

out = replace(rmatrix*NA, as.matrix(df), rmatrix[as.matrix(df)])
out
#     col1 col2 col3 col4
#row1   NA    8   NA   10
#row2   NA   NA   NA   NA
#row3   NA   NA   59   NA
#row4   67   25  100   NA

The following would work even when rmatrix is made of characters

replace(replace(rmatrix, TRUE, NA), as.matrix(df), rmatrix[as.matrix(df)])

We can do this directly based on setdiff

library(dplyr)
rmatrix[as.matrix(setdiff(data.frame(r = rownames(rmatrix)[row(rmatrix)],
     c= colnames(rmatrix)[col(rmatrix)]), df))] <- NA
rmatrix
#     col1 col2 col3 col4
#row1   NA    8   NA   10
#row2   NA   NA   NA   NA
#row3   NA   NA   59   NA
#row4   67   25  100   NA

Or another option is to create a new matrix of NAs and then fill it with values based on the index in 'df'

m1 <- sapply(df, function(x) as.numeric(gsub("\\D+", "", x)))
rmatrix2 <- matrix(NA, nrow = nrow(rmatrix), ncol = ncol(rmatrix), 
                     dimnames = dimnames(rmatrix))
rmatrix2[m1] <- rmatrix[m1]
rmatrix2
#     [,1] [,2] [,3] [,4]
#[1,]   NA    8   NA   10
#[2,]   NA   NA   NA   NA
#[3,]   NA   NA   59   NA
#[4,]   67   25  100   NA

Or we can create a sparseMatrix

library(Matrix)
r1 <- sparseMatrix(i = match(df[[1]], row.names(rmatrix)), 
   j = match(df[[2]], colnames(rmatrix)), x = rmatrix[as.matrix(df)])
r1
#  4 x 4 sparse Matrix of class "dgCMatrix"

#[1,]  .  8   . 10
#[2,]  .  .   .  .
#[3,]  .  .  59  .
#[4,] 67 25 100  .

If we need to get the NA values

(NA^!r1)*r1
#4 x 4 Matrix of class "dgeMatrix"
#     [,1] [,2] [,3] [,4]
#[1,]   NA    8   NA   10
#[2,]   NA   NA   NA   NA
#[3,]   NA   NA   59   NA
#[4,]   67   25  100   NA

This can be converted to a normal matrix by wrapping with as.matrix

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM