【问题标题】:R group by and aggregate - return relative rank within groups using plyrR group by and aggregate - 使用 plyr 返回组内的相对排名
【发布时间】:2015-03-11 11:25:31
【问题描述】:

更新:我有一个如下所示的数据框“测试”:

    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' 值来检查这一点,毫不奇怪它等于最高排名值。如果有人可以复制和帮助,我将不胜感激。谢谢

【问题讨论】:

  • 相同的分数获得相同的排名
  • 对不起,但由于依赖包lazyeval,我似乎无法安装dplyr。当我尝试安装该依赖项时,它说包“lazyeval”不可用(对于 R 版本 3.0.2)
  • 您可以更新到最新的 R 版本然后安装
  • 我再次打开了这个 - 添加了新的数据来重现。我还诊断出问题出在与 group by (session_id) 无关,而是在整个集合中进行排名
  • 您好像完全删除了原来的问题?

标签: r group-by aggregate plyr dplyr


【解决方案1】:

一个选项:

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

dense_rank“类似于 min_rank,但等级之间没有差距”,所以我否定了 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))

【讨论】:

  • 我不确定该解决方案是否适合我 - 我确实看到我的 df 中添加了一个名为“rank”的新列,但是该列的值只是数字 1: 21(对于我上面的示例),已订购,与 Seller_feedback_score 没有明显关系
  • 这很奇怪,但您的解决方案适用于 1 列,但不适用于另一列。
  • @user3628777,您需要通过提供一些数据来测试它来使其可重现。如果没有更多信息,我无法验证为什么它不能在不同的列上工作。该列是否包含正值和负值?你的意思是它会引发错误还是排名错误? ...很多可能性
  • @user3628777,从更新中仍然不清楚你的意思是它不起作用。这对我来说不是那么明显。请详细说明。
  • desc()代替-会好一点
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-18
    • 1970-01-01
    • 2011-04-05
    相关资源
    最近更新 更多