R 查找匹配行的最快方法

R 查找匹配行的最快方法,r,data.table,xts,R,Data.table,Xts,我想知道在xts对象中查找与某一特定行相同的所有行的最快方法是什么 library(xts) nRows <- 3 coreData <- data.frame(a=rnorm(nRows), b=rnorm(nRows), c=rnorm(nRows)) testXts1 <- xts(coreData, order.by=as.Date(1:nRows)) testXts2 <- xts(coreData, order.by=as.Date((nRows + 1

我想知道在
xts
对象中查找与某一特定行相同的所有行的最快方法是什么

library(xts)

nRows <- 3

coreData <- data.frame(a=rnorm(nRows), b=rnorm(nRows), c=rnorm(nRows))

testXts1 <- xts(coreData, order.by=as.Date(1:nRows))
testXts2 <- xts(coreData, order.by=as.Date((nRows + 1):(2*nRows)))
testXts3 <- xts(coreData, order.by=as.Date((2*nRows + 1):(3*nRows)))

testXts <- rbind(testXts1, testXts2, testXts3)

> testXts
                    a         b         c
1970-01-02 -0.3288756  1.441799  1.321608
1970-01-03 -0.7105016  1.639239 -2.056861
1970-01-04  0.1138675 -1.782825 -1.081799
1970-01-05 -0.3288756  1.441799  1.321608
1970-01-06 -0.7105016  1.639239 -2.056861
1970-01-07  0.1138675 -1.782825 -1.081799
1970-01-08 -0.3288756  1.441799  1.321608
1970-01-09 -0.7105016  1.639239 -2.056861
1970-01-10  0.1138675 -1.782825 -1.081799

rowToSearch <- first(testXts)

> rowToSearch
                    a        b        c
1970-01-02 -0.3288756 1.441799 1.321608

indicesOfMatchingRows <- unlist(apply(testXts, 1, function(row)  lapply(1:NCOL(row), function(i) row[i] == coredata(rowToSearch[, i]))))

testXts[indicesOfMatchingRows, ]

                    a         b         c
1970-01-02 -0.3288756  1.441799  1.321608
1970-01-05 -0.3288756  1.441799  1.321608
1970-01-08 -0.3288756  1.441799  1.321608
库(xts)

nRows这里有一个更快的base R解决方案:

ind <- colSums(t(testXts) != as.vector(rowToSearch)) == 0L
testXts[ind,]

ind这不使用
数据表
,但速度可能相当快。可以通过散列行来实现

library(digest)
hash <- apply(testXts, 1, digest)
testXts[which(hash[1] == hash)]

#                    a          b          c
# 1970-01-02 0.8466816 -0.7129076 -0.5742323
# 1970-01-05 0.8466816 -0.7129076 -0.5742323
# 1970-01-08 0.8466816 -0.7129076 -0.5742323
库(摘要)

hash因为您说过速度是您最关心的问题,所以即使使用Rcpp的data.table解决方案,您也可以获得加速:

library(Rcpp)
cppFunction(
"LogicalVector compareToRow(NumericMatrix x, NumericVector y) {
  const int nr = x.nrow();
  const int nc = x.ncol();
  LogicalVector ret(nr, true);
  for (int j=0; j < nr; ++j) {
    for (int k=0; k < nc; ++k) {
      if (x(j, k) != y[k]) {
        ret[j] = false;
        break;
      }
    }
  }
  return ret;
}")
testXts[compareToRow(testXts, rowToSearch),]
#                   a         b         c
# 1970-01-02 1.324457 0.8485654 -1.464764
# 1970-01-05 1.324457 0.8485654 -1.464764
# 1970-01-08 1.324457 0.8485654 -1.464764
库(Rcpp)
cpp函数(
“LogicalVector比较器行(数值矩阵x,数值向量y){
常数int nr=x.nrow();
常数int nc=x.ncol();
LogicalVector ret(nr,真);
对于(int j=0;j
下面是一个相当大的实例(有一百万行)的比较:

set.seed(144)

bigXts最简单的
数据。表
解决方案可能是:

merge(as.data.table(testXts), as.data.table(rowToSearch, keep.rownames=FALSE))
返回:

          a          b         c      index
1: 1.685138 -0.3039018 -1.550871 1970-01-02
2: 1.685138 -0.3039018 -1.550871 1970-01-05
3: 1.685138 -0.3039018 -1.550871 1970-01-08
为什么会这样:

merge=公共列上的内部联接(如果未另行指定)。此内部联接仅返回值(a、b、c)与rowToSearch相同的列


右侧的
keep.rownames=FALSE
确保rowToSearch的日期索引(不需要)已删除,并且未输入要加入的公共列。

您是否可以更新您的解决方案,使其使用提供的
rowToSearch
,而不是假设它正在搜索矩阵中的第一行?@josilber我无法找出该部分,请随意编辑,因为OP是为了提高效率,所以我会寻找一种更快的方法来生成密钥
do.call(粘贴,如.data.frame(testXts))
将所有数字粘贴在一起,速度似乎更快(在我的基准测试中使用预先计算的
testDT
时,我可以使它与基本R解决方案相竞争)。使用digest,您只需制作一次哈希表,因此,如果你需要多个搜索,那么它可能会有回报。我认为这个基准对于
roland.dt
来说太快了,因为
testDT
通过引用
roland.dt
来通过,它在第一次试验期间对其进行排序,这将使后续试验更快。您可以在这里尝试:
a这并不是一个很大的区别,但我无法在一个更“诚实”的一次性
数据上获得比基准两倍更好的解决方案
merge(as.data.table(testXts), as.data.table(rowToSearch, keep.rownames=FALSE))
          a          b         c      index
1: 1.685138 -0.3039018 -1.550871 1970-01-02
2: 1.685138 -0.3039018 -1.550871 1970-01-05
3: 1.685138 -0.3039018 -1.550871 1970-01-08