矩阵%in%matrix

时间:2011-10-30 07:02:58

标签: r

假设我有两个矩阵,每个矩阵有两列和不同的行数。我想检查并查看另一个矩阵中哪一对矩阵。如果这些是一维的,我通常会a %in% x来获得我的结果。 match似乎只适用于矢量。

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

我希望结果为c(FALSE,TRUE,TRUE,FALSE)

5 个答案:

答案 0 :(得分:11)

重新创建数据:

a <- matrix(c(1, 2, 4, 9, 1, 6, 7, 7), ncol=2, byrow=TRUE)
x <- matrix(c(1, 6, 2, 7, 3, 8, 4, 9, 5, 10), ncol=2, byrow=TRUE)

定义一个函数%inm%,它是%in%

的矩阵类似物
`%inm%` <- function(x, matrix){
  test <- apply(matrix, 1, `==`, x)
  any(apply(test, 2, all))
}

将此应用于您的数据:

apply(a, 1, `%inm%`, x)
[1] FALSE  TRUE  TRUE FALSE

比较单行:

a[1, ] %inm% x
[1] FALSE

a[2, ] %inm% x
[1] TRUE

答案 1 :(得分:10)

另一种方法是:

> paste(a[,1], a[,2], sep="$$") %in% paste(x[,1], x[,2], sep="$$")
[1] FALSE  TRUE  TRUE FALSE

更通用的版本是:

> apply(a, 1, paste, collapse="$$") %in% apply(x, 1, paste, collapse="$$")
[1] FALSE  TRUE  TRUE FALSE

答案 2 :(得分:10)

Andrie的解决方案非常好。但是如果你有大矩阵,你可能想尝试基于递归的其他东西。如果您按列工作,则可以通过排除第一个位置不匹配的所有内容来减少计算时间:

fastercheck <- function(x,matrix){
  nc <- ncol(matrix)
  rec.check <- function(r,i,id){
    id[id] <- matrix[id,i] %in% r[i]
    if(i<nc & any(id)) rec.check(r,i+1,id) else any(id)
  }
  apply(x,1,rec.check,1,rep(TRUE,nrow(matrix)))
}

比较:

> set.seed(100)
> x <- matrix(runif(1e6),ncol=10)
> a <- matrix(runif(300),ncol=10)
> a[c(3,7,9,15),] <- x[c(1000,48213,867,20459),]
> system.time(res1 <- a %inm% x)
   user  system elapsed 
  31.16    0.14   31.50 
> system.time(res2 <- fastercheck(a,x))
   user  system elapsed 
   0.37    0.00    0.38 
> identical(res1, res2)
[1] TRUE
> which(res2)
[1]  3  7  9 15

编辑:

我检查了接受的答案只是为了好玩。执行比双重应用更好(因为你摆脱内部循环),但递归仍然规则! ; - )

> system.time(apply(a, 1, paste, collapse="$$") %in% 
 + apply(x, 1, paste, collapse="$$"))
   user  system elapsed 
   6.40    0.01    6.41 

答案 3 :(得分:5)

以下是使用digest包并为每行创建checksums的另一种方法,这些方法是使用散列算法生成的(默认为md5

a <- matrix(c(1, 2, 4, 9, 1, 6, 7, 7), ncol=2, byrow=TRUE)
x <- matrix(c(1, 6, 2, 7, 3, 8, 4, 9, 5, 10), ncol=2, byrow=TRUE)
apply(a, 1, digest) %in% apply(x, 1, digest)

[1] FALSE  TRUE  TRUE FALSE

答案 4 :(得分:1)

来到游戏后期:我之前使用“使用分隔符粘贴”方法编写了算法,然后找到了此页面。我猜这里的代码片段之一是最快的,但是:

andrie<-function(mfoo,nfoo) apply(mfoo, 1, `%inm%`, nfoo)
# using Andrie's %inm% operator exactly as above
carl<-function(mfoo,nfoo) {
 allrows<-unlist(sapply(1:nrow(mfoo),function(j) paste(mfoo[j,],collapse='_'))) 
 allfoo <- unlist(sapply(1:nrow(nfoo),function(j) paste(nfoo[j,],collapse='_')))
 thewalls<-setdiff(allrows,allfoo)
 dowalls<-mfoo[allrows%in%thewalls,]
}

 ramnath <- function (a,x) apply(a, 1, digest) %in% apply(x, 1, digest)

 mfoo<-matrix( sample(1:100,400,rep=TRUE),nr=100)
 nfoo<-mfoo[sample(1:100,60),]

 library(microbenchmark)
 microbenchmark(andrie(mfoo,nfoo),carl(mfoo,nfoo),ramnath(mfoo,nfoo),times=5)

Unit: milliseconds
                expr       min        lq    median        uq            max neval
  andrie(mfoo, nfoo) 25.564196 26.527632 27.964448 29.687344     102.802004     5
    carl(mfoo, nfoo)  1.020310  1.079323  1.096855  1.193926       1.246523     5
 ramnath(mfoo, nfoo)  8.176164  8.429318  8.539644  9.258480       9.458608     5

所以显然构造字符串并进行单组操作是最快的! (PS我检查过,所有3种算法都给出了相同的结果)