2013-08-20 12 views
9

Ieri ho dovuto passare un po 'di tempo a cercare un bug nel mio codice e ho trovato che il pacchetto data.table ordina le stringhe in un modo un po' diverso dalla base. Si tratta di un comportamento normale e qual è il modo più efficiente (con vantaggi di data.table) per riprodurre i risultati ottenuti con la funzione base order? Ecco un esempio riproducibile giocattolo:Come data.table ordina le stringhe quando si imposta la chiave

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()) 

OS Windows 7

+0

Qual è il tuo sistema operativo? – GSee

+0

il mio sistema operativo è Windows 7 – jem77bfp

risposta

9

Aggiornamento marzo 2014

C'è stata qualche discussione su questo. A partire dalla versione 1.1.2, per ora abbiamo risolto l'ordinamento setkey utilizzando C locale; ad esempio, tutte le lettere maiuscole vengono prima di tutte le lettere minuscole, indipendentemente dalle impostazioni locali dell'utente. Questo è stato un cambiamento fatto in v1.8.8 che avevamo intenzione di invertire ma per ora sono rimasto bloccato.

Considerare save() -in una tabella con chiave nelle impostazioni locali e un collega load() -in esso in un locale diverso. Quando si uniscono a quella tabella, potrebbe non funzionare più correttamente se si tratta di un ordinamento locale. Dobbiamo riflettere un po 'più attentamente se setkey è di consentire nuovamente l'ordinamento locale, probabilmente salvando il nome locale insieme all'attributo "ordinato", quindi data.table può almeno confrontare e rilevare se le impostazioni internazionali correnti sono diverse da quella in esecuzione setkey.

È anche per motivi di velocità, in quanto l'ordinamento in base alla locale è molto più lento di C locale. Sebbene, possiamo farlo nel modo più efficiente possibile e permettere che sia opzionalmente ideale.

Quindi, questa è ora una richiesta di funzionalità e ulteriori commenti sono molto graditi.

FR#4842 setkey to sort using session's locale not C locale



Bella cattura! La chiamata a setkey chiama a sua volta setkeyv e che chiama fastorder per "ordinare" le colonne/voci che a sua volta chiama chorder.

chorder a sua volta chiama una funzione C Ccountingcharacter.c. Ora, qui suppongo che il problema sia dovuto a "locale".

Vediamo quale "locale" sono sul mio 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" 

Ora vediamo come order tipi IT:

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

Ora, cambiamo il "locale" a "C".

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

order(x) 
# [1] 1 2 3 

Da ?order:

L'ordinamento dei vettori di caratteri dipenderà dalla sequenza di collazione del locale in uso: vedi Comparison.

Da ?Comparison:

Confronto di stringhe in vettori di caratteri è lessicografico all'interno delle stringhe utilizzando la sequenza di collazione del locale in uso: vedi locali. La sequenza di confronto di localizzazioni come en_US è normalmente diversa da C (che dovrebbe usare ASCII) e può essere sorprendente. Fai attenzione a qualsiasi ipotesi sull'ordine di collazione: ad es. in Z Estonian si frappone tra S e T, e il confronto non è necessariamente carattere per carattere - in genere aa danesi come una singola lettera, dopo z ....

Quindi, in sostanza, order così sotto " C "locale, dà lo stesso ordine di di setkey. La mia ipotesi è che la funzione C chiamata da chorder venga eseguita automaticamente su C-locale che confronterà i valori ascii per i quali "S" precede "b".

Probabilmente è importante portare questo a @ l'attenzione di MatthewDowle (se non ne è già a conoscenza). Quindi, ti suggerisco di archiviarlo come un bug here (solo per essere sicuro).

+0

+1 bel lavoro investigativo –

+0

bel lavoro, ma non definirei un bug, forse una richiesta di funzionalità – eddi

2

Beh, io non sono sicuro di quello che il modo più efficace è, ma è possibile effettuare le seguenti operazioni per riprodurre il risultato data.frame.

dt[order(dt$cn)] 

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

funziona correttamente, ma con un set di dati più grande potrebbe essere molto più lento del setkey – jem77bfp

+0

Accetto. Sembra che potrebbe avere qualcosa a che fare con il metodo di ordinamento utilizzato in setkey. Questo è quello che dice nella "setkey" (tuttavia non sono riuscito a trovare un'opzione per impostare il metodo sort in setkey) _L'ordinamento viene tentato con il metodo "radix" molto veloce in sort.list. Se fallisce, l'ordinamento ritorna al metodo predefinito in ordine. Quella logica è ripetuta colonna per colonna. Forse qualcun altro ne sa di più? –

Problemi correlati