Кумулятивные суммы в R с несколькими условиями? - PullRequest
2 голосов
/ 18 апреля 2020

Я пытаюсь выяснить, как создать накопительную или скользящую сумму в R на основе нескольких условий.

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

Итак, для каждого Title.ID начните с 1 копии для первого экземпляра (ID.Index). Затем для каждого последующего экземпляра определите, нужна ли еще одна копия, исходя из того, находится ли REQUEST.DATE в течение 16 недель (112 дней) от предыдущего запроса.

# A tibble: 15 x 3
# Groups:   Title.ID [2]
   REQUEST.DATE Title.ID ID.Index
   <date>          <int>    <int>
 1 2013-07-09          2        1
 2 2013-08-07          2        2
 3 2013-08-20          2        3
 4 2013-09-08          2        4
 5 2013-09-28          2        5
 6 2013-12-27          2        6
 7 2014-02-10          2        7
 8 2014-03-12          2        8
 9 2014-03-14          2        9
10 2014-08-27          2       10
11 2014-04-27          6        1
12 2014-08-01          6        2
13 2014-11-13          6        3
14 2015-02-14          6        4
15 2015-05-14          6        5

Хитрость в том, что определение необходимости новой копии основано не только на количестве запросов (ID.Index) и запросе . ДАТА некоторого предыдущего кредита, но также и на предыдущую сумму накопления.

Например, для третьего запроса на заголовок 2 (Title.ID 2, ID.Index 3) теперь есть две копии, поэтому, чтобы определить, нужна ли новая копия, вы должны увидеть, REQUEST.DATE находится в течение 112 дней с момента запроса первый (не второй ) (ID.Index 1). В отличие от этого, для третьего запроса на заголовок 6 (Title.ID 6, ID.Index 3) доступна только одна копия (поскольку запрос 2 был не в течение 112 дней), поэтому определение необходимости новой копии основано на возвращаясь к REQUEST.DATE для ID.Index 2.

Требуемый вывод («Копии») будет принимать каждый новый запрос (ID.Index), а затем возвращаться к соответствующему REQUEST.DATE на основе количество доступных копий, и это будет означать просмотр накопленной суммы для предыдущего расчета. (Примечание: максимальное количество копий будет равно 10.)

Я предоставил желаемый вывод для примера ниже («Копии»).

# A tibble: 15 x 4
# Groups:   Title.ID [2]
   REQUEST.DATE Title.ID ID.Index Copies
   <date>          <int>    <int>  <dbl>
 1 2013-07-09          2        1      1
 2 2013-08-07          2        2      2
 3 2013-08-20          2        3      3
 4 2013-09-08          2        4      4
 5 2013-09-28          2        5      5
 6 2013-12-27          2        6      5
 7 2014-02-10          2        7      5
 8 2014-03-12          2        8      5
 9 2014-03-14          2        9      5
10 2014-08-27          2       10      5
11 2014-04-27          6        1      1
12 2014-08-01          6        2      2
13 2014-11-13          6        3      2
14 2015-02-14          6        4      2
15 2015-05-14          6        5      2
> 

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

Спасибо миллион!

* 4/19 обновление: новые примеры, где новая копия может быть добавлена ​​после задержки, т.е. не по порядку. Я также добавил столбцы, показывающие дни с момента выполнения предыдущего запроса, что помогает проверить, нужно ли добавлять новую копию, исходя из того, сколько существует копий.

Образец 2: новая копия должна быть добавлена ​​с третьим запросом, поскольку прошло всего 96 дней с момента последнего запроса (и существует только одна копия)

REQUEST.NUMBER REQUEST.DATE Title.ID ID.Index Days.Since Days.Since2 Days.Since3 Days.Since4 Days.Since5 Copies
  <fct>          <date>          <int>    <int> <drtn>     <drtn>      <drtn>      <drtn>      <drtn>       <int>
1 BRO-10680332   2013-10-17          6        1  NA days    NA days     NA days     NA days     NA days         1
2 PEN-10835735   2014-04-27          6        2 192 days    NA days     NA days     NA days     NA days         1
3 PEN-10873506   2014-08-01          6        3  96 days   288 days     NA days     NA days     NA days         1
4 PEN-10951264   2014-11-13          6        4 104 days   200 days    392 days     NA days     NA days         1
5 PEN-11029526   2015-02-14          6        5  93 days   197 days    293 days    485 days     NA days         1
6 PEN-11106581   2015-05-14          6        6  89 days   182 days    286 days    382 days    574 days         1

Образец 3: новая копия должен быть добавлен с последним запросом, поскольку существует две копии, а самый старый запрос составляет 45 дней.

REQUEST.NUMBER REQUEST.DATE Title.ID ID.Index Days.Since Days.Since2 Days.Since3 Days.Since4 Days.Since5 Copies
  <fct>          <date>          <int>    <int> <drtn>     <drtn>      <drtn>      <drtn>      <drtn>       <int>
1 BRO-10999392   2015-01-20         76        1  NA days    NA days     NA days     NA days     NA days         1
2 YAL-11004302   2015-01-22         76        2   2 days    NA days     NA days     NA days     NA days         2
3 COR-11108471   2015-05-18         76        3 116 days   118 days     NA days     NA days     NA days         2
4 HVD-11136632   2015-07-27         76        4  70 days   186 days    188 days     NA days     NA days         2
5 MIT-11164843   2015-09-09         76        5  44 days   114 days    230 days    232 days     NA days         2
6 HVD-11166239   2015-09-10         76        6   1 days    45 days    115 days    231 days    233 days         2

Ответы [ 2 ]

0 голосов
/ 21 апреля 2020

Мне удалось найти работоспособное решение, основанное на нахождении максимального количества других запросов в течение 112 дней после запроса (после создания даты возврата) для каждого заголовка.

data$RETURN.DATE <- as.Date(data$REQUEST.DATE + 112)
data <- data %>% 
  group_by(Title.ID) %>% 
  mutate(
    Copies = sapply(REQUEST.DATE, function(x)
      sum(as.Date(REQUEST.DATE) <= as.Date(x) &
            as.Date(RETURN.DATE) >= as.Date(x)
      ))
  )

Затем я дедуплицировал список заголовков, используя максимальное число для каждого заголовка, и добавил его обратно к исходным данным.

Я все еще думаю, что есть решение исходной проблемы, где я мог бы go вернуться назад и посмотреть, в какой момент необходимо добавить новые копии (для анализа, основанного на публикации заголовка), но это работает теперь.

0 голосов
/ 18 апреля 2020

Вы можете использовать пакет runner , чтобы применить любую функцию R к совокупному окну . На этот раз мы выполняем функцию f, используя x = REQUEST.DATE. Мы просто посчитаем количество наблюдений, которые находятся в пределах min(x) + 112.

library(dplyr)
library(runner)

data %>%
  group_by(Title.ID) %>%
  mutate(
    Copies = runner(
      x = REQUEST.DATE,
      f = function(x) {
        length(x[x <= (min(x + 112))])
      }
    )
  )

# # A tibble: 15 x 4
# # Groups:   Title.ID [2]
#        REQUEST.DATE Title.ID ID.Index Copies
#        <date>          <int>    <int>  <int>
#    1 2013-07-09          2        1      1
#    2 2013-08-07          2        2      2
#    3 2013-08-20          2        3      3
#    4 2013-09-08          2        4      4
#    5 2013-09-28          2        5      5
#    6 2013-12-27          2        6      5
#    7 2014-02-10          2        7      5
#    8 2014-03-12          2        8      5
#    9 2014-03-14          2        9      5
#   10 2014-08-27          2       10      5
#   11 2014-04-27          6        1      1
#   12 2014-08-01          6        2      2
#   13 2014-11-13          6        3      2
#   14 2015-02-14          6        4      2
#   15 2015-05-14          6        5      2


data

data <- read.table(
  text = "   REQUEST.DATE Title.ID ID.Index
 1 2013-07-09          2        1
 2 2013-08-07          2        2
 3 2013-08-20          2        3
 4 2013-09-08          2        4
 5 2013-09-28          2        5
 6 2013-12-27          2        6
 7 2014-02-10          2        7
 8 2014-03-12          2        8
 9 2014-03-14          2        9
10 2014-08-27          2       10
11 2014-04-27          6        1
12 2014-08-01          6        2
13 2014-11-13          6        3
14 2015-02-14          6        4
15 2015-05-14          6        5", 
  header = TRUE)

data$REQUEST.DATE <- as.Date(as.character(data$REQUEST.DATE))

...