Сводная сумма за количество вопросов, решенных за последние 7 дней каждым пользователем - PullRequest
3 голосов
/ 13 июня 2019

С учетом User_Id, Solved_Date и NumberOfQuestions решено для каждого пользователя, как получить скользящую сумму за последние 7 дней, исключая текущую дату. Я решил это, используя цикл и цикл по каждой строке, но искал альтернативный способ и легко читаемый код, например, используя dplyr

Input:
fread("
USER_ID SOLVED_DATE QUESTIONS_SOLVED
          1 2019-05-01        1
          1 2019-05-02        1
          2 2019-05-02        1
          2 2019-05-03        1
          2 2019-05-04        1
          2 2019-05-05        1
          1 2019-05-06        1
          2 2019-05-06        1
          1 2019-05-07        1
          2 2019-05-07        1
          1 2019-05-08        1
          2 2019-05-08        1
          1 2019-05-09        1
          1 2019-05-10        1
          1 2019-05-11        1
          2 2019-05-11        1
          2 2019-05-12        1
          2 2019-05-13        1
          2 2019-05-14        1
          2 2019-05-15        1
          1 2019-05-16        1")

OutPut:
USER_ID SOLVED_DATE NUMBER_QUESTIONS_SOLVED PAST_7DAY_SOLVED_HISTORY
           1 2019-05-01        1                       0
           1 2019-05-02        1                       1
           2 2019-05-02        1                       0
           2 2019-05-03        1                       1
           2 2019-05-04        1                       2
           1 2019-05-05        1                       2
           2 2019-05-05        1                       3
           1 2019-05-06        1                       3
           2 2019-05-06        1                       4
           1 2019-05-07        1                       4
           2 2019-05-07        1                       5
           1 2019-05-08        1                       4
           2 2019-05-08        1                       6
           1 2019-05-09        1                       4
           1 2019-05-10        1                       5
           1 2019-05-11        1                       6
           2 2019-05-11        1                       4
           2 2019-05-12        1                       4
           2 2019-05-13        1                       4
           2 2019-05-14        1                       4
           2 2019-05-15        1                       4
           1 2019-05-16        1                       2

Ответы [ 3 ]

6 голосов
/ 13 июня 2019

Мы могли бы сначала преобразовать SOLVED_DATE в фактические даты, а затем использовать map_dbl из purrr, чтобы узнать, сколько вопросов решено за последние 7 дней.

library(dplyr)
library(purrr)

df %>%
  mutate(SOLVED_DATE = as.Date(SOLVED_DATE)) %>%
  group_by(USER_ID) %>%
  mutate(Order_History = map_dbl(SOLVED_DATE, 
        ~sum(QUESTIONS_SOLVED[(SOLVED_DATE > . - 7) & (SOLVED_DATE < .)])))

#   USER_ID SOLVED_DATE QUESTIONS_SOLVED Order_History
#     <int> <date>                 <int>         <dbl>
# 1       1 2019-05-01                 1             0
# 2       1 2019-05-02                 1             1
# 3       2 2019-05-02                 1             0
# 4       2 2019-05-03                 1             1
# 5       2 2019-05-04                 1             2
# 6       2 2019-05-05                 1             3
# 7       1 2019-05-06                 1             2
# 8       2 2019-05-06                 1             4
# 9       1 2019-05-07                 1             3
#10       2 2019-05-07                 1             5
# … with 11 more rows
2 голосов
/ 13 июня 2019

Альтернативой является использование rollapply() из пакета zoo.Однако мне пришлось завершить последовательность дат, а затем удалить дополнительные строки.Так что ответ Ронакса, вероятно, более практичный.

library(zoo)
library(tidyverse)

df %>%
  mutate(SOLVED_DATE = as.Date(SOLVED_DATE)) %>%
  group_by(USER_ID) %>%
  complete(SOLVED_DATE = full_seq(SOLVED_DATE, 1)) %>%
  mutate(PAST_7DAY_ORDER_HISTORY = rollapply(QUESTIONS_SOLVED, width = 7, align = "right", 
                                             FUN = function(x) sum(x[-1], na.rm = T), 
                                             fill = NA, partial = T)) %>%
  filter(!is.na(QUESTIONS_SOLVED))

Это, тем не менее, хорошая функция для такого рода работы.Вы можете установить размер окна с помощью width =, указать ему, как выровнять окно.

0 голосов
/ 15 июня 2019

Вот решение для неравного соединения data.table. Это зависит от обновления по ссылке.

library (data.table)
  dt[, SOLVED_DATE := as.Date(SOLVED_DATE)]
  dt[, `:=` (END_RANGE = SOLVED_DATE - 7, PAST_7DAY_SOLVED_HISTORY = 0L)]

  dt[dt
     , on = .(USER_ID
              , SOLVED_DATE > SOLVED_DATE
              , END_RANGE < SOLVED_DATE)
     , PAST_7DAY_SOLVED_HISTORY :=.N
     , by = .EACHI
     ][, END_RANGE := NULL]

Вот решение dplyr в том же духе, которое использует некоторые идеи @Ronak Shah для суммирования.

tib%>%
  mutate(SOLVED_DATE = as.Date(SOLVED_DATE))%>%
  inner_join(.,., by = 'USER_ID')%>%
  group_by(USER_ID, SOLVED_DATE = SOLVED_DATE.x)%>%
  summarize(
    QUESTIONS_SOLVED = first(QUESTIONS_SOLVED.x) #a little hacky
    , PAST_7DAY_SOLVED_HISTORY =sum(QUESTIONS_SOLVED.x[SOLVED_DATE.x > SOLVED_DATE.y & SOLVED_DATE.x - 7 < SOLVED_DATE.y]))

Для этого набора данных @Ronak - самый быстрый.

Unit: milliseconds
            expr    min      lq      mean median      uq     max neval
     purrr_ronak 2.0315 2.13435  2.306462 2.1988 2.32110  5.2616   100
 dplyr_cole_join 2.2900 2.38270  2.716720 2.4537 2.54155 17.7151   100
         dt_cole 4.4387 4.77680  5.102791 5.0109 5.16260  9.7652   100
  dplyr_zoo_hump 8.9480 9.31415 10.067683 9.4534 9.92390 40.9371   100
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...