Почему нотация data.table для выбора столбца влияет на скорость - PullRequest
10 голосов
/ 26 мая 2020

Кажется, есть разница в скорости в зависимости от того, как вы указываете столбцы, которые будут выбираться из таблицы данных: x[, .(var)] vs x[, c('var')]. Причина может быть совершенно очевидной, однако на справочной странице обозначения .(), list() и c() кажутся взаимозаменяемыми. Я работаю с довольно большими наборами данных, поэтому для меня это немного важно: -)

Пример (порядок вызова не влияет на скорость):

x <- as.data.table(as.character(rnorm(20000000,1,0.5)))
setkey(x, V1)

tic(); x[, .(V1)]; toc()
25.08 sec elapsed


tic(); x[, c('V1')]; toc()
0.28 sec elapsed

tic(); x[, 1]; toc()
0.02 sec elapsed

> sessionInfo()
R version 3.6.1 (2019-07-05)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18362)

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] tictoc_1.0        data.table_1.12.8

loaded via a namespace (and not attached):
[1] compiler_3.6.1  tools_3.6.1     lifecycle_0.2.0 rlang_0.4.6  

1 Ответ

7 голосов
/ 26 мая 2020

Вы обнаружили ошибку (проблема здесь ) - data.table пытается определить, является ли вывод [] ключевым; для этого выполняется внутренняя функция is.sorted. Это очень медленно для огромной таблицы уникальных строк.

К счастью, мы можем провести статический c анализ и понять, что ваша выходная таблица фактически снабжена ключами - подмножества нет, а ключевой столбец (V1) без изменений. Следовательно, порядок сортировки не может быть изменен, и ваш вывод также будет отсортирован по V1.

Этот лог c встроен в PR, чтобы исправить эту проблему - вы можете протестировать его с помощью remotes::install_github('Rdatatable/data.table@fix_sorting_on_sorted'), с оговоркой, что это новейшая версия пакета, или вы можете подождать, пока он не будет объединен с мастером, или пока не будет выпущена новая версия для CRAN.

In Между тем, вот обходной путь:

setkey(x, NULL)
system.time(x[ , .(V1)])
#    user  system elapsed 
#   0.120   0.087   0.213

Конечно, это блокирует дальнейшую обработку от распознавания того, что ваши данные отсортированы, и их эффективности ...

В этом случае (! и в этом случае только - используйте осторожно !!!) - если вы уверены, что данные уже отсортированы по V1 - вы можете мгновенно восстановить ключ с помощью:

setattr(x, 'sorted', 'V1')

Подробнее как правило, есть небольшие различия между выбором [, [[, $, и т.д. c. [ будет, как правило, самым медленным, поскольку мы проводим много «статического c анализа запросов», чтобы помочь повысить эффективность вашего кода, что связано с затратами на производительность, которые мы надеемся, будут небольшими. почти каждый раз. Каждый раз, когда эта стоимость не мала, это должно быть ошибкой. Также ведется активная работа, чтобы попытаться предложить ярлыки для уменьшения этих накладных расходов, см., Например, этот PR

...