R group by и aggregate - возвращает относительный ранг в группах, используя 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), который, очевидно, должен ранжировать "seller_feedback_score" в каждой группе session_id:

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

однако на самом деле происходит то, что R ранжирует весь фрейм данных вместе, не связываясь с группами (session_id's):

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", и неудивительно, что оно равно наибольшему значению ранга. Буду признателен, если кто-то сможет воспроизвести и помочь. Спасибо

2 ответа

Решение

Один вариант:

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))

От data.table 1.9.5 на, frank() (для быстрого ранга) функция экспортируется. Интерфейс похож на base::rank, но это реализует dense rank в дополнение ко всем методам ранжирования base::rank обеспечивает, и это также работает над списком в дополнение к векторам. Вы можете установить его, следуя инструкциям здесь.

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

Как отмечает @David, возможно, вы хотите rank = "first" или "мин"?? Точно сказать не могу...

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
Другие вопросы по тегам