R中双索引的滚动总和

Rolling sum with double indexing in R

我想计算 R 中两个索引列的滚动总和或滚动计数。以下数据 table 有一个显示销售量的列和两个日期列。我想创建第 4 列,它给出 Column index2 中的日期数小于 Column index1 中的日期,我还希望第 5 列给出与第四列相关的销售额总和列。

sales_vec <- c(2, 4, 3, 5)
index1_vec <- as.Date("2019-08-29") + c(0, 2, 5, 6)
index2_vec <- as.Date("2019-08-29") + c(-5, 2, 1, -3)
company <- tibble(
  sales = sales_vec,
  index1 = index1_vec ,
  index2 = index2_vec 
)

> print(company)
# A tibble: 4 x 3
  sales index1     index2    
  <dbl> <date>     <date>    
1     2 2019-08-29 2019-08-24
2     4 2019-08-31 2019-08-31
3     3 2019-09-03 2019-08-30
4     5 2019-09-04 2019-08-26

我的结果应该是这样的:

# A tibble: 4 x 5
  sales index1     index2     rollingCount rollingSum
  <dbl> <date>     <date>            <dbl>      <dbl>
1     2 2019-08-29 2019-08-24            2          7
2     4 2019-08-31 2019-08-31            3         10
3     3 2019-09-03 2019-08-30            4         14
4     5 2019-09-04 2019-08-26            4         14

rollingCount的第一行是2,因为Column index2中有两个日期小于index1的第一行,与这两行相关联的销售额之和为2 + 5 = 7,显示在 rollingSum 的第一行。 rollingCount 的第二行是 3,因为 Column index2 中有三个日期小于 index1 的第二行,与这三行相关的销售额总和为 2 + 5 + 3 = 10,显示在第二行滚动总和行。等等。

我熟悉用于滚动计算的“幻灯片”命令系列,但我很难完成这项任务,因为它有两个索引列。

base R中,我们可以使用sapply遍历'index1'列,用index2列创建一个逻辑向量,用它来得到[=逻辑向量的 15=] 和 'sales'

子集的 sum
cbind(company, t(sapply(company$index1, function(x) {
        i1 <- company$index2  < x
    c(rollingCount = sum(i1), rollingSum = sum(company$sales[i1])) })))
#  sales     index1     index2 rollingCount rollingSum
#1     2 2019-08-29 2019-08-24            2          7
#2     4 2019-08-30 2019-08-31            3         10
#3     3 2019-09-03 2019-08-30            4         14
#4     5 2019-09-04 2019-08-26            4         14

或者另一个选项是 tidyverse

library(dplyr)
library(purrr)
map_dfr(company$index1, ~ {
       i1 <- company$index2 < .x
       tibble(rollingCount = sum(i1), rollingSum = sum(company$sales[i1]))}) %>%
    bind_cols(company, .)
# A tibble: 4 x 5
#  sales index1     index2     rollingCount rollingSum
#  <dbl> <date>     <date>            <int>      <dbl>
#1     2 2019-08-29 2019-08-24            2          7
#2     4 2019-08-30 2019-08-31            3         10
#3     3 2019-09-03 2019-08-30            4         14
#4     5 2019-09-04 2019-08-26            4         14

这里有几种方法:

使用rowwise

library(dplyr)
library(purrr)

company %>%
  rowwise() %>%
  mutate(rollingCount = sum(index1 > .$index2), 
         rollingSum = sum(.$sales[index1 > .$index2]))


#  sales index1     index2     rollingCount rollingSum
#  <dbl> <date>     <date>            <int>      <dbl>
#1     2 2019-08-29 2019-08-24            2          7
#2     4 2019-08-31 2019-08-31            3         10
#3     3 2019-09-03 2019-08-30            4         14
#4     5 2019-09-04 2019-08-26            4         14

并使用 purrr 中的 map_dbl :

company %>%
   mutate(rollingCount = map_dbl(index1, ~{
                 vec <- .x > index2
                 sum(vec)
                 }),
          rollingSum = map_dbl(index1, ~sum(sales[.x > index2])))