改善data.table的性能,为列分配新的值

时间:2019-01-07 22:39:33

标签: r performance data.table

我有一个庞大的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的答案可能有助于加快速度。

1 个答案:

答案 0 :(得分:1)

您可以选择根据条件COND == "C"生成的具有cumsumTRUE 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)]