Сумма за 2 недели до конца каждого второго вторника - PullRequest
3 голосов
/ 11 июля 2020

У меня есть некоторые данные в формате, подобном воспроизводимому примеру ниже (код для ввода данных под вопросом, в конце). Две вещи:

  1. Не все даты имеют значение (т.е. многие даты отсутствуют).
  2. Некоторые даты имеют несколько значений, например 16 июня 2020 г.
#>        date value
#> 1 30-Jun-20    20
#> 2 29-Jun-20  -100
#> 3 26-Jun-20    -4
#> 4 16-Jun-20   -13
#> 5 16-Jun-20    40
#> 6  9-Jun-20    -6

Для двухнедельных периодов, заканчивающихся по вторникам, я хотел бы взять сумму столбца value.

Итак, в приведенном выше примере данных я хочу суммировать, заканчиваясь на:

  • две недели, заканчивающиеся во вторник, 16 июня 2020 г. (т.е. с 3 июня 2020 г. по 16 июня 2020 г. включительно)
  • две недели, заканчивающиеся во вторник, 30 июня 2020 г. (17 июня 2020 г. - 30 июня 2020 г. включительно)
  • В конечном итоге я бы хотел, чтобы код продолжал суммировать все двухнедельные периоды, заканчивающиеся каждый второй вторник, когда будет больше данных.

Итак, мой желаемый результат:

#2_weeks_end     total
#30-Jun-20    -84
#16-Jun-20     21

Я бы предпочел решения Tidyverse и lubridate.

Код для ввода данных ниже:

df <- data.frame(
  stringsAsFactors = FALSE,
                date = c("30-Jun-20","29-Jun-20",
                       "26-Jun-20","16-Jun-20","16-Jun-20","9-Jun-20"),
                value = c(20L, -100L, -4L, -13L, 40L, -6L)
)
df

Ответы [ 2 ]

3 голосов
/ 11 июля 2020

Решение с использованием findInterval ().

df$date <- dmy(df$date)
df_intervals <- seq(as.Date("2020-06-03"), as.Date("2020-06-03")+14*3, 14)

df %>%
  mutate(interval = findInterval(date, df_intervals)) %>%
  mutate(`2_weeks_end` = df_intervals[interval+1]-1) %>%
  group_by(`2_weeks_end`) %>%
  summarise(total= sum(value))

Возвращает:

# A tibble: 2 x 2
  2_weeks_end   total
  <date>     <int>
1 2020-06-16    21
2 2020-06-30   -84
1 голос
/ 11 июля 2020

Вот вариант, если вам нравится еженедельная или любая другая единица измерения, которая входит в lubridate по умолчанию:

library(dplyr)
library(lubridate)
df%>%
    mutate(date = as.Date(date, format = "%d-%b-%y"))%>%
    group_by(week_ceil = ceiling_date(date - 1L, unit = "week", week_start = 2L))%>%
    summarize(sums = sum(value))

Вот подход , который создает ссылку таблица, за которой следует неэквивалентное соединение:

library(data.table)
setDT(df)
df[, date := as.Date(date, format = "%d-%b-%y")]

ref_dt = df[,  .(beg_date = seq.Date(from = floor_date(min(date), unit = "week", week_start = 3L),
               to = max(date), 
               by =  "2 weeks"))]
ref_dt[, end_date := beg_date +13L]

df[ref_dt, 
   on = .(date > beg_date,
          date <= end_date),
   sum(value),
   by = .EACHI]

##         date       date  V1
##1: 2020-06-03 2020-06-16  21
##2: 2020-06-17 2020-06-30 -84
...