Медленный dplyr запрос в R - PullRequest
       0

Медленный dplyr запрос в R

5 голосов
/ 02 апреля 2020

У меня есть немного кода в R:

library(dplyr)

df_temp <- df %>%
   group_by(policy_number, policy_year) %>% 
   summarise(term_start_date  = last(term_start_date),
             term_end_date    = last(term_end_date),
             on_cover_after   = last(on_cover_after),
             termination_code = last(termination_code),
             termination_date = last(termination_date))

Основная таблица df составляет около 700 000 строк на 130 столбцов. Сгруппированные по policy_number и policy_year насчитывают около 300 000 (policy_number / policy_year) группировок.

4 из 5 столбцов, на которые я ссылался в last(), - это даты.

Этот запрос занимает около 3 минут, что неприятно, потому что остальная часть моего кода выполняется довольно быстро. Я надеюсь ускорить это. Могу ли я попробовать что-нибудь, что могло бы помочь, пожалуйста?

(в идеале, я бы предоставил представительство, но как мне здесь это сделать? Не уверен)

Спасибо.

Редактировать : так как я всегда использую последнюю запись для данной пары (policy_number / policy_year), есть ли какой-нибудь код, который я мог бы написать в следующих строках:

df_temp <- df %>%
   group_by(policy_number, policy_year) %>% 
   mutate(counter = 1:n()) %>%
   filter(counter == max(counter)) %>%
   select(term_start_date,
          term_end_date,
          on_cover_after,
          termination_code,
          termination_date)

?

Ответы [ 3 ]

4 голосов
/ 02 апреля 2020

Здесь есть отличный источник . Автор делает несколько замечательных предложений (см. Его раздел комментариев). Я хотел бы рассмотреть агрегацию ваших данных с data.table, или, если вы придерживаетесь dplyr, подумайте об определении ключа. Некоторые метрики относительных ориентиров:

enter image description here

Из источника

4 голосов
/ 02 апреля 2020

Вместо summarise используйте summarise_at

library(dplyr)
df %>%
   group_by(policy_number, policy_year) %>%
   summarise_at(vars(term_start_date, term_end_date,
       term_end_date,termination_code, termination_date), last)
3 голосов
/ 03 апреля 2020

Вы можете попробовать либо пакет dtplyr (data.table backend для dplyr), либо пакет data.table напрямую, чтобы ускорить расчет. См. Бенчмарк ниже для iris набора данных

library(microbenchmark)
library(data.table)
library(dtplyr)
library(dplyr, warn.conflicts = FALSE)

# create a “lazy” data table for dtplyr
iris2 <- lazy_dt(iris)

# create a data table for data.table
dt <- setDT(copy(iris))

# dplyr calculation
dplyr_func <- function() {
  iris %>% 
    group_by(Species) %>% 
    summarise_at(vars(Sepal.Length:Petal.Width), last)      
}

# dtplyr calculation
dtplyr_func <- function() {
  iris2 %>% 
    group_by(Species) %>% 
    summarise_at(vars(Sepal.Length:Petal.Width), last)  %>% 
    as_tibble()      
}

# data.table calculation
dt_func <- function() {
  dt[ 
    , lapply(.SD, last)
    , Species]
}

Эталон

microbenchmark(
  dplyr_func(),
  dtplyr_func(),
  dt_func(),
  times = 1000L
)

#> Unit: microseconds
#>           expr    min     lq   mean median     uq   max neval cld
#>   dplyr_func() 4605.0 4892.9 5180.3 4999.9 5155.1 23253  1000   c
#>  dtplyr_func() 2503.9 2633.6 2885.0 2714.3 2812.2 39490  1000  b 
#>      dt_func()  949.2 1155.3 1848.1 2036.0 2302.1  7251  1000 a

Создан в 2020-04-02 пакетом Представить (v0 .3.0)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...