找到等于vector的所有矩阵行

时间:2015-03-30 11:39:47

标签: r

假设我有以下矩阵:

cm<-structure(c(100, 200, 400, 800, 100, 200, 400, 800, 100, 200, 
400, 800, 100, 200, 400, 800, 100, 200, 400, 800, 0, 0, 0, 0, 
0.5, 0.5, 0.5, 0.5, 1, 1, 1, 1, 0, 0, 0, 0, 0.5, 0.5, 0.5, 0.5, 
-0.4, -0.4, -0.4, -0.4, -0.4, -0.4, -0.4, -0.4, -0.4, -0.4, -0.4, 
-0.4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1), .Dim = c(20L, 4L), .Dimnames = list(
    NULL, c("Var1", "Var2", "Var3", "n1")))

和另一个衍生自它的矩阵:

a4<-data.matrix(unique(cm[,1:3]))

现在,我想查找cm的前三行等于a4[1,]的所有行,但是做了直观的事情:

a5<-which(cm[,1:3]==a4[1,])

失败(R 3.1.3)。例如,a5[2]为13,但cm[,1:3]的第13行与a4[1,]相同。

3 个答案:

答案 0 :(得分:7)

row.match中的prodlim功能易于使用,非常适合您的问题。

library(prodlim)
row.match(a4[1,], cm[,1:3])
[1] 1

答案 1 :(得分:6)

使用applyall.equal将每一行与目标行进行比较。使用==的问题在于它只检查它回收矢量的元素以进行比较,而你想要查看行矢量中的所有值是否与a4[1,]匹配,因此你应该使用all.equal }。结果是它的返回值不是逻辑,而是描述对象之间差异的字符串,这使得使用它比单独使用==更麻烦:

which(apply(cm, 1, function(x) all.equal(x[1:3], a4[1,])) == "TRUE")
# [1] 1

使用identical代替all.equal,您也可以更简单一点:

which(apply(cm, 1, function(x) identical(x[1:3], a4[1,])))
# [1] 1

然后提取:

cm[apply(cm, 1, function(x) identical(x[1:3], a4[1,])),,drop=FALSE]
#      Var1 Var2 Var3 n1
# [1,]  100    0 -0.4  1

为了明确说明发生了什么,请在传递矩阵参数时考虑==隐含的内容:

which(cm[,1:3]==a4[1,])
# [1]  1 13 23 35 42 45 48 51 53 56 59

该结果与将矩阵转换为矢量相同:

as.vector(cm[,1:3])
#  [1] 100.0 200.0 400.0 800.0 100.0 200.0 400.0 800.0 100.0 200.0 400.0 800.0 100.0 200.0 400.0 800.0 100.0 200.0 400.0 800.0   0.0   0.0   0.0   0.0   0.5   0.5   0.5
# [28]   0.5   1.0   1.0   1.0   1.0   0.0   0.0   0.0   0.0   0.5   0.5   0.5   0.5  -0.4  -0.4  -0.4  -0.4  -0.4  -0.4  -0.4  -0.4  -0.4  -0.4  -0.4  -0.4   0.0   0.0
# [55]   0.0   0.0   0.0   0.0   0.0   0.0
which(as.vector(cm[,1:3])==a4[1,])
# [1]  1 13 23 35 42 45 48 51 53 56 59

因此,位置是cm的向量表示内的位置,而不是矩阵表示中的行。当试图比较不等长的矢量或者一个矢量的长度不是另一个矢量的倍数时,==比较也可能是危险的(再次对上面提到的回收做),这会产生警告:

1:2 == 1:3
# [1]  TRUE  TRUE FALSE
# Warning message:
# In 1:2 == 1:3 :
#   longer object length is not a multiple of shorter object length

使用回收时没有警告:

1:2 == 1:6
# [1]  TRUE  TRUE FALSE FALSE FALSE FALSE

答案 2 :(得分:1)

将要匹配的行和主表存储为数据帧并调用plyr的match_df。

首先,了解匹配过程。

plyr::match_df(data.frame(cm[,1:3]),
           data.frame(t(a4[1,])))

# Matching on: Var1, Var2, Var3
# Var1 Var2 Var3
# 1  100    0 -0.4

现在,使用另一个案例。使用两列匹配并提取行号以对数据帧进行切片。

cm[plyr::match_df(data.frame(cm[,c(1,3)]),
               data.frame(t(cm[3,c(1,3)]))) %>% rownames() %>% as.numeric(),]

# 
# Matching on: Var1, Var3
# Var1 Var2 Var3 n1
# [1,]  400  0.0 -0.4  1
# [2,]  400  0.5 -0.4  1
# [3,]  400  1.0 -0.4  1