(dplyr)最近日期的N值之和

时间:2017-10-07 18:16:09

标签: r dplyr

我正在尝试创建一个函数,该函数将最接近的n值与给定日期相加。因此,如果我有5周的数据,并且n = 2,则第1周的值将是第2周和第3周的总和,第2周的值将是第1周和第3周的总和等。示例:

library(dplyr)
library(data.table)

Week <- 1:5
Sales <- c(1, 3, 5, 7, 9)

frame <- data.table(Week, Sales)
frame
   Week Sales  Recent
1:    1     1    8
2:    2     3    6
3:    3     5    10
4:    4     7    14
5:    5     9    12

我想为我做一个函数,为最近的n(不仅仅是2)提供输入,但是现在我想要2对。这是我使用lag / lead的函数:

RecentSum = function(Variable, Lags){
  Sum = 0
  for(i in 1:(Lags/2)){ #Lags/2 because I want half values before and half after
    #Check to see if you can go backwards. If not, go foward (i.e. use lead).
    if(is.na(lag(Variable, i))){
      LoopSum = lead(Variable, i)
    }
    else{
      LoopSum = lag(Variable, i)
    }
    Sum = Sum + LoopSum
  }
  for(i in 1:(Lags/2)){
    if(is.na(lead(Variable, i))){ #Check to see if you can go forward. If not, go backwards (i.e. use lag).
      LoopSum = lag(Variable, i)
    }
    else{
      LoopSum = lead(Variable, i)
    }
    Sum = Sum + LoopSum
  }
  Sum
}

当我RecentSum(frame$Sale,2)时,由于多种原因,我认为[1] 6 10 14 18 NA出错了:

  1. 我的if语句仅在第一周播出,因此延迟始终为NA,并且始终为非NA。
  2. 我需要有办法看看它是否第一次使用滞后/领先。第一个值是6而不是8,因为第一个for循环将它发送到lead(_,1),但是第二个for循环执行相同的操作。我想不出如何让我的第二个for-loop认识到这一点。
  3. 是否有功能或库(Zoo?)使这项任务变得简单?我想让自己的功能为了练习/理解而工作,但在这一点上我宁愿完成它。

    谢谢!

2 个答案:

答案 0 :(得分:4)

要详细说明我的评论,leadlag是要在dplyr等矢量化函数中使用的函数。这是一种在dplyr内不使用函数的方法:

df <- tibble(week = Week, sales = Sales)

df %>%
  mutate(recent = case_when(is.na(lag(sales)) ~ lead(sales, n = 1) + lead(sales, n = 2),
                            is.na(lead(sales)) ~ lag(sales, n = 1) + lag(sales, n = 2),
                            TRUE ~ lag(sales) + lead(sales)))

这给你这个:

# A tibble: 5 x 3
   week sales recent
   <int> <dbl>  <dbl>
1     1     1      8
2     2     3      6
3     3     5     10
4     4     7     14
5     5     9     12

答案 1 :(得分:1)

1)假设k甚至将to定义为索引的向量,使得对于to的每个元素,我们将{{1}的k + 1个元素相加在那个索引中结束并从中减去Sales

Sales

,并提供:

k <- 2  # number of elements to sum
n <- nrow(frame)
to <- pmax(k+1, pmin(1:n + k/2, n))
Sum <- function(to, Sales) sum(Sales[seq(to = to, length = k+1)])
frame %>% mutate(recent = sapply(to, Sum, Sales) - Sales)

请注意,通过使用以下行替换上面的最后一行代码,解决方案可以完全在基础R中完成:

  Week Sales recent
1    1     1      8
2    2     3      6
3    3     5     10
4    4     7     14
5    5     9     12    

2)这将连接Sales系列之前和之后的相应元素,以便普通滚动总和给出结果。

transform(frame, recent = sapply(to, Sum, Sales) - Sales)

请注意,如果k = 2,则将其减少到这个单行:

library(zoo)

ix <- c(seq(to = k+1, length = k/2), 1:n, seq(to = n-k, length = k/2))
frame %>% mutate(recent = rollsum(Sales[ix], k+1) - Sales)

,并提供:

frame %>% mutate(recent = rollsum(Sales[c(3, 1:n(), n()-2)], 3) - Sales)

更新:已修复为k&gt; 2