当订单在R中有问题时,在矩阵中查找向量

时间:2016-02-08 15:14:21

标签: r matrix

我有一个矩阵说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中这样做?感谢

4 个答案:

答案 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)),]