Как ранжироваться в группах в R?
ОК, проверьте этот фрейм данных...
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, а все последующие ордера ранжируются на основе значения, а прерыватель связи является датой получения последнего ордера с приоритетом. В этом примере заказ Джона от 6 августа 2012 года получает ранг №2, потому что он был размещен после 1 ноября 2010 года. Заказ 5/7/2015 равен 1, потому что он был самым большим. Таким образом, даже если этот заказ был размещен 20 лет назад, он должен быть рангом № 1, потому что это был самый высокий заказ Джона.
Кто-нибудь знает, как я могу сделать это в R? Где я могу ранжировать внутри группы указанных переменных во фрейме данных?
Спасибо за вашу помощь!
6 ответов
Вы можете сделать это довольно чисто с 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
Ответ с самым высоким рейтингом (от cdeterman) на самом деле неверен. Функция заказа обеспечивает расположение ранжированных значений 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
Порядок используется для изменения порядка данных в порядке убывания или увеличения. То, что мы на самом деле хотим, - это запустить функцию заказа дважды, а вторая функция заказа даст нам реальные ранги, которые мы хотим.
> 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
Это может быть достигнуто с 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
Вы можете сделать это с немного громоздким
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 rank 1 Иоанн 2010-11-01 15 3 2 Bob 2008-03-25 12 1 3 Алекс 2009-11-15 5 1 4 Иоанн 2012-08-06 15 2 5 Иоанн 2015-05-07 20 1
где order
предоставляется как первичное значение, так и значения прерывателя связей для каждой группы.
df %>%
group_by(customer_name) %>%
arrange(customer_name,desc(order_values)) %>%
mutate(rank2=rank(order_values))
Подобно ответу @t-himmel, вы можете получить ранги с помощью data.table.
dt[ , rnk := order(order(order_values, decreasing = TRUE)), customer_name ]