我有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
中列名的完整列表,这样的事情会很方便,以避免冲突。
答案 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
或者您可以eval
对list(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()
,我也可以添加。