我正在寻找一个与具有基于时间的窗口的不规则时间序列上的优化滚动函数密切相关的问题的帮助。
我想计算我的函数(在下面的例子中它是总和,但可以很容易地是最小值或最大值或中位数......(在时间步长上达到一定分钟数,但不超过这个数字。因此,如果我感兴趣的持续时间是 8 分钟,而我第三次的时间步长为 2,2,5,我只想对最后 2 个数字的值求和(总时间为 7(,不包括第一个,这将给出总时间为 9。所以基本上我希望尽可能接近我的持续时间而不超过。
对于上下文,值是降雨数据,mindiff是记录间隔。因此,如果我有 5 分钟的时间步长,那么在这 5 分钟内的任何时间都可能发生下雨。我只想找到我能保证的雨在最后 8 分钟内下过,所以任何在 8 分钟前开始的时间步长我都不确定,我想排除。
下面的代码非常接近我想要的(根据 Uwe 对上述问题的回答进行调整(,但它包括一个点之前,除非间隔正好等于我的持续时间。如果时间步长大于持续时间,我也希望它转到 NA,但这之后很容易实现。
末尾包含所需输出的示例:
library(tibble)
library(data.table)
set.seed(1)
testdf <- tibble(mindiff = c(1,2,1,2,5,2,2,2,11,5,3,2,0,1),
DateTime = as.POSIXct("2019-01-01 00:00", z = "Etc/GMT-10")+(cumsum(mindiff)*60),
Value = round(runif(14,0,5),1))
dur8= 60*8
testdf[["Total8Min"]] <- setDT(testdf)[, rn := .I][.(ur = rn, ud = DateTime, ld = DateTime - dur8),
on = .(rn <= ur, DateTime <= ud, DateTime > ld),
sum(as.double(Value)), by = .EACHI]$V1
testdf$desiredOut <- c(1.3,3.2,6.1,10.6,8.4,5.5,9.2,12.5,NA, 0.3,1.3,1.9,5.3,7.2)
创建于 2019-08-21 由 reprex 软件包 (v0.3.0(
我在data.table
有点新手,如果有人有tidyverse
方法,我更习惯于为tidyverse
方法感到高兴。
针对评论进一步解释: 在第 6 行的所需输出中,我只希望输出为 5.5,这是过去 2 分钟(从 00:11 到 00:13(和之前的 5 分钟(从 00:06 到 00:11(下降的输出。我不想在第 4 行中包含该值,因为这场雨可能会在 00:04 到 00:06 的任何时间下降 - 可能都在 00:05 之前,也就是我在第 6 行的"现在"时间之前的 8 分钟。
这是使用cumsum
的另一种可能方法(DateTime
结果是红鲱鱼(:
setDT(testdf)[, c("rn", "cs", "lagcs") := .(.I, cs <- cumsum(mindiff), cs - mindiff)]
testdf[, do := testdf[.(rn=rn, start=cs-8), on=.(rn<=rn, lagcs>=start),
sum(Value), by=.EACHI]$V1]
输出:
mindiff Value desiredOut rn cs lagcs do
1: 1 1.3 1.3 1 1 0 1.3
2: 2 1.9 3.2 2 3 1 3.2
3: 1 2.9 6.1 3 4 3 6.1
4: 2 4.5 10.6 4 6 4 10.6
5: 5 1.0 8.4 5 11 6 8.4
6: 2 4.5 5.5 6 13 11 5.5
7: 2 4.7 9.2 7 15 13 9.2
8: 2 3.3 12.5 8 17 15 12.5
9: 11 3.1 NA 9 28 17 NA
10: 5 0.3 0.3 10 33 28 0.3
11: 3 1.0 1.3 11 36 33 1.3
12: 2 0.9 1.9 12 38 36 1.9
13: 0 3.4 5.3 13 38 38 5.3
14: 1 1.9 7.2 14 39 38 7.2
数据:
library(data.table)
set.seed(1)
mindiff = c(1,2,1,2,5,2,2,2,11,5,3,2,0,1)
testdf <- data.table(mindiff = mindiff, Value = round(runif(14,0,5),1))
testdf$desiredOut <- c(1.3,3.2,6.1,10.6,8.4,5.5,9.2,12.5,NA, 0.3,1.3,1.9,5.3,7.2)
>我认为@chinsoon12有一个更好且可扩展的方法,但由于我已经开始研究我的解决方案,所以我还是会发布它。
library(dplyr)
testdf %>%
mutate(row = row_number(),
out = purrr::map2_dbl(DateTime, row, ~{
inds <- which(DateTime > (.x - dur8) & DateTime <= .x & .y >= row)
if (sum(mindiff[inds]) > 8) sum(Value[inds[-1L]]) else sum(Value[inds])
})) %>%
select(-row)
# A tibble: 14 x 5
# mindiff DateTime Value desiredOut out
# <dbl> <dttm> <dbl> <dbl> <dbl>
# 1 1 2019-01-01 00:01:00 1.3 1.3 1.3
# 2 2 2019-01-01 00:03:00 1.9 3.2 3.2
# 3 1 2019-01-01 00:04:00 2.9 6.1 6.1
# 4 2 2019-01-01 00:06:00 4.5 10.6 10.6
# 5 5 2019-01-01 00:11:00 1 8.4 8.4
# 6 2 2019-01-01 00:13:00 4.5 5.5 5.5
# 7 2 2019-01-01 00:15:00 4.7 9.2 9.2
# 8 2 2019-01-01 00:17:00 3.3 12.5 12.5
# 9 11 2019-01-01 00:28:00 3.1 NA 0
#10 5 2019-01-01 00:33:00 0.3 0.3 0.3
#11 3 2019-01-01 00:36:00 1 1.3 1.3
#12 2 2019-01-01 00:38:00 0.9 1.9 1.9
#13 0 2019-01-01 00:38:00 3.4 5.3 5.3
#14 1 2019-01-01 00:39:00 1.9 7.2 7.2
在这里,对于每DateTime
,我们都会sum
8 分钟范围内的Value
。