2016-06-17 14 views
17

mam data.tabledumdt:Zmiana kolejności wierszy w data.table w określonej kolejności

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

którego wiersze chciałbym uporządkować w tym konkretnym indeksów kolejności (tak pierwszy trzeci obserwacji, wówczas piąty potem drugi, itd.):

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

Więc chciałbym dumdt być wynikiem dumdt[to_ord] ale ja również chciałbym to zrobić poprzez odniesienie i uniknąć robi dumdt <- dumdt[to_ord].

wiem, że mogę zmienić kolejność wierszy przez odniesienie z setorder (lub setorderv), ale tylko według jednej lub kilku zmiennych, w kolejności rosnącej lub malejącej, a nie w niestandardowej kolejności.
Jeśli jednak chciałbym zmienić kolejność kolumn, a nie wierszy, w niestandardowej kolejności, mógłbym użyć setcolorder.

Oto moje pytanie: czy istnieje funkcja, która działałaby tak, jak setcolorder, ale z wierszami (lub sposobem użycia tego samego przy użyciu setorder)?

Moja pożądanym wyjściem byłoby coś

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

Czy nie jest 'setorder (cbind (dumdt, to_ord), to_ord)' (następnie ustawić to_ord na NULL) wystarczająco szybko? –

+1

@EricLecoutre Dziękuję za komentarz, nie jestem pewien, czy użycie 'cbind' będzie skuteczne, ale w każdym razie, to zmieniłoby nieprzypisane wyjście' cbind', a nie obiekt początkowy, tak by naprawdę nie pomogło. (a właściwie jestem przekonany, że produkcja nie byłaby oczekiwana ...) – Cath

+0

Yeks ... Rzeczywiście. Zawsze pewne trudności z odniesieniami ... –

Odpowiedz

12

Ta funkcja nie jest (jeszcze) eksportowane . Po przeanalizowaniu źródła setorderv udało mi się wyodrębnić wymagane wywołanie do funkcji C, która wykonuje to, czego potrzebujesz i dostarcza je z niestandardową kolejnością.

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 

jednak rozwiązanie proponowane przez Franka wygląda trochę ładniejszy.

+1

To dla mnie wygląda jak magia ;-) Dziękuję bardzo, właśnie stworzyłeś funkcję, którą chciałbym mieć. Teraz czuję się jak zepsuta dziewczyna ;-) – Cath

+0

Generalnie myślę, że odpowiedź Franka jest trochę bardziej poprawna, jeśli chodzi o to, że polega ona tylko na eksportowanych funkcjach z data.table, w przeciwieństwie do mojego, gdzie ':::' służy do dostępu nie wyeksportowana funkcja. – jangorecki

+1

Eh, ten sposób jest chłodniejszy i nie wymaga dwukrotnego zamówienia :) – Frank

12

Jeśli dobrze rozumiem, można po prostu dodać col a następnie zamówienie przez niego:

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

fajny sposób "podwojenia" porządku 'to_ord', nie wymyśliłem jak użyć porządku na nim, nie przerzedziłem' order (order (to_ord)) == to_ord' :-) – Cath

Powiązane problemy