Agregue una columna de “rango” a un dataframe

Tengo un dataframe con recuentos de diferentes elementos, en diferentes años:

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)) 

Y me gustaría agregar una columna “year.rank”, que da el rango de un elemento dentro de un año determinado, donde un conteo más alto conduce a un “rango” más alto. Con lo anterior, se vería así:

  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 

Sé que podría hacer esto para todo el dataframe usando el order(df$count) , pero no estoy seguro de cómo lo haría por año.

Hay una función de rank para ayudarte con eso:

 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 

versión data.table para la práctica:

 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 

Usando la función de order ,

 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 

EDITAR

Puede usar plyr aquí también:

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

Usando dplyr puedes hacerlo de la siguiente manera:

 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 

Es lo mismo que:

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

Tenga en cuenta que los datos resultantes todavía están agrupados por “año”. Si desea eliminar la agrupación, simplemente puede ampliar la tubería con %>% ungroup() .

Al usar las respuestas dadas por otros, descubrí que lo siguiente funciona más rápido que las variantes de transformación y dyplr :

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