假设我有两个矩阵,每个矩阵有两列和不同的行数。我想检查并查看另一个矩阵中哪一对矩阵。如果这些是一维的,我通常会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)
。
答案 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种算法都给出了相同的结果)