мутировать по группе в R - PullRequest
0 голосов
/ 04 июля 2018

У меня есть данные со следующими столбцами:

    Date         CID      FID        rank  
    31/01/17     abc0001  rx180x01    0
    31/01/17     abc0001  rx180x02    0
    31/01/17     abc0001  rx180x03    2
    28/02/17     abc0001  rx180x32    1
    28/02/17     abc0001  rx180x31    0

Каждый CID имеет несколько уникальных FID, сопоставленных с ним, и имеет некоторый ранг для этих FID. Мне нужно создать 2 новых столбца finalrank и finalFID.

Финальный ранг - это максимальный ранг каждого CID для каждой даты. т. е. для CID abc0001, на дату 31.01.17, finalrank будет равен 2. Эта логика будет применяться ко всей уникальной комбинации CID-даты.

FinalFID - это тот FID, который имеет конкретное значение finalrank для CID в дате. Например, в дате 31.01.17 для CID abc0001 FID с максимальным рангом равен rx180x03

Так что мой результат должен выглядеть так:

    Date         CID      FID        rank  finalrank finalFID
    31/01/17     abc0001  rx180x01    0    2         rx180x03
    31/01/17     abc0001  rx180x02    0    2         rx180x03
    31/01/17     abc0001  rx180x03    2    2         rx180x03
    28/02/17     abc0001  rx180x32    1    1         rx180x32
    28/02/17     abc0001  rx180x31    0    1         rx180x32

Я написал код, который выглядит элегантно и хорошо, но он не работает для очень больших данных. У того, с кем я имею дело, около 5 000 000. Когда я запускаю его в R, он показывает, что больше ничего не работает для таких огромных кадров данных.

       data          = dplyr::group_by(data,CID,date)
       data          = arrange(data,CID,date)
       data          = dplyr::mutate(data, finalrank =max(rank))

       # Id FID of maximum rank
       data   = dplyr::mutate(data, match = FID[match(finalrank ,rank)])

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Подход с использованием dplyr, который, как ожидается, будет более быстрым, заключается в arranging данных на Date, CID, rank и последующем взятии last. Решение будет таким:

library(dplyr)

df %>% mutate(Date = as.POSIXct(Date,format = "%d/%m/%y")) %>%
  group_by(Date, CID) %>%
  arrange(Date, CID, rank) %>%
  mutate(finalrank = last(rank), finalFID=last(FID)) %>%
  as.data.frame()

#         Date     CID      FID rank finalrank finalFID
# 1 2017-01-31 abc0001 rx180x01    0         2 rx180x03
# 2 2017-01-31 abc0001 rx180x02    0         2 rx180x03
# 3 2017-01-31 abc0001 rx180x03    2         2 rx180x03
# 4 2017-02-28 abc0001 rx180x31    0         1 rx180x32
# 5 2017-02-28 abc0001 rx180x32    1         1 rx180x32

Отредактировано: Чтобы пояснить @Onyambu, что если последняя строка не имеет максимального значения для ранга, то также работает решение.

df$rank[1] <- 3

df %>% mutate(Date = as.POSIXct(Date,format = "%d/%m/%y")) %>%
  group_by(Date, CID) %>%
  arrange(Date, CID, rank) %>%
  mutate(finalrank = last(rank), finalFID=last(FID)) %>%
  as.data.frame()


#        Date     CID      FID rank finalrank finalFID
# 1 2017-01-31 abc0001 rx180x02    0         3 rx180x01
# 2 2017-01-31 abc0001 rx180x03    2         3 rx180x01
# 3 2017-01-31 abc0001 rx180x01    3         3 rx180x01
# 4 2017-02-28 abc0001 rx180x31    0         1 rx180x32
# 5 2017-02-28 abc0001 rx180x32    1         1 rx180x32

Данные:

df <- read.table(text=
"Date         CID      FID        rank  
31/01/17     abc0001  rx180x01    0
31/01/17     abc0001  rx180x02    0
31/01/17     abc0001  rx180x03    2
28/02/17     abc0001  rx180x32    1
28/02/17     abc0001  rx180x31    0",
header = TRUE,  stringsAsFactors = FALSE)
0 голосов
/ 04 июля 2018
dat%>%
   group_by(Date,CID)%>%
   mutate(finalrank=max(rank),finalFID=FID[which.max(rank)])
# A tibble: 5 x 6
# Groups:   Date, CID [2]
  Date     CID     FID       rank finalrank finalFID
  <fct>    <fct>   <fct>    <int>     <dbl> <fct>   
1 31/01/17 abc0001 rx180x01     0         2 rx180x03
2 31/01/17 abc0001 rx180x02     0         2 rx180x03
3 31/01/17 abc0001 rx180x03     2         2 rx180x03
4 28/02/17 abc0001 rx180x32     1         1 rx180x32
5 28/02/17 abc0001 rx180x31     0         1 rx180x32

с использованием data.table

library(data.table)
setDT(dat)[,c("finalrank","finalFID"):=.(max(rank),FID[which.max(rank)]),by=.(Date,CID)]
dat 
       Date     CID      FID rank finalrank finalFID
1: 31/01/17 abc0001 rx180x01    0         2 rx180x03
2: 31/01/17 abc0001 rx180x02    0         2 rx180x03
3: 31/01/17 abc0001 rx180x03    2         2 rx180x03
4: 28/02/17 abc0001 rx180x32    1         1 rx180x32
5: 28/02/17 abc0001 rx180x31    0         1 rx180x32
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...