Какова цель установки ключа в данных.стол?
я использую данные.таблица и есть много функций, которые требуют от меня установить ключ (например,X[Y]
). Таким образом, я хочу понять, что делает ключ, чтобы правильно установить ключи в моих таблицах данных.
один источник, который я читал, был ?setkey
.
setkey()
сортировкаdata.table
и помечает его как сортируется. Сортированные столбцы являются ключевыми. Ключом могут быть любые столбцы в любом порядке. Столбцы всегда сортируются в порядке возрастания. Таблица изменяется на ссылка. Копия не создается вообще, за исключением временной рабочей памяти размером с один столбец.
моя идея заключается в том, что ключ будет "сортировка" данных.стол, в результате чего очень похожий эффект order()
. Однако это не объясняет цель наличия ключа.
данные.таблица FAQ 3.2 и 3.3 объясняет:
3.2 у меня нет ключа на большой стол, но группировка по-прежнему очень быстро. Почему?
данные.таблица использует сортировку по корням. Это значительно быстрее, чем другие алгоритмы сортировки. Radix специально для целых чисел, см.
?base::sort.list(x,method="radix")
. Это также одна из причин, почемуsetkey()
быстро. Когда ключ не установлен, или мы группируем в другом порядке исходя из этого ключа, мы называем его ad hoc by.3.3 почему группировка по столбцам в ключе быстрее, чем ad hoc by?
потому что каждая группа является смежной в ОЗУ, тем самым минимизируя страницу выборки и память могут быть скопированы в основную (
memcpy
в C), а не зацикливание в с.
отсюда я предполагаю, что установка ключа каким-то образом позволяет R использовать "сортировку по радиусу" по другим алгоритмам, и именно поэтому она быстрее.
в 10-минутном руководстве по быстрому запуску также есть руководство по клавишам.
- ключи
давайте начнем с рассмотрения данных.рамка, конкретно имена строк (или в Английский язык, названия строк). То есть несколько имен принадлежность к единому ряд. Несколько имен, принадлежащих к одной строке? Это не то, что мы привыкли в данных.рамка. Мы знаем, что каждая строка имеет не более одного имя. У человека есть по крайней мере два имени, первое имя и второе имя. Это полезно для организации телефонного справочника, например, который сортируется по фамилии,затем по имени. Однако, каждая строка в данные.рамка может иметь только одно имя.
ключ состоит из одного или нескольких столбцы имен строк, которые могут быть целое число, фактор, символ или некоторые другой класс, не просто характер. Кроме того, строки сортируются по ключ. Таким образом, данные.таблица может иметь более одного ключа, потому что невозможно отсортировать более чем одним способом.
уникальность не применяется, т. е. допускается дублирование ключевых значений. Так как строки сортируются по ключ, любые дубликаты в ключе будут появляться последовательно
телефонный справочник был полезным в понимании того, что ключ есть, но кажется, что ключ ничем не отличается по сравнению с наличием столбца факторов. Кроме того, он не объясняет, зачем нужен ключ (особенно для использования определенных функций) и как выбрать столбец для установки в качестве ключа. Кроме того, кажется, что в данных.таблица со временем в качестве столбца, установка любого другого столбца в качестве ключа, вероятно, также испортит столбец времени, что делает его еще более запутанным, поскольку я не знаю, разрешено ли мне устанавливать любой другой столбец в качестве ключа. Может кто-нибудь просветить меня, пожалуйста?
2 ответа:
обновление: пожалуйста, обратитесь к новые HTML виньетки как хорошо. этот вопрос выделены другие виньетки, которые мы планируем.
я обновил этот ответ снова (февраль 2016) в свете нового
on=
функция, которая позволяет ad-hoc также присоединяется. См. историю для более ранних (устаревших) ответов.что именно
setkey(DT, a, b)
делать?он делает две вещи:
- переупорядочивает строки данные.таблица
DT
по колонке(ам), предоставленной (a,b)по ссылке всегда в повышение порядок.- помечает эти столбцы как ключ столбцы, установив атрибут с именем
sorted
доDT
.переупорядочивание происходит быстро (из-за данные.таблицавнутренняя сортировка корня) и память эффективный (только один дополнительный столбец типа двойной выделяется).
когда
setkey()
требуются?для группировки операций,
setkey()
никогда не было абсолютным требованием. То есть, мы можем выполнить холод-к или adhoc-by.до## "cold" by require(data.table) DT <- data.table(x=rep(1:5, each=2), y=1:10) DT[, mean(y), by=x] # no key is set, order of groups preserved in result
v1.9.6
, соединения формыx[i]
требуютсяkey
наx
. новаяon=
аргумент от v1.9. 6+, это больше не верно, и поэтому клавиши настройки не абсолютное требование здесь.## joins using < v1.9.6 setkey(X, a) # absolutely required setkey(Y, a) # not absolutely required as long as 'a' is the first column X[Y] ## joins using v1.9.6+ X[Y, on="a"] # or if the column names are x_a and y_a respectively X[Y, on=c("x_a" = "y_a")]
отметим, что
on=
аргумент может быть указан даже дляkeyed
также присоединяется.единственная операция, которая требует
key
чтобы быть абсолютно набор -foverlaps()
ключ-это в основном индекс в наборе данных, который позволяет очень быстро и эффективно сортировать, фильтровать и объединять операции. Это, вероятно, лучшие причины для использования таблиц данных вместо фреймов данных (синтаксис для использования таблиц данных также гораздо более удобен для пользователя, но это не имеет ничего общего с ключами).
если вы не понимаете индексы, подумайте об этом: телефонная книга "индексируется" по имени. Так что если я хочу посмотреть чей-то номер телефона, это довольно просто. Но предположим, я хочу выполнить поиск по номеру телефона (например, посмотреть, у кого есть конкретный номер телефона)? Если я не смогу" переиндексировать " телефонную книгу по номеру телефона, это займет очень много времени.
рассмотрим следующий пример: предположим, что у меня есть таблица, ZIP, всех почтовых индексов в США (>33 000) вместе с соответствующей информацией (город, штат, население, средний доход и т. д.). Если я хочу найти информацию для определенного почтового индекса, поиск (фильтр) примерно в 1000 раз быстрее, если я
setkey(ZIP,zipcode)
первый.еще одно преимущество связано с объединениями. Предположим, что в таблице данных есть список людей и их почтовые индексы (назовите его "PPL"), и я хочу добавить информацию из таблицы ZIP (например, город, штат и т. д.). Следующий код сделает это:
setkey(ZIP,zipcode) setkey(PPL,zipcode) full.info <- PPL[ZIP, nomatch=F]
это "соединение" в том смысле, что я присоединяюсь к информации из 2 таблиц, основанных на общем поле (zipcode). Соединения, подобные этому, на очень больших таблицах чрезвычайно медленны с фреймами данных и чрезвычайно быстро с таблицами данных. В реальном примере мне пришлось сделать более 20 000 таких соединений на полной таблице почтовых индексов. С таблицами данных сценарий занял около 20 минут. бежать. Я даже не пробовал его с фреймами данных, потому что это заняло бы более 2 недель.
ИМХО вы должны не просто читать, но исследование FAQ и вводный материал. Это легче понять, если у вас есть реальная проблема, чтобы применить это.
[ответ на @Фрэнка комментарий]
Re:сортировка и индексация - на основе ответа на этот вопрос, явствует, что
setkey(...)
фактически переставляет столбцы в таблице (например, физическая сортировка) и не создает индекс в смысле базы данных. Это имеет некоторые практические последствия: во-первых, если вы установите ключ в таблице сsetkey(...)
а затем измените любое из значений в ключевом столбце data.таблица просто объявляет, что таблица больше не сортируется (путем поворота прочь ); это не динамически переиндексировать для поддержания правильного порядка сортировки (как это происходит в базе данных). Кроме того, "удаление ключа" с помощьюsetky(DT,NULL)
тут не восстановить таблицу в исходном, несортированном порядке.Re:фильтр против join - практическая разница заключается в том, что фильтрация извлекает подмножество из одного набора данных, тогда как join объединяет данные из двух наборов данных на основе общего поля. Есть много различные виды соединения (внутренний, внешний, слева). Приведенный выше пример является внутренним соединением (возвращаются только записи с ключами, общими для обеих таблиц), и это имеет много общего с фильтрацией.