2013-03-02 28 views
31

我有不同的項目數一個數據幀,在不同的年份:一個「等級」欄添加到數據幀

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

而且我想補充一個「year.rank」一欄,這使一個項目在給定年份內的排名,更高的數字會導致更高的「排名」。通過上述方式,它看上去像:

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 

我知道我可以使用order(df$count)整個數據幀做到這一點,但我不知道我怎麼會在今年做到這一點。

回答

32

有一個rank功能,幫你:

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,因爲我試圖與排名不更迭!我堅持排名的功能! – agstudy 2013-03-02 04:53:36

+1

@agstudy,我實際上最初發布得太快,沒有成功。關鍵是'-x'(因爲排名通常從低到高)和'tie.method'(因爲排名通常默認爲平均值)。 – A5C1D2H2I1M1N2O1R2T1 2013-03-02 04:56:42

+0

這很好,謝謝。 – Wilduck 2013-03-02 05:09:39

9

使用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 

編輯

你可以在這裏使用plyr也:

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

我喜歡一個更乾淨的解決方案,我發現最好' ave()'而不是'ave(rank())',但在這種情況下,你不能控制'ties.method',對吧? – 2013-08-09 17:41:21

24

data.table版本做法:

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

這太好了。謝謝。是否有任何好的文檔可以使用data.table的副作用部分?我已經開始使用它了,但我還沒有像我想的那樣精通。 – Wilduck 2013-03-02 05:09:05

+1

@Wilduck - 這不像主效應那麼重要!我對'data.table'也很陌生,但我剛剛瀏覽了http://cran.r-project.org/web/packages/data.table/vignettes/datatable-faq上的FAQ。 pdf谷歌是你的朋友! – thelatemail 2013-03-02 05:16:15

+0

副作用我的意思是它正在對data.table執行一個操作,而不是返回一個單獨的結果。 http://en.wikipedia.org/wiki/Side_effect_(computer_science)無論如何,我很欣賞這種迴應。 – Wilduck 2013-03-02 06:41:50

8

使用dplyr可以按如下方式做到這一點:

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 

這是一樣的:

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

注意,結果數據仍然按「年份」分組。如果你想刪除分組,你可以簡單地用%>% ungroup()擴展管道。

1

在使用別人給的答案,我發現比快下進行變換dyplr變種:

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