Р: данные.таблица vs производительность слияния (aggregate ())

или, чтобы быть более общим, это DT[,.SD[...],by=...] и merge(aggregate(...)).

без дальнейших церемоний, вот данные и пример:

set.seed(5141)
size = 1e6
df <- data.table(a = rnorm(size),
                 b = paste0(sample(letters, size, T), 
                            sample(letters, size, T), 
                            sample(letters, size, T)),
                 c = sample(1:(size/10), size, T),
                 d = sample(seq.Date(as.Date("2015-01-01"), 
                                     as.Date("2015-05-31"), by="day"), size, T))

system.time(df[,.SD[d == max(d)], by = c])
# user  system elapsed 
# 50.89    0.00   51.00 
system.time(merge(aggregate(d ~ c, data = df, max), df))
# user  system elapsed 
# 18.24    0.20   18.45 

обычно не имея никаких проблем с data.table производительность, я был удивлен этим конкретным примером. Мне пришлось подмножество (совокупности) довольно большой фрейм данных с учетом только последний (может быть одновременно) встречаемость некоторых типов событий. И сохраните остальные данные для этих конкретных событий. Однако, похоже, что .SD не масштабируется хорошо в этом конкретном приложении.

есть ли лучший "способ таблицы данных" для решения такого рода задач?

1 ответов


можно использовать .I чтобы получить индекс строки и подмножество строк, основываясь на этом. Это должно быть быстрее.

system.time(df[df[,.I[d == max(d)], by = c]$V1])
#    user  system elapsed 
#   5.00    0.09    5.30 
@Heroka это
system.time(df[,is_max:=d==max(d), by = c][is_max==T,])
#   user  system elapsed 
#  5.06    0.00    5.12 

на aggregate метод на моей машине дает

system.time(merge(aggregate(d ~ c, data = df, max), df))
#   user  system elapsed 
#  48.62    1.00   50.76 

С .SD опции

system.time(df[,.SD[d == max(d)], by = c])
#   user  system elapsed 
# 151.13    0.40  156.57 

С помощью data.table вступить

system.time(df[df[, list(d=max(d)) , c], on=c('c', 'd')])
#   user  system elapsed 
#   0.58    0.01    0.60 

если мы посмотрим на сравнение между merge/aggregate и ==, это разные функции. Обычно aggregate/merge метод будет медленнее по сравнению с coresponding join с data.table. Но, вместо этого мы используем ==, который сравнивает каждую строку (занимает некоторое время) вместе с .SD для подмножества (что также относительно менее эффективно по сравнению с .I для индексации строк). The .SD также имеет накладные расходы [.data.table.