【发布时间】:2019-01-07 22:39:33
【问题描述】:
我有一个巨大的data.table,我需要根据现有列内的条件创建新列。
假设我的数据如下所示:
library(data.table)
dt=data.table(ID=rep(1:3,1000000),LABEL=rep(c("A","A","B"),1000000),COND=rep(c("C","D","D"),1000000),VALUE=sample(letters,1000000,replace=T))
现在,我需要根据其他列上的值将值分配给新列 WHATEVER。假设我正在循环执行此操作:
dt$WHATEVER=as.numeric(NA)
for(id in dt[,unique(ID)]){
for(label in dt[,unique(LABEL)]){
n=dt[which(ID==id&LABEL==label&COND=="C"),cumsum(grepl("a",VALUE))]
set(dt,
i=dt[,which(ID==id&LABEL==label&COND=="C")],
j="WHATEVER",
value=n)
}
}
如果我system.time()这个,我得到:
user system elapsed
0.788 0.000 0.788
但是,我的数据集(和我的代码)要复杂得多,而且需要数小时。所以我尝试setkey 到我用来选择循环内外数据的列,但我几乎没有任何变化。
setkey(dt,ID,LABEL,COND)
for(id in dt[,unique(ID)]){
for(label in dt[,unique(LABEL)]){
#setkey(dt,ID,LABEL,COND)
n=dt[which(ID==id&LABEL==label&COND=="C"),cumsum(grepl("a",VALUE))]
set(dt,
i=dt[,which(ID==id&LABEL==label&COND=="C")],
j="WHATEVER",
value=n)
}
}
...如您所见:
user system elapsed
0.801 0.020 0.820
我做错了什么或者可以做得更好吗? (我知道我可以更改应用功能。我的问题是 data.table 明智)
按照 Henrik 的要求,我将展示我的数据集样本并解释我想要做什么。我的数据集如下所示:
ID NAME PROGRAM
1: 2056 CE 348
2: 2056 CE 348
3: 2056 AE 348
4: 2056 CE 348
5: 2056 AE 348
6: 2056 AE 348
7: 2056 CE 348
8: 2056 AE 348
9: 2056 BC 348
10: 2056 CB 348
我试图为每个 ID 计算每个 NAME 出现的次数,并为 NEWCOLUMN 分配一个数字,告诉我哪个时间是那个时间(顺序很重要,尽管 setkey 可能会搞砸我可以解决它),但仅限于某些程序。
后来我使用分配给新列的值来创建另一个,它告诉我哪个 NAME 是第一个和最后一个,再次为每个 ID 和仅某些 PROGRAM。 (这个更慢,因为它是由其他专栏完成的),尽管 PoGibas 的回答可能有助于加快速度。
【问题讨论】:
-
不幸的是,仅在示例中。
-
完成,@PoGibas。
-
这有点帮助,但它仍然没有。我再次更新问题。
-
好的,@PoGibas,这更接近我的需要。
-
@Henrik 我对我的数据做了一些进一步的解释和玩具。
标签: r performance data.table