我想累积一个长期(包括不同年份)每天测量的变量。变量的累积应从一年中的固定日期开始(例如,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))
编辑: 谢谢你的帮助。 它如何与data.table包一起工作?
答案 0 :(得分:0)
让我们从功能界面开始,该界面是可以解决问题的功能列表以及其输入和输出。
函数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
相同。
is_feb_1st
将返回TRUE
,否则返回FALSE
。我将把它留给您练习。
功能接口使用原始函数which
,split
和lapply
,其原始文档仅供练习阅读。
现在,解决方案的轮廓可以写为:
restart_feb_first<-function(data.frame) {
reset_cum_sums(data.frame$value,
which(is_feb_first(data.frame$date))
}
如果您的数据中2月的第一个出现在位置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
编写起来应该很容易,但是让我们再待一天。
此函数返回一个向量,因此要与数据表包一起使用,只需添加一个赋值即可,如
DT[,new_column:=reset_sum(value,,isFebFirst(date)]