我有一个矩阵说m
如下:
> m
[,1] [,2] [,3] [,4] [,5]
[1,] 4 1 5 2 3
[2,] 5 2 3 4 1
[3,] 3 4 1 5 2
[4,] 1 5 2 3 4
[5,] 2 3 4 1 5
[6,] 4 1 5 2 3
[7,] 5 2 3 4 1
[8,] 3 4 1 5 2
和名为vec
的向量如下:
> vec
[1] 3 1
我想以相同的顺序查找m
中包含vec
的所有行。例如结果应该是(注意第一,第四和第六行不感兴趣):
> res
[2,] 5 2 3 4 1
[3,] 3 4 1 5 2
[5,] 2 3 4 1 5
[7,] 5 2 3 4 1
[8,] 3 4 1 5 2
请告诉我如何在R中这样做?感谢
答案 0 :(得分:4)
这是一般解决方案。我们可以为vec
创建一个正则表达式模式,然后根据数据进行检查,并将其组合成每行的一组字符串:
v2 <- paste(vec, collapse=".*?")
df.vec <- do.call(paste, as.data.frame(m))
m[grep(v2, df.vec),]
# [,1] [,2] [,3] [,4] [,5]
# [2,] 5 2 3 4 1
# [3,] 3 4 1 5 2
# [5,] 2 3 4 1 5
# [7,] 5 2 3 4 1
# [8,] 3 4 1 5 2
答案 1 :(得分:3)
以下是使用apply
的选项:
> m[apply(m, 1, function(x) all(c(3,1) %in% x) & which(x == 3) < which(x == 1)),]
# V2 V3 V4 V5 V6
#2 5 2 3 4 1
#3 3 4 1 5 2
#5 2 3 4 1 5
#7 5 2 3 4 1
#8 3 4 1 5 2
以下是任何向量的一般解决方案:
> vec <- c(3,4,1,5)
> m[apply(m, 1, function(x) all(vec %in% x) & all(diff(sapply(vec, function(y) which(x == y))) > 0)),]
# V2 V3 V4 V5 V6
#3 3 4 1 5 2
#5 2 3 4 1 5
#8 3 4 1 5 2
我把它放在一个更方便使用的功能中:
f <- function(m, vec) m[apply(m, 1, function(x) all(vec %in% x) & all(diff(sapply(vec, function(y) which(x == y))) > 0)),]
f(m, c(3,1,5))
# V2 V3 V4 V5 V6
#3 3 4 1 5 2
#5 2 3 4 1 5
#8 3 4 1 5 2
答案 2 :(得分:2)
又一次尝试。
由于(1)m[i, ]
和vec
是无重复的,并且(2)m
是排列因此ncol(m) << nrow(m)
您可以测试每个后续列是否与后续元素匹配vec
比前一列更多。
ff = function(mat, vec)
{
matched = array(match(mat, vec, 0L), dim(mat))
ans = seq_len(nrow(mat))
for(j in 2:ncol(mat)) {
zeroj = ans[matched[ans, j] == 0L]
matched[zeroj, j] = matched[zeroj, j - 1L]
ans = ans[matched[ans, j] >= matched[ans, j - 1L]]
}
ans
}
ff(m, c(3, 1))
#[1] 2 3 5 7 8
使用修改版本的akrun(最快)答案对大型数据进行基准测试:
akrun = function(mat, vec)
which(!apply(mat, 1L, function(x) is.unsorted(match(vec, x))))
set.seed(007); MAT = do.call(rbind, replicate(1e6, sample(15), simplify = FALSE)); VEC = sample(15, 8)
system.time({ ansff = ff(MAT, VEC) })
# user system elapsed
# 0.70 0.08 0.78
system.time({ ansakrun = akrun(MAT, VEC) })
# user system elapsed
# 5.28 0.06 5.35
all.equal(ansff, ansakrun)
#[1] TRUE
答案 3 :(得分:1)
我们可以尝试
m1[apply(m1, 1, function(x) {n1 <- match(vec,x)
n1[1] <n1[2]}),]
# v1 v2 v3 v4 v5
#[1,] 5 2 3 4 1
#[2,] 3 4 1 5 2
#[3,] 2 3 4 1 5
#[4,] 5 2 3 4 1
#[5,] 3 4 1 5 2
或者
m1[apply(m1, 1, function(x) all(diff(match(vec, x))>0)),]