关于矩阵:比较两个矩阵R之间的信息 | 珊瑚贝

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)
setdiff(1:n, unlist(lapply(1:n1, match_indexes)))
## [1] 1 3 6

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
n <- nrow(m); n1 <- nrow(m1)
tm <- t(m); tm1 <- t(m1)
match_indexes <- function(i) which(colSums(tm1[, i] == tm) == n1)
setdiff(1:n, unlist(lapply(1:n1, match_indexes)))
## 1 3 6 7

# 3
i <- interaction(as.data.frame(m))
i1 <- interaction(as.data.frame(m1))
match(setdiff(i, i1), i)
## 1 3 6

  • 我更喜欢第一个。它也更快。请参阅我的答案中的基准。
  • 第一个很棒。但不幸的是,我的 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({
    which(tail(!duplicated(rbind(m1, m)), nrow(m)))
})
#    user  system elapsed
# 339.888   2.368 342.204
system.time({
    x1 <- apply(m, 1, paste0, collapse = ‘;’)
    x2 <- apply(m1, 1, paste0, collapse = ‘;’)
    which(!x1 %in% x2)
})
#    user  system elapsed
# 395.428   0.568 395.955

system({
    n <- nrow(m); n1 <- nrow(m1)
    tm <- t(m); tm1 <- t(m1)

    match_indexes <- function(i) which(colSums(tm1[, i] == tm) == n1)
    setdiff(1:n, unlist(lapply(1:n1, match_indexes)))
})
# > 15 min, not finish

system({
    i <- interaction(as.data.frame(m))
    i1 <- interaction(as.data.frame(m1))
    match(setdiff(i, i1), i)
})
# run out of memory. My 32G RAM machine crashed.

  • 非常感谢你!但我的矩阵 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/

微信公众号
手机浏览(小程序)

Warning: get_headers(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(): Failed to enable crypto in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

Warning: get_headers(https://static.shanhubei.com/qrcode/qrcode_viewid_8990.jpg): failed to open stream: operation failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57
0
分享到:
没有账号? 忘记密码?