【问题标题】:Find point in two column datatable在两列数据表中查找点
【发布时间】:2018-05-21 21:33:17
【问题描述】:

有谁知道如何快速有效地检查两列数据表中是否存在点 P(x,y)?示例代码:

dt <- data.table(x=c(1,2,3,4,5), y = c(2,3,4,5,6))
P <- c(2,3)

我想要的 TRUE 输出(因为 dt 中的第二行包含我的点 P)。 我试过了

 P %in% dt

但它只适用于第一行,我尝试使用循环,但没有太多希望 - 我正在寻找高效的“data.table” - 风格的解决方案。

【问题讨论】:

  • toString(P) %in% apply(dt, 1, toString) - 这会将每个数字对视为一个字符串进行比较
  • PL = as.list(P); dt[PL, on=names(dt), .N, nomatch=0] &gt; 0
  • setkey 不会比内部连接快吗?
  • @chinsoon12 - 据我所知on= 无论如何都会进行键控连接。
  • @chinsoon 进一步阅读设置键,如果你有兴趣:stackoverflow.com/a/20057411/1191259

标签: r data.table data-manipulation


【解决方案1】:

在 cmets 上进行扩展。

来自 Frank 在评论中提供的 What is the purpose of setting a key in data.table? 中的 Arun 帖子:

  1. 即使在其他情况下,除非您重复执行连接,否则键控连接和临时连接之间应该没有明显的性能差异。

因此,必须弄清楚花在重新排序整个 data.table 上的时间是否值得花时间进行高效缓存的连接/聚合。通常,除非在同一个 keyed data.table 上执行重复的分组/连接操作,否则应该不会有明显的差异。

因此,OP 的快速有效的“data.table”风格解决方案实际上取决于问题的维度,即数据集的大小和将执行的搜索次数。 p>

如果两者都很大,以下是一些时间:

数据:

library(data.table)
set.seed(0L)
M <- 1e7
dtKeyed <- data.table(x=1:M, y=2:(M+1)) #R-3.4.4 data.table_1.10.4-3 win-x64
dtNoKey <- copy(dtKeyed)
system.time(setkey(dtKeyed, x, y)) #not free
dtKeyed

nsearches <- 1e3
points <- apply(matrix(sample(M, nsearches*2, replace=TRUE), ncol=2), 1, as.list)

变化:

findPtNoKey <- function() {
    lapply(points, function(p) dtNoKey[p, on=names(dtNoKey), .N > 0, nomatch=0])
}

findPtOnKey <- function() {
    lapply(points, function(p) dtKeyed[p, on=names(dtKeyed), .N > 0, nomatch=0])
}

findPtKeyed <- function() {
    lapply(points, function(p) dtKeyed[p, .N > 0, nomatch=0])
}

library(microbenchmark)
microbenchmark(findPtKeyed(), findPtOnKey(), findPtNoKey(), times=3L)

时间安排:

#rem to add back the timing from setkey into the timing for findPtKeyed

Unit: milliseconds
          expr         min          lq        mean      median          uq         max neval
 findPtKeyed()    924.6846    928.3025    946.0892    931.9205    956.7914    981.6624     3
 findPtOnKey()   1119.9686   1129.5641   1143.4505   1139.1597   1155.1915   1171.2233     3
 findPtNoKey() 146186.2216 154934.5463 161016.1277 163682.8709 168431.0807 173179.2905     3

准确性检查:

ref <- findPtNoKey()

identical(findPtKeyed(), ref)
#[1] TRUE

identical(findPtOnKey(), ref)
#[1] TRUE

【讨论】:

  • 也许值得一提:这个时机是如果您必须按顺序进行搜索(例如,您不知道要在开始时进行的全部搜索)。如果你能一次性完成,PDT = setnames(rbindlist(points), names(dtNoKey)); dtNoKey[PDT, on=names(dtNoKey), .N &gt; 0, nomatch=0, by=.EACHI] 非常快。
  • 同意。这完全取决于 OP 问题的维度
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-06-16
  • 2012-03-16
  • 2017-02-09
  • 1970-01-01
  • 2019-12-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多