data.table
Использование ключей и индексов
Поиск…
Вступление
замечания
Официальные виньетки - лучшее введение в эту тему:
- «Ключи и быстрое подмножество на основе бинарного поиска»
- «Вторичные индексы и автоматическая индексация»
Ключи против индексов
Таблицу данных можно «закрепить» по последовательности столбцов, сообщая заинтересованным функциям, что данные сортируются по этим столбцам. Чтобы получить или установить ключ, используйте функции, задокументированные ?key
.
Точно так же функции могут использовать «индексы» data.table. Каждый индекс - и таблица может иметь более одного - хранит информацию о порядке данных с учетом последовательности столбцов. Как ключ, индекс может ускорить выполнение определенных задач. Чтобы получить или установить индексы, используйте функции, задокументированные по ?indices
.
Индексы также могут быть установлены автоматически (в настоящее время только для одного столбца за раз). См. ?datatable.optimize
для получения подробной информации о том, как это работает и как отключить его, если необходимо.
Проверка и обновление
Недопустимые значения разрешены в ключевом столбце.
Ключи и индексы сохраняются как атрибуты и могут, случайно, не соответствовать фактическому порядку данных в таблице. Многие функции проверяют правильность ключа или индекса перед его использованием, но это стоит иметь в виду.
Ключи и индексы удаляются после обновлений, где не очевидно, что порядок сортировки сохраняется. Например, начиная с DT = data.table(a=c(1,2,4), key="a")
, если мы обновляем как DT[2, a := 3]
, ключ сломан.
Улучшение производительности для выбора подмножеств
# example data
set.seed(1)
n = 1e7
ng = 1e4
DT = data.table(
g1 = sample(ng, n, replace=TRUE),
g2 = sample(ng, n, replace=TRUE),
v = rnorm(n)
)
Соответствие по одному столбцу
После первого запуска операции подмножества с ==
или %in%
...
system.time(
DT[ g1 %in% 1:100]
)
# user system elapsed
# 0.12 0.03 0.16
Индекс был создан автоматически для g1
. Последующие операции подмножества выполняются почти мгновенно:
system.time(
DT[ g1 %in% 1:100]
)
# user system elapsed
# 0 0 0
Чтобы отслеживать, когда индекс создан или используется, добавьте параметр verbose=TRUE
или измените параметры глобальной настройки options(datatable.verbose=TRUE)
.
Согласование по нескольким столбцам
В настоящее время сопоставление по двум столбцам не создает автоматически индекс:
system.time(
DT[ g1 %in% 1:100 & g2 %in% 1:100]
)
# user system elapsed
# 0.57 0.00 0.57
Повторно запустите это, и он будет оставаться медленным. Даже если мы вручную добавим индекс с помощью setindex(DT, g1, g2)
, он будет оставаться медленным, потому что этот запрос еще не оптимизирован пакетом.
К счастью, если мы можем перечислить комбинации значений, которые мы хотим найти, и индекс доступен, мы можем быстро equi-join:
system.time(
DT[ CJ(g1 = 1:100, g2 = 1:100, unique=TRUE), on=.(g1, g2), nomatch=0]
)
# user system elapsed
# 0.53 0.00 0.54
setindex(DT, g1, g2)
system.time(
DT[ CJ(g1 = 1:100, g2 = 1:100, unique=TRUE), on=.(g1, g2), nomatch=0]
)
# user system elapsed
# 0 0 0
С CJ
важно следить за тем, чтобы количество комбинаций становилось слишком большим.