2011-09-22 10 views
10

W R, mam listę nietrywialnych obiektów (nie są to proste obiekty, takie jak skalary, których R można oczekiwać, aby móc zdefiniować zamówienie). Chcę posortować listę. Większość języków pozwala programiście dostarczyć funkcję lub coś podobnego, która porównuje parę elementów listy przekazywanych do funkcji sortowania. Jak mogę posortować listę?Sortuj listę nietrywialnych elementów w R

+0

Czy możesz podać fragment tej nietrywialnej listy elementów, aby inni mieli pojęcie o tym, o czym mówisz? Wskazówki dotyczące pisania powtarzalnych pytań tutaj: http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example – Chase

Odpowiedz

14

Aby było to tak proste, mogę powiedzieć, że twoje obiekty to listy z dwoma elementami, nazwą i wartością. Wartość jest wartością numeryczną; właśnie to chcemy sortować. Możesz sobie wyobrazić, że masz więcej elementów i potrzebujesz czegoś bardziej złożonego do sortowania.

Na stronie pomocy sort podano, że sort używa xtfrm; xtfrm z kolei mówi nam, że będzie używać metod == i > dla klasy x[i].

Najpierw będę określić przedmiot, który chcę sortować:

xx <- lapply(c(3,5,7,2,4), function(i) list(name=LETTERS[i], value=i)) 
class(xx) <- "myobj" 

Teraz, ponieważ xtfrm prac nad x[i] „s, muszę zdefiniować [ funkcję, która zwraca żądane elementy, ale wciąż z prawo klasa

`[.myobj` <- function(x, i) { 
    class(x) <- "list" 
    structure(x[i], class="myobj") 
} 

teraz musimy == i > funkcje klasy myobj; to potencjalnie mogłoby być mądrzejsze poprzez odpowiednie wektoryzowanie; ale dla funkcji sortowania wiemy, że będziemy tylko przechodzić w myobj o długości 1, więc użyję pierwszego elementu do zdefiniowania relacji.

`>.myobj` <- function(e1, e2) { 
    e1[[1]]$value > e2[[1]]$value 
} 

`==.myobj` <- function(e1, e2) { 
    e1[[1]]$value == e2[[1]]$value 
} 

Teraz działa sort.

sort(xx) 

To może być uważane za bardziej właściwe, aby napisać pełną Ops funkcję dla obiektu; jednak, aby po prostu sortować, wydaje się, że to wszystko, czego potrzebujesz. Zobacz str.89-90 w Venables/Ripley, aby dowiedzieć się więcej o tym, używając stylu S3. Ponadto, jeśli możesz łatwo napisać funkcję dla swoich obiektów, będzie to prostsze i najprawdopodobniej szybsze.

+0

Dzięki Aaron. Fantastyczna odpowiedź. – Chris

+1

To dużo pracy, aby skonstruować rozwiązanie mniej ogólne, niż można zbudować zwykłymi bitami R: Są to dwa zastosowania sortowania "porządku" na pierwszej wartości: 'xx [order (as.character (sapply (xx," ["," value ")))], a następnie na nazwie:' xx [order (as.character (sapply (xx, "[", "name")))] 'bez żadnego odniesienia do metod klasy. –

+0

@DWin ma absolutną rację; jeśli możesz zrobić coś mądrzejszego, powinieneś! – Aaron

4

Funkcja order pozwala określić porządek sortowania znaków lub argumentów numerycznych oraz zerwanie powiązania z kolejnymi argumentami. Musisz być bardziej szczegółowy o tym, co chcesz. Wytwórz przykład "nietrywialnego obiektu" i określ żądaną kolejność w jakimś obiekcie R. Listy są prawdopodobnie najbardziej non-obiekty wektorowe:

> slist <- list(cc=list(rr=1), bb=list(ee=2, yy=7), zz="ww") 
> slist[order(names(slist))] # alpha order on names() 
$bb 
$bb$ee 
[1] 2 
$bb$yy 
[1] 7 
$cc 
$cc$rr 
[1] 1  
$zz 
[1] "ww" 

slist[c("zz", "bb", "cc")] # an arbitrary ordering 
$zz 
[1] "ww" 
$bb 
$bb$ee 
[1] 2 
$bb$yy 
[1] 7 
$cc 
$cc$rr 
[1] 1 
1

Jedną z opcji jest stworzenie xtfrm metodę swoimi obiektami. Funkcje takie jak order pobierają wiele kolumn, które działają w niektórych przypadkach. Istnieją również pewne wyspecjalizowane funkcje dla konkretnych przypadków, takich jak mixedsort w pakiecie .