2011-10-11 19 views
7

Znalazłem aplikację, w której potrzebuję posortować dane.frame według numerów kolumn i żaden z usual solutions wydaje się na to nie zezwalać.Zamów na liście

Kontekst tworzy metodę as.data.frame.by. Ponieważ obiekt by będzie miał ostatnią kolumnę jako kolumnę wartości i pierwsze kolumny ncol-1 jako kolumny indeksu. melt zwraca go posortowane do tyłu - indeks 3, następnie indeks 2, a następnie indeks 1. Dla zgodności z latex.table.by Chciałbym posortować go do przodu. Ale mam problem z robieniem tego w wystarczająco ogólny sposób. Zakreślona linia w poniższej funkcji to moja najlepsza jak dotąd próba.

as.data.frame.by <- function(x, colnames=paste("IDX",seq(length(dim(x))),sep=""), ...) { 
    num.by.vars <- length(dim(x)) 
    res <- melt(unclass(x)) 
    res <- na.omit(res) 
    colnames(res)[seq(num.by.vars)] <- colnames 
    #res <- res[ order(res[ , seq(num.by.vars)]) , ] # Sort the results by the by vars in the heirarchy given 
    res 
} 

dat <- transform(ChickWeight, Time=cut(Time,3), Chick=cut(as.numeric(Chick),3)) 
my.by <- by(dat, with(dat,list(Time,Chick,Diet)), function(x) sum(x$weight)) 
> as.data.frame(my.by) 
      IDX1   IDX2 IDX3 value 
1 (-0.021,6.99] (0.951,17.3] 1 3475 
2  (6.99,14] (0.951,17.3] 1 5969 
3  (14,21] (0.951,17.3] 1 8002 
4 (-0.021,6.99] (17.3,33.7] 1 640 
5  (6.99,14] (17.3,33.7] 1 1596 
6  (14,21] (17.3,33.7] 1 2900 
13 (-0.021,6.99] (17.3,33.7] 2 2253 
14  (6.99,14] (17.3,33.7] 2 4734 
15  (14,21] (17.3,33.7] 2 7727 
22 (-0.021,6.99] (17.3,33.7] 3 666 
23  (6.99,14] (17.3,33.7] 3 1391 
24  (14,21] (17.3,33.7] 3 2109 
25 (-0.021,6.99] (33.7,50] 3 1647 
26  (6.99,14] (33.7,50] 3 3853 
27  (14,21] (33.7,50] 3 7488 
34 (-0.021,6.99] (33.7,50] 4 2412 
35  (6.99,14] (33.7,50] 4 5448 
36  (14,21] (33.7,50] 4 8101 

Z linii komentarzem, zwraca bełkot (to właśnie traktuje cały data.frame jako wektor, z katastrofalnymi skutkami).

Próbowałem nawet sprytnych rzeczy, takich jak res <- res[ order(...=list(res[,1],res[,2])) , ], ale bezskutecznie.

Podejrzewam, że istnieje prosty sposób, aby to zrobić, ale nie widzę tego.

Edytuj w celu wyjaśnienia: Nie chcę określać nazw kolumn. Zamiast tego chcę móc sortować je za pomocą wektora liczbowego (np. Sortować według kolumn 1: 4).

Odpowiedz

7
mydf <- as.data.frame(my.by) 
mydf[order(mydf$IDX3, mydf$IDX2, mydf$IDX1) , ] 
      IDX1   IDX2 IDX3 value 
1 (-0.021,6.99] (0.951,17.3] 1 3475 
3  (14,21] (0.951,17.3] 1 8002 
2  (6.99,14] (0.951,17.3] 1 5969 
4 (-0.021,6.99] (17.3,33.7] 1 640 
6  (14,21] (17.3,33.7] 1 2900 
5  (6.99,14] (17.3,33.7] 1 1596 
13 (-0.021,6.99] (17.3,33.7] 2 2253 
15  (14,21] (17.3,33.7] 2 7727 
14  (6.99,14] (17.3,33.7] 2 4734 
22 (-0.021,6.99] (17.3,33.7] 3 666 
24  (14,21] (17.3,33.7] 3 2109 
23  (6.99,14] (17.3,33.7] 3 1391 
25 (-0.021,6.99] (33.7,50] 3 1647 
27  (14,21] (33.7,50] 3 7488 
26  (6.99,14] (33.7,50] 3 3853 
34 (-0.021,6.99] (33.7,50] 4 2412 
36  (14,21] (33.7,50] 4 8101 
35  (6.99,14] (33.7,50] 4 5448 

Lub;

my.by <- by(dat, with(dat,list(Diet,Chick, Time)), function(x) sum(x$weight)) 
mydf <- as.data.frame(my.by) 

EDIT: Albo ten produkuje taką samą moc jak się góry za pomocą numerycznych indeksów kolumna:

mydf <- as.data.frame(my.by) 
mydf[ do.call(order, mydf[, 3:1]) , ] 
+0

Niestety powinno były wyraźniejsze: Chcę aby nie trzeba określać nazwy kolumn. Zamiast tego chcę móc sortować je za pomocą wektora liczbowego (np. Sortować według kolumn 1: 4). –

+0

Patrz wyżej. Metoda "do.call" przekazywania ramek danych do 'order' jest przedstawiona na stronie' help (order) '. –

+0

Nice. Dzięki. Muszę przyjrzeć się bliżej 'do.call', ponieważ podejrzewam, że rozwiąże wiele moich problemów :-) –