compare the information between two matrices R
我有两个矩阵,一个是通过删除一些行从另一个生成的。例如:
1
2 |
m = matrix(1:18, 6, 3)
m1 = m[c(-1, -3, -6),] |
假设我不知道 m 中的哪些行被删除来创建 m1,我应该如何通过比较两个矩阵来找到它?我想要的结果是这样的:
1
|
1, 3, 6
|
我正在处理的实际矩阵非常大。我想知道是否有任何有效的方法来进行。
这里有一些方法:
1) 如果我们可以假设 m 中没有重复的行——问题示例中就是这种情况——那么:
1
2 |
which(tail(!duplicated(rbind(m1, m)), nrow(m)))
## [1] 1 3 6 |
2) 转置 m 和 m1 给出 tm 和 tm1 因为在列上工作比在行上工作更有效。
定义 match_indexes(i),它返回一个向量 r,使得 m[r, ] 中的每一行都匹配 m1[i, ]。
将其应用于 1:n1 中的每个 i 并从 1:n 中删除结果。
1
2 3 4 5 6 |
n <- nrow(m); n1 <- nrow(m1)
tm <- t(m); tm1 <- t(m1) match_indexes <- function(i) which(colSums(tm1[, i] == tm) == n1) |
3) 计算每个矩阵的交互向量,然后使用 setdiff 最后使用 match 得到索引:
1
2 3 4 |
i <- interaction(as.data.frame(m))
i1 <- interaction(as.data.frame(m1)) match(setdiff(i, i1), i) ## [1] 1 3 6 |
已添加如果 m 中可能有重复项,则 (1) 和 (3) 将仅返回 m 中的任何多次出现的行中的第一个,而不是 m1 中的。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
m <- matrix(1:18, 6, 3)
m1 <- m[c(2, 4, 5),] m <- rbind(m, m[1:2, ]) # 1 which(tail(!duplicated(rbind(m1, m)), nrow(m))) ## 1 3 6 # 2 # 3 |
- 我更喜欢第一个。它也更快。请参阅我的答案中的基准。
- 第一个很棒。但不幸的是,我的 m 矩阵本身有重复的行。不过,我喜欢你在这里提出的新颖方法。谢谢!
- 其实我们可以稍微放宽一下条件。如果m1中有重复的行,m中的重复行也是可以的。如果 m 中有重复的行不在 m1 中,则只有每个多重出现的行中的第一个将包含在输出向量中。这够好吗?
一种可能的方式是将每一行表示为一个字符串:
1
2 3 4 |
x1 <- apply(m, 1, paste0, collapse = ‘;’)
x2 <- apply(m1, 1, paste0, collapse = ‘;’) which(!x1 %in% x2) # [1] 1 3 6 |
使用我的解决方案和 G. Grothendieck 的解决方案对大型矩阵进行一些基准测试:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
set.seed(123)
m <- matrix(rnorm(20000 * 5000), nrow = 20000) m1 <- m[-sample.int(20000, 1000), ] system.time({ system({ match_indexes <- function(i) which(colSums(tm1[, i] == tm) == n1)
system({ |
- 非常感谢你!但我的矩阵 m 实际上是一个包含 14290 行和 4413 个术语的文档术语矩阵。这种方法能处理这么大的矩阵吗?
- @user7453767,这个在那个大矩阵上非常慢。我做了一个测试示例并在几分钟前运行它。它还没有完成。
- 这很有帮助!谢谢@mt1022
我们也可以使用 do.call
1
2 |
which(!do.call(paste, as.data.frame(m)) %in% do.call(paste, as.data.frame(m1)))
#[1] 1 3 6 |
来源:https://www.codenong.com/44402561/