Data.table: shift() in data.table v1.9.6 ist für viele Gruppen langsam

Erstellt am 11. Feb. 2016  ·  3Kommentare  ·  Quelle: Rdatatable/data.table

Hi!
Für viele verschiedene Gruppen in by ist shift viel langsamer als manuelles Schalten.
Siehe: http://stackoverflow.com/questions/35179911/shift-in-data-table-v1-9-6-is-slow-for-many-groups
und https://github.com/nachti/datatable_test/blob/master/leadtest.R für ein detailliertes Beispiel.
Beifall,
Gerhard

GForce performance

Hilfreichster Kommentar

@ ben519 Fyi, für den Sonderfall, wenn Ihr Code so aussieht, gibt es eine Verknüpfung:

library(data.table)
dt <- data.table(Grp = rep(seq_len(1e6), each=10L))
dt[, Value := sample(100L, size = .N, replace = TRUE)]

system.time(dt[, PrevValueByGrp := shift(Value, type = "lag"), by = Grp][])
#    user  system elapsed 
#   19.50    0.80   20.34
system.time(dt[, v := shift(Value, type = "lag")][rowid(Grp)==1L, v := NA][])
#    user  system elapsed 
#    1.00    0.87    1.25 

dt[, all.equal(v, PrevValueByGrp)]
# [1] TRUE

Alle 3 Kommentare

Das ist nicht überraschend. Dies verschwindet, wenn gforce für := optimiert ist. Es steht auf der Liste für diese Veröffentlichung, glaube ich.

+1 für diese Leistungssteigerung. shift() ist der größte Engpass in einem Großteil meines Codes. Scheint, dass bei einer festen Anzahl von Zeilen die Zeit zum Ausführen von shift() proportional zur Anzahl der Gruppen in den Daten ist.

library(data.table)

# Build table to store timings
timings <- CJ(RowCount = 10^7, Groups = 10^c(0:7))
timings[, SizePerGroup := RowCount/Groups]

# Loop through each experiment
for(i in 1:nrow(dt)){
  print(paste0("Iteration: ", i))

  # Build dataset
  timings_i <- timings[i]
  dt <- data.table(Grp = rep(seq_len(timings_i$Groups), each = timings_i$SizePerGroup))
  dt[, Value := sample(100, size = .N, replace = T)]

  # Measure the time it takes to insert a column indicating the previous value by group
  elapsed <- system.time(dt[, PrevValueByGrp := shift(Value, type = "lag"), by = Grp])["elapsed"]
  timings[i, Elapsed := elapsed]
}

library(ggplot2)
ggplot(timings, aes(x = Groups, y = Elapsed))+geom_line()+geom_point()

screen shot 2018-11-10 at 1 08 15 pm

@ ben519 Fyi, für den Sonderfall, wenn Ihr Code so aussieht, gibt es eine Verknüpfung:

library(data.table)
dt <- data.table(Grp = rep(seq_len(1e6), each=10L))
dt[, Value := sample(100L, size = .N, replace = TRUE)]

system.time(dt[, PrevValueByGrp := shift(Value, type = "lag"), by = Grp][])
#    user  system elapsed 
#   19.50    0.80   20.34
system.time(dt[, v := shift(Value, type = "lag")][rowid(Grp)==1L, v := NA][])
#    user  system elapsed 
#    1.00    0.87    1.25 

dt[, all.equal(v, PrevValueByGrp)]
# [1] TRUE
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen