Как работает order() для символьной переменной в data.table?

#r #data.table

#r #data.table

Вопрос:

Я хочу изменить порядок строк в моей таблице в соответствии с символьной переменной ( stage в моем примере). Если я сначала сохраню желаемый order ( order(dt1$stage) ) в переменную, а затем применю его как dt1[myorder, stage] — он работает нормально. Но когда я пытаюсь сделать то же самое встроенное, например dt1[order(dt1$stage), ] , порядок отличается! Должно быть, что-то очень простое, чего мне не хватает…

 dt1 <- fread('
id stage pos
 1 I       1
 2 II      2
 3 III     5
 4 IV      6
 5 IIa     3
 6 IIb     7
 7 IIIa    8
 8 IIIb    4
 9 IVa     9
10 IVb    10')

sort(dt1$stage) # OK
# I II IIa IIb III IIIa IIIb IV IVa IVb

myorder <- order(dt1$stage)
dt1[myorder         , stage] # OK
# I II IIa IIb III IIIa IIIb IV IVa IVb

dt1[order(dt1$stage), stage] # different!
# I II III IIIa IIIb IIa IIb IV IVa IVb
 

Ответ №1:

Он выполняет a fast order вместо base::order . Согласно ?data.table::order

Обратите внимание, что запросы типа x[order(.)] оптимизированы внутренне для использования быстрого порядка data.table.

Также обратите внимание, что data.table всегда переупорядочивает в «C-locale» (см. Подробности). Для сортировки по языку сеанса используйте x[base::order(.)] .

data.table реализует свой собственный быстрый порядок на основе radix.

data.table всегда переупорядочивает в «C-locale». Как следствие, порядок может отличаться от порядка, полученного с помощью base::order . Например, в английских языках сортировка чувствительна к регистру в C-locale. Таким образом, сортировка c(«c», «a», «B») возвращает c(«B», «a», «c») в data.table, но c(«a», «B», «c») в base::ord

Если мы хотим реплицировать sort from base , используйте base::order

 dt1[base::order(stage)]$stage
#[1] "I"    "II"   "IIa"  "IIb"  "III"  "IIIa" "IIIb" "IV"   "IVa"  "IVb" 
 

Комментарии:

1. большое спасибо, теперь все ясно! Итак, если бы я хотел изменить порядок всей таблицы, вместо setorder(dt1, stage) я должен использовать dt1 <- dt1[base::order(stage),] , верно?

2. @VasilyA да, но это может быть медленным по сравнению с setorder большими наборами данных