每年的固定日期开始cumsum()

问题描述 投票:0回答:1

我想累积一个长期(包括不同年份)每天都测量的变量。变量的累积应从一年中的固定日期开始(例如,2月1日,或者换句话说,每年的日数(doy)32-我以前在doys工作)。每年的累积金额应从这个固定的日期开始。

我尝试使用setDT(df)[, whatiwant := cumsum(variable), by = rleid(DOY >= 32)]rle(DOY >= 32),但他们都不考虑每年的头几天。

理论上,函数ave()应该可以正常工作,但是我不知道如何在不同年份的doy之间创建一个标志变量(它通常仅创建第一个)。

df <- data.frame(Date = seq(as.Date("2010-01-01"), by = 1, len = 1000),
                 Year = format(seq(as.Date("2010-01-01"), by = 1, len = 1000), "%Y"),
                 DOY = format(seq(as.Date("2010-01-01"), by = 1, len = 1000), "%j"),
                 Variable = rnorm(1000, mean=10, sd=3))
r flags cumsum
1个回答
0
投票

让我们从功能接口开始,该接口是可以解决问题的功能列表以及它们的输入和输出。

  1. 函数reset_cum_sums包含两个元素,一个向量和该向量的重置位置列表。 输出将是一个包含累积总和的向量,并且总和在向量的每个所需位置重新开始。一个例子应该使它更清楚:

    在每个重置位置,累计和重置。因此,如果输入为1:10,位置矢量为3 5 7,则输出为

    input: [1 2 3 4 5 6 7 8 9 10]

    output: [1 3 3 7 5 11 7 15 24 34]

如果未给出位置,将产生与cumsum相同的结果。

  1. is_feb_1st如果日期为2月1日,则返回TRUE,否则为FALSE。我将把它留给您练习。

  2. 功能接口使用原始函数whichsplitlapply,其原始文档仅供阅读。]]

  3. 现在,解决方案的轮廓可以写成:

restart_feb_first<-function(data.frame) {
   reset_cum_sums(data.frame$value,  
       which(is_feb_first(data.frame$date))
   }

如果您的数据中的二月初值出现在位置32,32 + 365,32 + 730,..,则将构成您的位置向量。好消息是您可以轻松容纳leap年。

唯一具有挑战性的部分是写reset_cum_sums;在这里,我提供了一种方法,不一定是最有效的方法。该程序将向量分成多个块,每个块都从适当的位置开始(在您的情况下,二月初)。请注意,此示例不需要管道操作员。您可以改用传统的功能符号。

另外,我以这种方式编写函数来说明一些R概念,而不一定编写性能最高的代码。但是,如果要重写,则只需将您在此功能上的工作隔离开。

#
# purpose: define a function that creates cumulative  sums
# of vectors, but which reset at each position given by 
# the vector `positions`, which can be null.
# reset_sum

# parameters for hypothetical example
set.seed(18)
values=runif(50)

# cumulative sums reset at these positions.
positions=c(3,13,23,33,43)

# dependencies
require(magrittr) # or tidyverse for pipe operator


reset_sum = function(vector,positions) {
   k=length(vector)
  # cut the list into pieces 
  splitter=cut(1:k,breaks=c(-Inf,positions,Inf),right = FALSE)
  pieces=split(vector,splitter)
  # do the cumsum of each piece, and then glue then back together
  pieces %>%  lapply(cumsum) %>% unlist(use.names=FALSE)
}

这里是该函数的调用方式

# examples
reset_sum(values,positions)
reset_sum(rep(1,50),positions)

我希望这可以指导您找到适合您需求的解决方案。关键概念是将其分解,直到找到一个根据R原语“易于”编写的函数。如果您需要reset_cum_sums超级高效,那么用C或data.table编写应该相当容易,但是让我们再待一天。

© www.soinside.com 2019 - 2024. All rights reserved.