【问题标题】:R - Compare 2 matrices to find rows which rows aren't in bothR - 比较 2 个矩阵以查找哪些行都不在这两个矩阵中
【发布时间】:2017-12-05 22:21:24
【问题描述】:

我在 R 中有两个不同大小的大矩阵,371 x 1502 (A) 和 371 x 1207 (B)。

所有矩阵 B 都包含在 A 中。A 还包含许多其他行。我正在寻找一种方法来创建一个新矩阵 C,它包含 A 中 B 中未找到的所有行。

我确信有一种方法可以使用 data.tables 和键来做到这一点,但我终其一生都无法弄清楚。

示例数据:

a = t(matrix(c(1,2,3,4,5,6,7,8,9), nrow = 3))
b = t(matrix(c(1,2,3,7,8,9), nrow = 3))

感谢您的帮助,

谢谢。

【问题讨论】:

  • 真实矩阵中 A 和 B 的行长度不同?
  • 我想你想要一个反加入。
  • 奇怪的是,这是一个封闭的问题 - stackoverflow.com/questions/34325762/…
  • 并从上一个问题中窃取 - a[!interaction(data.frame(a)) %in% interaction(data.frame(b)),]
  • 感谢大家的帮助,我在搜索中从未注意到以前的问题。非常感谢:)

标签: r matrix data.table


【解决方案1】:

我会在基础 R 中这样做:

a[!duplicated(rbind(b,a))[(nrow(b)+1):(nrow(a)+nrow(b))], ]

...但是 data.table 解决方案可能更优雅和/或更快。


感谢@thelatemail,这里是data.table 版本:

a[!b, on=names(a)]

这里是迄今为止提出的所有解决方案的基准,这里和 Maurits Evers

require('data.table')
require('plyr')
require('microbenchmark')    

n = 371
n1 = 1502
n2 = 1207

b = matrix(0 + sample.int(n * n2), ncol = n)
a = rbind(matrix(n*n2+1 + sample.int(n * (n1 - n2)), ncol = n), b)
b = b[sample.int(nrow(b)), ]

# preparing the data.table and data.frame versions of the data:
a.dt = data.table(a)
b.dt = data.table(b)
a.df = as.data.frame(a)
b.df = as.data.frame(b)

microbenchmark(
  BASE_R = a[!duplicated(rbind(b,a))[(nrow(b)+1):(nrow(a)+nrow(b))], ],
  DATA.TABLE = a.dt[!b.dt, on=names(a.dt)],
  DATA.TABLE2 = fsetdiff(a.dt, b.dt),
  PLYR = anti_join(a.df, b.df),
  times = 100
)

对于这个问题,另一个答案中提出的plyr解决方案是最快的。两个data.table 解决方案紧随其后,基础R 版本要慢得多。

    Unit: milliseconds
        expr        min         lq       mean     median        uq       max neval cld
      BASE_R 1125.05968 1412.13170 1555.82674 1577.81665 1703.3674 1927.1632   100   c
  DATA.TABLE   54.68581   83.99182  117.90571   91.86808  123.8300  318.3788   100  b 
 DATA.TABLE2   58.44053   86.90981  127.11152   97.39086  138.8306  328.1396   100  b 
        PLYR   30.87235   49.32260   61.02968   53.66639   59.6925  278.6965   100 a  

【讨论】:

  • 您可能还想在其中放一个 drop=FALSE,这样如果只有 1 行符合条件(如本例中所示),您将返回一个矩阵。
  • data.table 解决方案是反连接,如果你想添加它 - a[!b, on=names(a)]
  • 这个解决方案出现错误:a[!b, on = names(a)] 中的错误:(下标)逻辑下标太长。任何想法为什么?
【解决方案2】:

这是你想要的吗?

使用dplyr::anti_join:

require(dplyr);
anti_join(as.data.frame(a), as.data.frame(b));
#  V1 V2 V3
#1  4  5  6

使用data.table::fsetdiff

require(data.table);
fsetdiff(as.data.table(a), as.data.table(b));
#   V1 V2 V3
#1:  4  5  6

样本数据

# Your sample data
a = t(matrix(c(1,2,3,4,5,6,7,8,9), nrow = 3))
b = t(matrix(c(1,2,3,7,8,9), nrow = 3));

【讨论】:

    猜你喜欢
    • 2016-08-03
    • 1970-01-01
    • 2010-10-30
    • 2017-08-13
    • 1970-01-01
    • 2020-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多