Как ранжироваться в группах в 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 ]
Другие вопросы по тегам