我有一个庞大的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可能会弄乱这个时间,尽管我可以解决),但仅适用于某些程序。
最近,我使用分配给新列的值来创建另一个值,该值告诉我哪个名称是首先执行的,还是最后执行的,再次针对每个ID和仅某些程序。 (这是更慢的,因为它是由其他专栏完成的),Althouth PoGibas的答案可能有助于加快速度。
答案 0 :(得分:1)
您可以选择根据条件COND == "C"
生成的具有cumsum
和TRUE
VALUE == "a"
值的行(具有COND != "C"
的行将被NA
填充)。
# Assign cumsum to new column WHATEVER2 by ID and LABEL
dt[COND == "C", WHATEVER2 := cumsum(VALUE == "a"), .(ID, LABEL)]
# All values are equal to the ones generate by OP
dt[, all(WHATEVER == WHATEVER2, na.rm = TRUE)]