check whether matrix rows equal a vector in R , ve

2019-02-22 02:35发布

问题:

I'm very surprised this question has not been asked, maybe the answer will clear up why. I want to compare rows of a matrix to a vector and return whether the row == the vector everywhere. See the example below. I want a vectorized solution, no apply functions because the matrix is too large for slow looping. Suppose there are many rows as well, so I would like to avoid repping the vector.

set.seed(1)

M = matrix(rpois(50,5),5,10)

v = c(3 ,   2 ,   7  ,  7 ,   4   , 4   , 7  ,  4  ,  5, 6)

M
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    4    8    3    5    9    4    5    6    7     7
[2,]    4    9    3    6    3    1    5    7    6     1
[3,]    5    6    6   11    6    4    5    2    7     5
[4,]    8    6    4    4    3    8    3    6    5     6
[5,]    3    2    7    7    4    4    7    4    5     6

Output should be

FALSE  FALSE FALSE FALSE TRUE

回答1:

One possibility is

rowSums(M == v[col(M)]) == ncol(M)
## [1] FALSE FALSE FALSE FALSE  TRUE

Or simlarly

rowSums(M == rep(v, each = nrow(M))) == ncol(M)
## [1] FALSE FALSE FALSE FALSE  TRUE

Or

colSums(t(M) == v) == ncol(M)
## [1] FALSE FALSE FALSE FALSE  TRUE

v[col(M)] is just a shorter version of rep(v, each = nrow(M)) which creates a vector the same size as M (matrix is just a vector, try c(M)) and then compares each element against its corresponding one using ==. Fortunately == is a generic function which has an array method (see methods("Ops") and is.array(M)) which allows us to run rowSums (or colSums) on it in order to makes sure we have the amount of matches as ncol(M)



回答2:

Using DeMorgan's rule (Not all = Some not), then All equal = Not Some Not equal, we also have

!colSums(t(M) != v)


回答3:

The package prodlim has a function called row.match, which is easy to use and ideal for your problem. First install and load the library: library(prodlim). In our example, row.match will return '5' because the 5th row in M is equal to v. We can then convert this into a logical vector.

m <- row.match(v, M)
m==1:NROW(M)#[1] FALSE FALSE FALSE FALSE  TRUE