user1234440
user1234440

Reputation: 23567

Search a matrix for rows with given values in any order

I have a matrix and a vector with values:

mat<-matrix(c(1,1,6,
              3,5,2,
              1,6,5,
              2,2,7,
              8,6,1),nrow=5,ncol=3,byrow=T)

vec<-c(1,6)

This is a small subset of a N by N matrix and 1 by N vector. Is there a way so that I can subset the rows with values in vec?

The most straight forward way of doing this that I know of would be to use the subset function:

subset(mat,vec[,1] == 1 & vec[,2] == 6) #etc etc

The problem with subset is you have to specify in advance the column to look for and the specific combination to do for. The problem I am facing is structured in a way such that I want to find all rows containing the numbers in "vec" in any possible way. So in the above example, I want to get a return matrix of:

1,1,6
1,6,5
8,6,1

Any ideas?

Upvotes: 0

Views: 696

Answers (1)

Ricardo Saporta
Ricardo Saporta

Reputation: 55340

You can do

apply(mat, 1, function(x) all(vec %in% x))
#  [1]  TRUE FALSE  TRUE FALSE  TRUE

but this may give you unexpected results if vec contains repeated values:

vec <- c(1, 1)
apply(mat, 1, function(x) all(vec %in% x))
# [1]  TRUE FALSE  TRUE FALSE  TRUE

so you would have to use something more complicated using table to account for repetitions:

vec <- c(1, 1)
is.sub.table <- function(table1, table2) {
  all(names(table1) %in% names(table2)) &&
  all(table1 <= table2[names(table1)])
}
apply(mat, 1, function(x)is.sub.table(table(vec), table(x)))
# [1]  TRUE FALSE FALSE FALSE FALSE

However, if the vector length is equal to the number of columns in your matrix as you seem to indicate but is not the case in your example, you should just do:

vec <- c(1, 6, 1)
apply(mat, 1, function(x) all(sort(vec) == sort(x)))
# [1]  TRUE FALSE FALSE FALSE FALSE

Upvotes: 1

Related Questions