在R中,用于矩阵的行或列的匹配函数

10

R中的值匹配函数非常有用。但据我理解,它不足以支持两个或高维输入。

例如,假设xy是具有相同列数的矩阵,并且我想将x的行与y的行匹配。 'R'函数调用match(x,y)不能实现此目的。同样的不足也会出现在列表输入中。

我已经实现了自己的版本,称为matchMat(xMat, yMat)(如下所示),但我想知道你对这个任务的解决方案。

matchMat = function(xMat, uMat, dimn=1) {
    ind = rep(-1, dim(xMat)[dimn])
    id = 1 : dim(uMat)[dimn]
    for (i in id) {
        e = utilSubMat(i, uMat, dimn)
        isMatch = matchVect(e, xMat, dimn)
        ind[isMatch] = i
    }
    return(ind)
}

matchVect = function(v, xMat, dimn) {
    apply(xMat, dimn, function(e) {
        tf = e == v
        all(tf)
    })
}

unittest_matchMat = function() {
    dimn = 1
    uMat = matrix(c(1, 2, 2, 3, 3, 4, 4, 5), ncol=2, byrow=T)
    ind = sample(dim(uMat)[1], 10, replace=T)
    print(ind)
    xMat = uMat[ind, ]
    rst = matchMat(xMat, uMat, dimn)
    print(rst)
    stopifnot(all(ind == rst))

    xMat2 = rbind(c(999, 999), xMat, c(888, 888))
    rst2 = matchMat(xMat2, uMat, dimn)
    print(rst2)
    stopifnot(all(c(-1, ind, -1) == rst2))
    print('pass!')   
}
5个回答

24

match 可以用于原子向量的 list。因此,为了将一个矩阵的行匹配到另一个矩阵中,您可以执行以下操作:

match(data.frame(t(x)), data.frame(t(y)))

t 将行转置为列,然后 data.frame 在转置矩阵中创建列的列表。


3
这是一个最简示例,我想知道为什么它不起作用:A <- data.frame(x = 1:6, y = 2:7)B <- data.frame(x = 1:8, y = c(2:8, 10))match(data.frame(t(A)), data.frame(t(B)))。它只输出 [1] NA NA NA NA NA NA - Liang Zhang
原因是 class(c(2:7)) 返回 [1] "integer",而 class(c(2:8, 10)) 返回 [1] "numeric"。如果列表中不包含相同类型的数据,则它们不相同,但这证明了这种解决方案不方便使用。 - Jean Paul

5

prodlim包中,函数row.match可以让您识别一个矩阵中与另一个矩阵相同(完全相同)的行。非常方便易用。

library(prodlim)
row.match(x,y)

似乎这只返回了第一个匹配项,而不是所有的。 - derp92
@derp92 match 做的事情完全相同。从文档中可以看到:match 返回第一个参数在第二个参数中匹配的位置向量。 - Jean Paul

3
您可以使用 asplit 创建一个list,然后可以将其用于匹配。但是手册上说列表会被转换为字符向量列表匹配可能非常缓慢,除非在简单情况下最好避免使用
match(asplit(x, 1), asplit(y, 1))
#[1] NA  1  2

因此,也许使用 interactionpaste 是一种选择。

match(interaction(data.frame(x)), interaction(data.frame(y)))
#[1] NA  1  2

match(apply(x, 1, paste, collapse =" "), apply(y, 1, paste, collapse =" "))
#[1] NA  1  2

数据:

(x <- matrix(1:9, 3))
#     [,1] [,2] [,3]
#[1,]    1    4    7
#[2,]    2    5    8
#[3,]    3    6    9

(y <- matrix(2:10, 3))
#     [,1] [,2] [,3]
#[1,]    2    5    8
#[2,]    3    6    9
#[3,]    4    7   10

2

不使用任何函数也可以实现这一点:

假设adj1是一个3*3矩阵,它的colnamesrow.names都是c('V1','V2','V3')vec1是你想要将矩阵转换成的顺序:

vec1 <- c('V2','V3','V1')

您可以直接使用以下代码:
adj1[vec1,vec1]

这将为你带来神奇的效果。

干杯!


0
您可以使用 apply
z <- apply(x, 1, function(a) apply(y, 1, function(b) all(a==b)))

这将生成一个矩阵,其行数为nrow(x),列数为nrow(y),其条目标记了匹配的索引。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接