我建议使用带有键值的data.table
。以下是如何设置(以修改后的示例为例):
require(data.table)
mainDT <- data.table(main)
setkey(mainDT,V1,V2,V3)
现在我们可以使用如下语法基于相等条件进行子集划分:
mainDT[J("a","A")]
或者
mainDT[J(c("a","b"),"A",1)]
这是关于it技术的翻译内容: V1 %in% c("a","b")
表示在哪些子集中使用(等同于 V1=="a"|V1=="b"
)。
下面是速度比较:
require(rbenchmark)
benchmark(
"[" = main[main$V1=="a" & main$V2=="A",],
"subset" = subset(main,V1=="a" & V2=="A"),
"DT[J()]" = mainDT[J("a","A")],
replications=5
)[,1:6]
这在我的电脑上得到了以下结果:
test replications elapsed relative user.self sys.self
1 [ 5 5.96 NA 5.38 0.57
3 DT[J()] 5 0.00 NA 0.00 0.00
2 subset 5 6.93 NA 6.20 0.72
所以,使用
J
进行子集划分是瞬间完成的,而其他两种方法需要几秒钟。然而,使用
J
进行子集划分有以下限制:
- 仅适用于等式条件。
- 对于上述简单语法,您需要按键的顺序传递参数。但是,您可以使用
mainDT[J("a",unique(V2),2)]
选择V1=="a" & V3 == 2
,并且速度仍然很快。
您可以使用data.table执行数据框中的所有操作。例如,subset(mainDT,V1=="a" & V2=="A")
仍然有效。因此,通常情况下将数据框转换为data.table不会有任何损失。您可以使用setDT(main)
在原地将其转换为data.table。
这是示例代码:
n = 1e7
n3 = 1e3
set.seed(1)
main <- data.frame(
V1=sample(letters,n,replace=TRUE),
V2=sample(c(letters,LETTERS),n,replace=TRUE),
V3=sample(1:n3,n,replace=TRUE),
V4=rnorm(n))
上面基准测试中的改进将根据您的数据而异。当您有许多观测值(
n
)或键的唯一值较少时(例如,
n3
),使用带键的data.table进行子集化的好处应该更大。
[
代替subset
来获得更快的速度,或者可能是data.table
。 - akrunlibrary(dplyr); filter(main, date == "2015-01-01 07:44:00" & name == "bob" & value == 1)
,尽管我还没有对其进行基准测试。 - talatsetkey(data);data[J("2015-01-01 07:44:00","bob",1)]
。 - Frank