【问题标题】:Improving data.table performance assigning new values to a column提高 data.table 性能,为列分配新值
【发布时间】: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


【解决方案1】:

您可以选择从条件VALUE == "a" 生成的具有COND == "C"cumsum TRUE 值的行(带有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)]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-07
    • 1970-01-01
    • 1970-01-01
    • 2013-12-27
    • 2018-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多