Как данные.таблица сортирует строки при настройке ключа

мне пришлось потратить некоторое время, пытаясь найти ошибку в моем коде, и я обнаружил, что data.table пакет сортирует строки способом, немного отличающимся от базового. Является ли это нормальным поведением и каков наиболее эффективный способ (который имеет преимущества data.table) для воспроизведения результатов, полученных с помощью base ? Вот воспроизводимый пример игрушки:

library(data.table)
options(stringsAsFactors = FALSE)

d <- data.frame(cn=c("USA","Ubuntu","Uzbekistan"))
d[order(d$cn),,drop=F]

#          cn
#2     Ubuntu
#1        USA
#3 Uzbekistan

dt <- data.table(d)
setkey(dt, cn)
dt

#           cn
#1:        USA
#2:     Ubuntu
#3: Uzbekistan

options(stringsAsFactors = default.stringsAsFactors())

ОС Windows 7

2 ответов


Обновление Март 2014

были некоторые дебаты по этому поводу. По состоянию на v1.9.2 мы пока остановились на setkey сортировка с использованием языка C; например, все заглавные буквы идут перед всеми строчными буквами, независимо от языка пользователя. Это было изменение, сделанное в v1.8.8 который мы намеревались повернуть вспять, но пока придерживались.

считают save()-ing ключевой таблицы в вашем регионе и коллега load()-ing его в другом месте. Когда они присоединитесь к этой таблице, она может больше не работать правильно, если это был порядок сортировки локали. Мы должны подумать немного более тщательно, если setkey разрешить упорядочение локали снова, возможно, сохранив имя локали вместе с атрибутом "sorted", поэтому data.table можно по крайней мере сравнить и определить, отличается ли текущая локаль от той, которая выполнялась setkey.

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

следовательно, теперь это запрос функции, и дальнейшие комментарии очень приветствуются.

FR#4842 setkey для сортировки с использованием локали сеанса не c locale



хороший улов! Вызов setkey в свою очередь setkeyv и fastorder чтобы "заказать" столбцы / записи, которые в свою очередь вызывает chorder.

chorder в свою очередь вызывает функцию C Ccountingcharacter.c. Сейчас, здесь, я полагаю, проблема возникает из-за"locale".

давайте посмотрим, что "locale" я на своем mac.

Sys.getLocale()
# [1] "en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8"

теперь посмотрим, как order он:

x <- c("USA", "Ubuntu", "Uzbekistan")
order(x)
# [1] 2 1 3

теперь давайте изменим "locale"на " C".

Sys.setlocale("LC_ALL", "C")
# [1] "C/C/C/C/C/en_US.UTF-8"

order(x)
# [1] 1 2 3

С ?order:

порядок сортировки символьных векторов будет зависеть от последовательности сортировки используемой локали: см. Comparison.

С ?Comparison:

сравнение строк в символьных векторах является лексикографическим в строках с использованием последовательности сопоставления используемой локали: см. локали. Последовательность сопоставления локалей, таких как en_US, обычно отличается от C (который должен использовать ASCII) и может быть удивительной. Остерегайтесь делать какие-либо предположения о порядке сортировки: например, на эстонском языке Z находится между S и T, а сортировка не обязательно по символам-в датских сортировках aa как одна буква, после Зет....

Итак, order также в разделе " C " locale, дает тот же порядок, что и data.table ' s setkey. Я предполагаю, что C-функция, вызываемая chorder автоматически запускается на C-locale, который будет сравнивать значения ascii, для которых "S" предшествует "b".

вероятно, важно довести это до сведения @MatthewDowle (если он еще не знает об этом). Итак, я предлагаю вам подать это как ошибку здесь (просто чтобы быть уверенным).


Ну, я не уверен, что самый эффективный способ, но вы можете сделать следующее, чтобы воспроизвести данные.результат кадра.

dt[order(dt$cn)]

           cn
1:     Ubuntu
2:        USA
3: Uzbekistan