Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R:intersection of matrices

Tags:

r

set

I was expecting this a simple task but to my surprise I am unable to find the solution of this.

I have to perform set operations on matrices. Intersect functions working fine for vectors. But for matrices they consider each column as vector as well. I need result on row - row comparison instead of each element of matrix.

Consider two following matrices

> m1
     [,1] [,2]
[1,]    1    6
[2,]    2    7
[3,]    3    8
[4,]    4    9
[5,]    5   10

and

> m2
     [,1] [,2]
[1,]    1    6
[2,]    3    8
[3,]    4    9
[4,]    5   10
[5,]    6   11

Is there any way to take intersection of both matrices so output must return only first row?

like image 775
mqpasta Avatar asked Mar 23 '23 10:03

mqpasta


2 Answers

The most efficient approach (IMHO) is to do:

If you want to compare row i to row i (what I wouldn't call intersection):

m1[rowSums(m1 == m2) == ncol(m1), , drop = FALSE]

If you want to compare row i to any row j (what I would call intersection):

m3 <- rbind(m1, m2)
m3[duplicated(m3), , drop = FALSE]

This last one assumes that m1 and m2 are sets, i.e. collections of distinct items. If it is not the case, you can make them into sets by passing them through unique: m3 <- rbind(unique(m1), unique(m2)).

Both will be a lot faster than using apply.

like image 65
flodel Avatar answered Mar 31 '23 17:03

flodel


Use this:

m1[apply(m1==m2, 1, all),]

for paired comparisons; and this:

o <- outer(seq_len(nrow(m1)), seq_len(nrow(m2)), Vectorize(
    function(i, j) all(m1[i,]==m2[j,])
))
m1[apply(o, 1, any),]
m2[apply(o, 2, any),]

for all rows in m1 (resp. m2) that are equal to some other row in m2 (resp. m1).

like image 43
Ferdinand.kraft Avatar answered Mar 31 '23 17:03

Ferdinand.kraft