Как создать новые функции на основе учетных записей и временных интервалов, таких как прошлый день, прошлая неделя, прошлый месяц и т.д. В R?

#r #datetime #aggregate #feature-engineering

#r #datetime #агрегировать #разработка функций

Вопрос:

PS: В моих данных миллион строк, поэтому я ищу решение, которое не занимало бы так много времени для работы с большими данными.

Это мои данные транзакции

 id          from    to          date        amount  
<int>       <fctr>  <fctr>      <date>      <dbl>
19521       6644    6934        2005-01-01  700.0
19524       6753    8456        2005-01-01  600.0
19523       9242    9333        2005-01-01  1000.0
19522       9843    9115        2005-01-01  900.0
19525       7075    6510        2005-02-01  400.0
19526       8685    7207        2005-02-01  1100.0
…           …       …           …           …
1052337     9866    5992        2010-12-31  139.1
1052768     9866    5797        2010-12-31  72.1
1054271     9866    6697        2010-12-31  95.8
1055597     9866    9736        2010-12-31  278.9
1053519     9868    8644        2010-12-31  242.8
1052790     9869    8399        2010-12-31  372.2
  

Я хочу создать новые функции на основе учетных записей в столбце «от» и временных интервалов, таких как последний день, на прошлой неделе, в прошлом месяце и т.д.

Например, я хочу рассчитать максимальное количество учетных записей в столбце «от», отправленных в последний день / на прошлой неделе / в прошлом месяце, и сохранить эту информацию в данных в виде новых столбцов

Следующие данные — это то, что я ожидаю получить на выходе:

 id      from    to      date        amount  max_amount_in_last_day  max_amount_in_last_week max_amount_in_last_month    max_amount_in_last_3month
<int>   <fctr>  <fctr>  <date>      <dbl>   <dbl>                   <dbl>                  <dbl>                       <dbl>
19521   6644    6934    2005-01-01  700.0   700.0                   700.0                   700.0                       700.0
16214   6644    6874    2005-06-30  288.8   288.8                   288.8                   288.8                       288.8
16806   6644    9746    2005-06-30  83.7    288.8                   288.8                   288.8                       288.8
15220   6644    6671    2005-07-23  21716.0 21716.0                 21716.0                 21716.0                     21716.0
11975   6644    5384    2005-08-31  216.7   216.7                   216.7                   216.7                       21716.0
26579   6644    6041    2005-12-31  159.2   159.2                   159.2                   159.2                       159.2
35893   6644    8567    2006-01-31  169.6   169.6                   169.6                   169.6                       169.6
39425   6644    5599    2006-02-12  16230.0 16230.0                 16230.0                 16230.0                     16230.0
43606   6644    6454    2006-03-06  5859.0  5859.0                  5859.0                  16230.0                     16230.0
52052   6644    8836    2006-04-13  7269.0  7269.0                  7269.0                  7269.0                      16230.0
...

  

Как я могу этого добиться?

Для вычисления max_amount_in_last_day я попробовал следующий код, но он работает очень плохо на большом наборе данных. Есть ли лучший подход к этому?

 y  <- NULL

for(i in data$id){
  
  date <- data[data$id==i,]$date
  
  acc <- data[data$id==i,]$from
  
  df <- data[data$from==acc amp; data$date==date,]
        
        df <- df %>% mutate(max_trx_amount_in_last_day=max(df$amount)) 

        tmp <- df
        y <- rbind(y, tmp) %>% distinct
        

}

y
  

Ответ №1:

Сначала определите функцию для вычисления нужной статистики за определенное количество предыдущих дней.

 previousDays <- function(X, from, date, days, FUN){
  FUN <- match.fun(FUN)
  Y <- X[X[['from']] == from, ]
  i <- Y[['date']] >= date - days   1 amp; Y[['date']] <= date
  if(sum(i) > 0) FUN(Y[i, 'amount']) else NA_real_
}
  

Теперь примените функцию к каждой строке на указанное количество дней. В приведенном ниже примере, 7 дни, последняя неделя.

 applyPrev <- function(X, days, FUN){
  FUN <- match.fun(FUN)
  sapply(seq_along(X[['id']]), function(i){
    f <- X[i, 'from']
    d <- X[i, 'date']
    previousDays(df1, f, d, days, FUN)
  })
}

applyPrev(df1, 7, max)
  

Данные

 df1 <- read.table(text = "
id          from    to          date        amount  
19521       6644    6934        2005-01-01  700.0
19524       6753    8456        2005-01-01  600.0
19523       9242    9333        2005-01-01  1000.0
19522       9843    9115        2005-01-01  900.0
19525       7075    6510        2005-02-01  400.0
19526       8685    7207        2005-02-01  1100.0
1052337     9866    5992        2010-12-31  139.1
1052768     9866    5797        2010-12-31  72.1
1054271     9866    6697        2010-12-31  95.8
1055597     9866    9736        2010-12-31  278.9
1053519     9868    8644        2010-12-31  242.8
1052790     9869    8399        2010-12-31  372.2
", header = TRUE)
  

Комментарии:

1. @nojdar В чем ошибка, она не возвращает ожидаемые значения?

2. Он просто возвращает одни и те же значения в столбце сумма, независимо от того, какое число я передаю в функцию applyPrev

3. @nojdar Вы правы, извините. Я вычислял max по id, а не по from . Смотрите сейчас.

4. Да, сейчас это работает. Спасибо! Но я должен сказать, что вычисления на больших данных снова занимают так много времени.