Ответ 1
library(microbenchmark)
library(data.table)
timings <- sapply(1:10, function(n) {
DF <- data.frame(id=rep(as.character(seq_len(2^n)), each=40), val=rnorm(40*2^n), stringsAsFactors=FALSE)
DT <- data.table(DF, key="id")
tofind <- unique(DF$id)[n-1]
print(microbenchmark( DF[DF$id==tofind,],
DT[DT$id==tofind,],
DT[id==tofind],
`[.data.frame`(DT,DT$id==tofind,),
DT[tofind]), unit="ns")$median
})
matplot(1:10, log10(t(timings)), type="l", xlab="log2(n)", ylab="log10(median (ns))", lty=1)
legend("topleft", legend=c("DF[DF$id == tofind, ]",
"DT[DT$id == tofind, ]",
"DT[id == tofind]",
"`[.data.frame`(DT,DT$id==tofind,)",
"DT[tofind]"),
col=1:5, lty=1)
Январь 2016: обновление до data.table_1.9.7
data.table
сделал несколько обновлений с тех пор, как это было написано (добавлено немного дополнительных надбавок к [.data.table
, поскольку были добавлены еще несколько аргументов/проверки надежности, а также введение автоматической индексации). Здесь обновленная версия от версии от 13 января 2016 года версии 1.9.7 от GitHub:
Основное нововведение заключается в том, что третий вариант теперь использует автоматическую индексацию. Основной вывод остается тем же - если ваша таблица имеет какой-либо нетривиальный размер (примерно 500 наблюдений), data.table
вызов внутри кадра выполняется быстрее.
(примечания об обновленном сюжете: некоторые незначительные вещи (отмена регистрации оси Y, выражение в микросекундах, изменение меток оси x, добавление заголовка), но одна нетривиальная вещь: я обновил microbenchmark
, чтобы добавить некоторую стабильность в оценках, а именно, я установил аргумент times
в as.integer(1e5/2^n)
)