如何在R中的组内排名?
Posted
技术标签:
【中文标题】如何在R中的组内排名?【英文标题】:How to rank within groups in R? 【发布时间】:2015-10-29 19:16:40 【问题描述】:好的,看看这个数据框...
customer_name order_dates order_values
1 John 2010-11-01 15
2 Bob 2008-03-25 12
3 Alex 2009-11-15 5
4 John 2012-08-06 15
5 John 2015-05-07 20
假设我想添加一个订单变量,该变量按名称、最大订单日期、使用决胜局的最后订单日期对最高订单价值进行排名。所以,最终数据应该是这样的:
customer_name order_dates order_values ranked_order_values_by_max_value_date
1 John 2010-11-01 15 3
2 Bob 2008-03-25 12 1
3 Alex 2009-11-15 5 1
4 John 2012-08-06 15 2
5 John 2015-05-07 20 1
每个人的单笔订单都得1分,之后的所有订单都根据该值进行排名,决胜局是最后一个订单日期获得优先权。 在此示例中,John 的 2012 年 8 月 6 日订单排名第 2,因为它是在 2010 年 11 月 1 日之后放置的。 2015 年 5 月 7 日的订单是 1,因为它是最大的。因此,即使该订单是 20 年前下的,它也应该是排名第一的,因为它是 John 的最高订单价值。
有谁知道我如何在 R 中做到这一点?我可以在数据框中的一组指定变量中进行排名吗?
感谢您的帮助!
【问题讨论】:
@akrun 价值的决胜局怎么样? 这是制作数据框的代码,以防万一:customer_name @SenorO OP 的示例测试起来应该更复杂一些。此外,来自dplyr
的dense_rank
是一种决胜局
@akun:价值的决胜局将是订单日期。所以约翰有两个 15 美元的订单,但最先下的那个排名更高。
可能是setDT(df1)[, rnk := order(desc(order_values), desc(order_dates)), customer_name]
使用data.table
【参考方案1】:
与@t-himmel 的回答类似,您可以使用 data.table 获取排名。
dt[ , rnk := order(order(order_values, decreasing = TRUE)), customer_name ]
【讨论】:
【参考方案2】:df %>%
group_by(customer_name) %>%
arrange(customer_name,desc(order_values)) %>%
mutate(rank2=rank(order_values))
【讨论】:
【参考方案3】:您可以使用dplyr
轻松完成此操作
library(dplyr)
df %>%
group_by(customer_name) %>%
mutate(my_ranks = order(order(order_values, order_dates, decreasing=TRUE)))
Source: local data frame [5 x 4]
Groups: customer_name
customer_name order_dates order_values my_ranks
1 John 2010-11-01 15 3
2 Bob 2008-03-25 12 1
3 Alex 2009-11-15 5 1
4 John 2012-08-06 15 2
5 John 2015-05-07 20 1
【讨论】:
这是不正确的。 correct answer 由 @T.Himmel 提供。【参考方案4】:评分最高的答案(由 cdeterman 提供)实际上是不正确的。 order 函数提供排名第 1、第 2、第 3 等值的位置,而不是当前顺序中值的排名。
让我们举一个简单的例子,我们想要排名,从最大的开始,按客户名称分组。我已经包含了一个手动排名,所以我们可以检查值
> df
customer_name order_values manual_rank
1 John 2 5
2 John 5 2
3 John 9 1
4 John 1 6
5 John 4 3
6 John 3 4
7 Lucy 4 4
8 Lucy 9 1
9 Lucy 6 3
10 Lucy 2 6
11 Lucy 8 2
12 Lucy 3 5
如果我运行 cdeterman 建议的代码,我会得到以下不正确的排名:
> df %>%
+ group_by(customer_name) %>%
+ mutate(my_ranks = order(order_values, decreasing=TRUE))
Source: local data frame [12 x 4]
Groups: customer_name [2]
customer_name order_values manual_rank my_ranks
<fctr> <dbl> <dbl> <int>
1 John 2 5 3
2 John 5 2 2
3 John 9 1 5
4 John 1 6 6
5 John 4 3 1
6 John 3 4 4
7 Lucy 4 4 2
8 Lucy 9 1 5
9 Lucy 6 3 3
10 Lucy 2 6 1
11 Lucy 8 2 6
12 Lucy 3 5 4
Order 用于将数据帧重新排序为降序或升序。我们真正想要的是运行两次 order 函数,第二次 order 函数为我们提供了我们想要的实际排名。
> df %>%
+ group_by(customer_name) %>%
+ mutate(good_ranks = order(order(order_values, decreasing=TRUE)))
Source: local data frame [12 x 4]
Groups: customer_name [2]
customer_name order_values manual_rank good_ranks
<fctr> <dbl> <dbl> <int>
1 John 2 5 5
2 John 5 2 2
3 John 9 1 1
4 John 1 6 6
5 John 4 3 3
6 John 3 4 4
7 Lucy 4 4 4
8 Lucy 9 1 1
9 Lucy 6 3 3
10 Lucy 2 6 6
11 Lucy 8 2 2
12 Lucy 3 5 5
【讨论】:
这对我很有用。我必须先运行detach("package:plyr", unload=TRUE)
,这样它才能正确分组。感谢您的解决方案!【参考方案5】:
在基础R
中,你可以用稍微笨重的东西来做到这一点
transform(df,rank=ave(1:nrow(df),customer_name,
FUN=function(x) order(order_values[x],order_dates[x],decreasing=TRUE)))
customer_name order_dates order_values 排名
1 约翰 2010-11-01 15 3
2 鲍勃 2008-03-25 12 1
3 亚历克斯 2009-11-15 5 1
4 约翰 2012-08-06 15 2
5 约翰 2015-05-07 20 1
其中order
提供了每个组的主要值和决胜局值。
【讨论】:
【参考方案6】:这可以通过ave
和rank
来实现。 ave
将适当的组传递给rank
。由于请求的顺序,rank
的结果是相反的:
with(x, ave(as.numeric(order_dates), customer_name, FUN=function(x) rev(rank(x))))
## [1] 3 1 1 2 1
【讨论】:
以上是关于如何在R中的组内排名?的主要内容,如果未能解决你的问题,请参考以下文章