2016-06-17 15 views
17

Ho un data.tabledumdt:righe Riordinare in data.table in un ordine specifico

set.seed(123) 
dumdt <- data.table(v1=sample(1:10, 5), v2=1:5) 

cui righe desidero riordinare in questa specifica indici ordinare (quindi prima della terza osservazione, poi il quinto, poi la seconda, ecc):

to_ord <- c(3, 5, 2, 1, 4) 

così mi piacerebbe dumdt ad essere il risultato di dumdt[to_ord] ma mi piacerebbe anche fare da riferimento e evitare di fare dumdt <- dumdt[to_ord].

So che posso riordinare le righe per riferimento con setorder (o setorderv) ma solo in base a una o più variabili, in ordine crescente o decrescente, non in un ordine personalizzato.
Tuttavia, se volessi riordinare le colonne, non le righe, in un ordine personalizzato, potrei usare setcolorder.

Quindi, ecco la mia domanda: c'è una funzione che potrebbe funzionare come setcolorder ma con le righe (o un modo di utilizzare setorder per fare lo stesso)?

mio output desiderato sarebbe qualcosa di simile

setroworder(x=dumdt, neworder=to_ord) 
dumdt 
    # v1 v2 
# 1: 4 3 
# 2: 6 5 
# 3: 8 2 
# 4: 3 1 
# 5: 7 4 
+0

Non è 'setorder (cbind (dumdt, to_ord), to_ord)' (quindi impostare to_ord su NULL) abbastanza veloce? –

+1

@EricLecoutre Grazie per il tuo commento, non sono sicuro che l'uso di 'cbind' sarà efficiente, ma in ogni caso, questo cambierebbe l'output non assegnato di' cbind' e non l'oggetto iniziale, quindi non sarebbe di grande aiuto. (e in realtà sono abbastanza convinto che l'uscita non sarebbe quella prevista ...) – Cath

+0

Yeks ... Infatti. Sempre qualche difficoltà con i riferimenti ... –

risposta

12

Questa funzionalità non è (ancora) esportati . Dopo aver esaminato la fonte di setorderv, sono stato in grado di estrarre la chiamata richiesta alla funzione C che esegue ciò che è necessario e lo fornisce con un ordine personalizzato.

library(data.table) 
set.seed(123) 
dumdt <- data.table(v1=sample(1:10, 5), v2=1:5) 
print(dumdt) 
# v1 v2 
#1: 3 1 
#2: 8 2 
#3: 4 3 
#4: 7 4 
#5: 6 5 
setroworder <- function(x, neworder) { 
    .Call(data.table:::Creorder, x, as.integer(neworder), PACKAGE = "data.table") 
    invisible(x) 
} 
to_ord <- c(3, 5, 2, 1, 4) 
setroworder(x=dumdt, neworder=to_ord) 
print(dumdt) 
# v1 v2 
#1: 4 3 
#2: 6 5 
#3: 8 2 
#4: 3 1 
#5: 7 4 

Eppure la soluzione proposta da Frank sembra un po 'più bello.

+1

Questo mi sembra davvero magico ;-) Grazie mille, hai appena creato la funzione che avrei voluto esistere. Ora mi sento una ragazza viziata ;-) – Cath

+0

In generale, penso che la risposta di Frank sia un po 'più corretta, in termini che si basa solo sulle funzioni esportate da data.table, a differenza del mio dove ':::' è usato per accedere funzione non esportata. – jangorecki

+1

Eh, in questo modo è più interessante e non richiede l'ordine due volte :) – Frank

12

Se ho capito bene, si può semplicemente aggiungere un colle e poi ordine da essa:

setorder(dumdt[, .r := order(to_ord)], .r)[, .r := NULL] 

    v1 v2 
1: 4 3 
2: 6 5 
3: 8 2 
4: 3 1 
5: 7 4 
+1

bel modo di "raddoppiare" l'ordine di 'to_ord', non ho capito come usare l'ordine, non thinjk' order (order (to_ord)) == to_ord' :-) – Cath

Problemi correlati