对data.table进行键控查找而不使用'with'

时间:2013-02-27 00:28:36

标签: r indexing data.table

我有data.table这样的结构(除了我真的很大):

dt <- data.table(x=1:5, y=3:7, key='x')

我希望通过另一个名称为x变量在该结构中查找行(注意 - 与dt的键名相同):< / p>

x <- 3:4
dt2 <- dt[ J(x) ]

这不起作用,因为查找首先查看列名,并且局部变量被遮挡:

dt2
#    x y
# 1: 1 3
# 2: 2 4
# 3: 3 5
# 4: 4 6
# 5: 5 7

我考虑了with的{​​{1}}参数,但这只适用于[.data.table参数,而不是j参数。

i参数有类似之处吗?

如果没有,只要我使用局部变量而且我不知道i中列名的完整列表,这样的事情会很方便,以避免冲突。

4 个答案:

答案 0 :(得分:10)

新闻1.8.2中有一项建议在某个时候添加..()语法,允许这样做

  

新DT [。(...)]语法(采用包plyr的样式)与           DT [list(...)],DT [J(...)]和DT [data.table(...)]。我们也计划添加..()           那个。()和..()类似于文件系统的./和../;即,。()           在父和范围内的DT和..()框架内进行评估。

同时,您可以从适当的环境中get

dt[J(get('x', envir = parent.frame(3)))]
##    x y
## 1: 3 5
## 2: 4 6

或者您可以evallist(x)J(x)

的整个来电
dt[eval(list(x))]
dt[eval(J(x))]
dt[eval(.(x))]

答案 1 :(得分:2)

新答案,现在我认为我理解了所要求的内容:

> X <- data.table(x=x)
> merge(dt, X)
   x y
1: 3 6
2: 4 7

答案 2 :(得分:1)

不需要设置密钥,它更快:

dt[eval(dt[, x %in% ..x])]

   x y
1: 3 5
2: 4 6

使用先前发布的答案进行基准测试

microbenchmark(dt[eval(dt[, x %in% ..x])],
               dt[J(get('x', parent.frame(3)))],
               dt[eval(list(x))],
               dt[eval(J(x))],
               dt[eval(.(x))],
               merge(dt, data.table(x)),
               times = 100L)

Unit: microseconds
                                  expr    min      lq     mean  median      uq    max neval
      dt[eval(dt[, x %in% ..x])]  486.1  500.60  518.529  503.70  512.65 1238.0   100
dt[J(get("x", parent.frame(3)))]  837.3  853.25  891.424  860.00  868.30 1675.3   100
               dt[eval(list(x))]  831.8  842.70  929.521  851.95  859.85 3878.3   100
                  dt[eval(J(x))]  833.8  845.50  948.535  856.00  870.00 4599.2   100
                  dt[eval(.(x))]  828.6  846.40  871.054  851.75  859.35 1985.6   100
        merge(dt, data.table(x)) 1766.0 1804.70 1907.617 1819.95 1870.95 3123.1   100

答案 3 :(得分:0)

根据要求添加一些基准测试结果。

dt是一个53080731 x 5 data.table对象,由一个数字列键控,大约有100个唯一值,分布相当均匀。 x是包含其中5个值的向量。

library(microbenchmark)
> mb <- microbenchmark(
+     dt[eval(J(x))],
+     merge(dt, data.table(x)),
+     times=10
+ )
> mb
Unit: milliseconds
                     expr      min       lq    median       uq      max neval
           dt[eval(J(x))]  127.324  127.549  133.5305  154.410  159.433    10
 merge(dt, data.table(x)) 5028.349 5083.792 5129.6590 5170.451 5250.255    10

@Tyler,如果您可以帮助我了解如何在多个列的情况下使用qdap::lookup(),我也可以添加。