2013-03-02 13 views
31

Mam dataframe z liczbą różnych przedmiotów, w różnych latach:Dodaj „rangi” kolumny do ramki danych

df <- data.frame(item = rep(c('a','b','c'), 3), 
       year = rep(c('2010','2011','2012'), each=3), 
       count = c(1,4,6,3,8,3,5,7,9)) 

I chciałbym dodać „year.rank” kolumny, co daje pozycja przedmiotu w danym roku, gdzie wyższa liczba prowadzi do wyższej "rangi". Z powyższego, to będzie wyglądać:

item year count year.rank 
1 a 2010  1   3 
2 b 2010  4   2 
3 c 2010  6   1 
4 a 2011  3   2 
5 b 2011  8   1 
6 c 2011  3   3 
7 a 2012  5   3 
8 b 2012  7   2 
9 c 2012  9   1 

wiem, co mogłem zrobić to dla całej ramki danych przy użyciu order(df$count), ale nie jestem pewien, w jaki sposób mogę to zrobić przez rok.

Odpowiedz

32

Jest rank funkcji, aby pomóc Ci w tym:

transform(df, 
      year.rank = ave(count, year, 
          FUN = function(x) rank(-x, ties.method = "first"))) 
    item year count year.rank 
1 a 2010  1   3 
2 b 2010  4   2 
3 c 2010  6   1 
4 a 2011  3   2 
5 b 2011  8   1 
6 c 2011  3   3 
7 a 2012  5   3 
8 b 2012  7   2 
9 c 2012  9   1 
+0

+1 bo próbowałem z rankingu bez sukcesu !! utknąłem z funkcją rangi! – agstudy

+1

@agstudy, faktycznie opublikowałem zbyt szybko, bez powodzenia. Kluczem był '-x' (od rangi zwykle przechodzi od niskiego do wysokiego) i' ties.method' (ponieważ pozycja zazwyczaj jest średnia). – A5C1D2H2I1M1N2O1R2T1

+0

To świetnie, dziękuję. – Wilduck

9

Korzystanie order funkcji

transform(dat, x= ave(count,year,FUN=function(x) order(x,decreasing=T))) 
    item year count x 
1 a 2010  1 3 
2 b 2010  4 2 
3 c 2010  6 1 
4 a 2011  3 2 
5 b 2011  8 1 
6 c 2011  3 3 
7 a 2012  5 3 
8 b 2012  7 2 
9 c 2012  9 1 

EDIT

Można użyć plyr tu również:

ddply(dat,.(year),transform,x = order(count,decreasing=T)) 
+0

Uwielbiam czystsze rozwiązanie, uważam, że lepiej to zrobić ' ave() 'niż' ave (rank()) 'ale w tym przypadku nie masz kontroli nad' ties.method', prawda? –

24

data.table wersja dla praktyki:

library(data.table) 
DT <- as.data.table(df) 
DT[,yrrank:=rank(-count,ties.method="first"),by=year] 

    item year count yrrank 
1: a 2010  1  3 
2: b 2010  4  2 
3: c 2010  6  1 
4: a 2011  3  2 
5: b 2011  8  1 
6: c 2011  3  3 
7: a 2012  5  3 
8: b 2012  7  2 
9: c 2012  9  1 
+3

To jest świetne. Dziękuję Ci. Czy istnieje jakaś dobra dokumentacja w dowolnym miejscu do korzystania z porcji efektów ubocznych z data.table? Zaczynam go używać, ale nie jestem jeszcze tak biegły, jak bym chciał. – Wilduck

+1

@Wilduck - to nie tyle efekt uboczny, co efekt główny! Jestem też całkiem nowym użytkownikiem 'data.table', ale właśnie przeglądałem FAQ na http://cran.r-project.org/web/packages/data.table/vignettes/datatable-faq. pdf Google jest twoim przyjacielem! – thelatemail

+0

Przez efekt uboczny rozumiem, że wykonuje operację na data.table, zamiast zwracać oddzielny wynik. http://en.wikipedia.org/wiki/Side_effect_(computer_science) W każdym razie, doceniam odpowiedź. – Wilduck

8

Korzystanie dplyr można to zrobić w następujący sposób:

library(dplyr) # 0.4.1 
df %>% 
    group_by(year) %>% 
    mutate(yrrank = row_number(-count)) 

#Source: local data frame [9 x 4] 
#Groups: year 
# 
# item year count yrrank 
#1 a 2010  1  3 
#2 b 2010  4  2 
#3 c 2010  6  1 
#4 a 2011  3  2 
#5 b 2011  8  1 
#6 c 2011  3  3 
#7 a 2012  5  3 
#8 b 2012  7  2 
#9 c 2012  9  1 

To jest taki sam jak:

df %>% 
    group_by(year) %>% 
    mutate(yrrank = rank(-count, ties.method = "first")) 

Należy zauważyć, że wynikowe dane są nadal pogrupowane według "roku". Jeśli chcesz usunąć zgrupowanie, możesz po prostu rozszerzyć rurę o %>% ungroup().

1

Podczas korzystania odpowiedzi udzielone przez innych, stwierdziliśmy, że następujące wykonuje się szybciej niż przekształcić i dyplr warianty:

df$year.rank <- ave(count, year, FUN = function(x) rank(-x, ties.method = "first")) 
Powiązane problemy