R group by and aggregate - return 使用 plyr 的组内相对排名

R group by and aggregate - return relative rank within groups using plyr

更新:我有一个数据框 'test' 看起来像这样:

    session_id  seller_feedback_score
1   1   282470
2   1   275258
3   1   275258
4   1   275258
5   1   37831
6   1   282470
7   1   26
8   1   138351
9   1   321350
10  1   841
11  1   138351
12  1   17263
13  1   282470
14  1   396900
15  1   282470
16  1   282470
17  1   321350
18  1   321350
19  1   321350
20  1   0
21  1   1596
22  7   282505
23  7   275283
24  7   275283
25  7   275283
26  7   37834
27  7   282505
28  7   26
29  7   138359
30  7   321360

和一个代码(使用 plyr 包)显然应该在每组 session_id 中对 'seller_feedback_score' 进行排名:

 test <- test %>% group_by(session_id) %>% 
  mutate(seller_feedback_score_rank = dense_rank(-seller_feedback_score))

然而,真正发生的是 R 将整个数据框放在一起而不与组相关(session_id):

session_id  seller_feedback_score   seller_feedback_score_rank_2
1   1   282470  5
2   1   275258  7
3   1   275258  7
4   1   275258  7
5   1   37831   11
6   1   282470  5
7   1   26  15
8   1   138351  9
9   1   321350  3
10  1   841 14
11  1   138351  9
12  1   17263   12
13  1   282470  5
14  1   396900  1
15  1   282470  5
16  1   282470  5
17  1   321350  3
18  1   321350  3
19  1   321350  3
20  1   0   16
21  1   1596    13
22  7   282505  4
23  7   275283  6
24  7   275283  6
25  7   275283  6
26  7   37834   10
27  7   282505  4
28  7   26  15
29  7   138359  8
30  7   321360  2 

我通过计算唯一的 'seller_feedback_score_rank' 值来检查这一点,毫不奇怪它等于最高排名值。如果有人可以重现和提供帮助,我将不胜感激。谢谢

一个选项:

library(dplyr)
df %>% group_by(session_id) %>% 
  mutate(rank = dense_rank(-seller_feedback_score))

dense_rank 是 "like min_rank, but with no gaps between ranks" 所以我否定了 seller_feedback_score 列以便将它变成类似 max_rank 的东西(dplyr 中不存在)。

如果您希望排名有差距,以便在您的情况下达到最低的 21,您可以使用 min_rank 而不是 dense_rank:

library(dplyr)
df %>% group_by(session_id) %>% 
    mutate(rank = min_rank(-seller_feedback_score))

data.table 1.9.5开始,导出frank()(快速排名)功能。该接口类似于 base::rank,但除了 base::rank 提供的所有排名方法外,它还实现了 dense rank,并且除了向量之外,它还适用于列表。您可以按照说明进行安装 here.

require(data.table) ## 1.9.5+
setDT(df)[, 
    rank := frank(-seller_feedback_score, ties.method="dense"), 
by=session_id]

正如@David 指出的那样,也许您想要的是 rank = "first" 或 "min"?不确定...

setDT(df)[, 
    rank := frank(-seller_feedback_score, ties.method="first"), ## or "min" or "max"
by=session_id]

总之,一定是快充裕了。这是针对基础 R 的基准:

require(data.table)
set.seed(45L)
val = sample(1e4, 1e7, TRUE)
system.time(ans1 <- rank(val, ties.method = "min"))
#    user  system elapsed 
#  16.771   0.199  17.035 
system.time(an2 <- frank(val, ties.method = "min"))
#    user  system elapsed 
#   0.532   0.013   0.550 
identical(ans1, ans2) # [1] TRUE