如何使用特定时间 window 调用函数?
How do I call a function using a specific time window?
假设我有一个动物园对象(或者它可能是一个 data.frame),它在 "time of day" 上有一个索引并且有一些值(见下面的示例数据):
val
...
2006-08-01 12:00 23
2006-08-01 12:01 24
2006-08-01 12:02 25
2006-08-01 12:03 26
2006-08-01 12:04 27
2006-08-01 12:05 28
2006-08-01 12:06 29
...
2006-08-02 12:00 123
2006-08-02 12:01 124
2006-08-02 12:02 125
2006-08-02 12:03 126
2006-08-02 12:04 127
...
我想在每次出现该间隔时从 12:01 - 12:03(即类似于 zoo::rollapply)调用一个自定义函数(称之为 custom.func(vals)
)所以在这个例子中,每天。我该怎么做?
注意事项(为了稳健性,考虑以下边缘情况也很好,但不是必需的):
- 不要假设我每天都有 12:01 - 12:03 的值
- 不要假设整个范围 12:01 - 12:03 每天都存在。有些日子我可能只有 12:01 和 12:02 但可能会丢失 12:03
- 如果我希望我的
custom.func(vals)
在日期边界被调用怎么办,比如使用 23:58 - 00:12 中的 val
?
我建议 runner package which allows to compute any rolling function on irregular time series. Function runner 等同于 rollApply
,区别在于它可以依赖于日期。 runner
允许在 window 长度上应用任何 R 函数,长度由 k
定义,日期为 idx
(或任何整数)。下面的示例计算 5 分钟(5*60 秒)window 跨度的回归。算法不关心是否会有日变化,每次只计算 5 分钟(例如 23:56-00:01)。
创建数据:
set.seed(1)
x <- cumsum(rnorm(1000))
y <- 3 * x + rnorm(1000)
time <- as.POSIXct(cumsum(sample(60:120, 1000, replace = TRUE)),
origin = Sys.Date()) # unequaly spaced time series
data <- data.frame(time, y, x)
滑动时调用的自定义函数windows:
library(runner)
running_regression <- function(idx) {
predict(lm(y ~ x, data = data))[max(idx)]
}
data$pred <- runner(seq_along(x),
k = 60 * 5,
idx = time,
f = running_regression)
一旦我们创建了具有滚动 5 分钟预测的数据集,那么我们就可以仅过滤特定的 windows - 此处,仅过滤一小时的第 1 分钟。这意味着我们总是保持 {hh}:56 - {hh+1}:01
library(dplyr)
library(lubridate)
filtered <-
data %>%
filter(minute(time) == 1)
plot(data$time, data$y, type = "l", col = "red")
points(filtered$time, filtered$pred, col = "blue")
在 vignette 中还有一些其他示例如何使用 runner
假设我们的输入是最后注释中给出的POSIXct动物园对象z
。
创建一个字符向量 times
,其中每个 z
的元素一个元素,形式为 HH:MM。然后创建一个逻辑 ok
指示哪些时间在指示的边界值之间。 z[ok]
然后 z
减少到这些值。最后,每天使用 aggregate.zoo
应用 sum
(如果需要可以使用其他功能):
times <- format(time(z), "%H:%M")
ok <- times >= "12:01" & times <= "12:03"
aggregate(z[ok], as.Date, sum)
## 2006-08-01 2006-08-02
## 75 375
次跨越午夜
该版本适用于时间跨越午夜的情况。请注意,发送到函数的值的顺序不是原始顺序,但如果函数是对称的,则无关紧要。
times <- format(time(z), "%H:%M")
ok <- times >= "23:58" | times <= "00:12"
aggregate(z[ok], (as.Date(format(time(z))) + (times >= "23:58"))[ok], sum)
## 2006-08-02
## 41
变化
如果函数在其参数的组件中是对称的(许多函数都是这种情况,例如 mean
和 sum
)但如果函数不对称,则先前的代码块有效我们需要一种稍微不同的方法。我们定义 to.sec
将 HH:MM 字符串转换为数字秒,并从每个 POSIXct 日期时间中减去 to.sec("23:58")
。那么z
的分量就是那些变换时间转换成HH:MM个小于"00:14"的字符串的分量。
to.sec <- function(x) with(read.table(text = x, sep = ":"), 3600 * V1 + 60 * V2)
times <- format(time(z) - to.sec("23:58"), "%H:%M")
ok <- times <= "00:14"
aggregate(z[ok], as.Date(time(z)[ok] - to.sec("23:58")), sum)
## 2006-08-01
## 41
备注
Lines <- "datetime val
2006-08-01T12:00 23
2006-08-01T12:01 24
2006-08-01T12:02 25
2006-08-01T12:03 26
2006-08-01T12:04 27
2006-08-01T12:05 28
2006-08-01T12:06 29
2006-08-01T23:58 20
2006-08-02T00:01 21
2006-08-02T12:00 123
2006-08-02T12:01 124
2006-08-02T12:02 125
2006-08-02T12:03 126
2006-08-02T12:04 127"
library(zoo)
z <- read.zoo(text = Lines, tz = "", header = TRUE, format = "%Y-%m-%dT%H:%M")
编辑
修改了非对称代码并简化了所有代码块。
假设我有一个动物园对象(或者它可能是一个 data.frame),它在 "time of day" 上有一个索引并且有一些值(见下面的示例数据):
val
...
2006-08-01 12:00 23
2006-08-01 12:01 24
2006-08-01 12:02 25
2006-08-01 12:03 26
2006-08-01 12:04 27
2006-08-01 12:05 28
2006-08-01 12:06 29
...
2006-08-02 12:00 123
2006-08-02 12:01 124
2006-08-02 12:02 125
2006-08-02 12:03 126
2006-08-02 12:04 127
...
我想在每次出现该间隔时从 12:01 - 12:03(即类似于 zoo::rollapply)调用一个自定义函数(称之为 custom.func(vals)
)所以在这个例子中,每天。我该怎么做?
注意事项(为了稳健性,考虑以下边缘情况也很好,但不是必需的):
- 不要假设我每天都有 12:01 - 12:03 的值
- 不要假设整个范围 12:01 - 12:03 每天都存在。有些日子我可能只有 12:01 和 12:02 但可能会丢失 12:03
- 如果我希望我的
custom.func(vals)
在日期边界被调用怎么办,比如使用 23:58 - 00:12 中的val
?
我建议 runner package which allows to compute any rolling function on irregular time series. Function runner 等同于 rollApply
,区别在于它可以依赖于日期。 runner
允许在 window 长度上应用任何 R 函数,长度由 k
定义,日期为 idx
(或任何整数)。下面的示例计算 5 分钟(5*60 秒)window 跨度的回归。算法不关心是否会有日变化,每次只计算 5 分钟(例如 23:56-00:01)。
创建数据:
set.seed(1)
x <- cumsum(rnorm(1000))
y <- 3 * x + rnorm(1000)
time <- as.POSIXct(cumsum(sample(60:120, 1000, replace = TRUE)),
origin = Sys.Date()) # unequaly spaced time series
data <- data.frame(time, y, x)
滑动时调用的自定义函数windows:
library(runner)
running_regression <- function(idx) {
predict(lm(y ~ x, data = data))[max(idx)]
}
data$pred <- runner(seq_along(x),
k = 60 * 5,
idx = time,
f = running_regression)
一旦我们创建了具有滚动 5 分钟预测的数据集,那么我们就可以仅过滤特定的 windows - 此处,仅过滤一小时的第 1 分钟。这意味着我们总是保持 {hh}:56 - {hh+1}:01
library(dplyr)
library(lubridate)
filtered <-
data %>%
filter(minute(time) == 1)
plot(data$time, data$y, type = "l", col = "red")
points(filtered$time, filtered$pred, col = "blue")
在 vignette 中还有一些其他示例如何使用 runner
假设我们的输入是最后注释中给出的POSIXct动物园对象z
。
创建一个字符向量 times
,其中每个 z
的元素一个元素,形式为 HH:MM。然后创建一个逻辑 ok
指示哪些时间在指示的边界值之间。 z[ok]
然后 z
减少到这些值。最后,每天使用 aggregate.zoo
应用 sum
(如果需要可以使用其他功能):
times <- format(time(z), "%H:%M")
ok <- times >= "12:01" & times <= "12:03"
aggregate(z[ok], as.Date, sum)
## 2006-08-01 2006-08-02
## 75 375
次跨越午夜
该版本适用于时间跨越午夜的情况。请注意,发送到函数的值的顺序不是原始顺序,但如果函数是对称的,则无关紧要。
times <- format(time(z), "%H:%M")
ok <- times >= "23:58" | times <= "00:12"
aggregate(z[ok], (as.Date(format(time(z))) + (times >= "23:58"))[ok], sum)
## 2006-08-02
## 41
变化
如果函数在其参数的组件中是对称的(许多函数都是这种情况,例如 mean
和 sum
)但如果函数不对称,则先前的代码块有效我们需要一种稍微不同的方法。我们定义 to.sec
将 HH:MM 字符串转换为数字秒,并从每个 POSIXct 日期时间中减去 to.sec("23:58")
。那么z
的分量就是那些变换时间转换成HH:MM个小于"00:14"的字符串的分量。
to.sec <- function(x) with(read.table(text = x, sep = ":"), 3600 * V1 + 60 * V2)
times <- format(time(z) - to.sec("23:58"), "%H:%M")
ok <- times <= "00:14"
aggregate(z[ok], as.Date(time(z)[ok] - to.sec("23:58")), sum)
## 2006-08-01
## 41
备注
Lines <- "datetime val
2006-08-01T12:00 23
2006-08-01T12:01 24
2006-08-01T12:02 25
2006-08-01T12:03 26
2006-08-01T12:04 27
2006-08-01T12:05 28
2006-08-01T12:06 29
2006-08-01T23:58 20
2006-08-02T00:01 21
2006-08-02T12:00 123
2006-08-02T12:01 124
2006-08-02T12:02 125
2006-08-02T12:03 126
2006-08-02T12:04 127"
library(zoo)
z <- read.zoo(text = Lines, tz = "", header = TRUE, format = "%Y-%m-%dT%H:%M")
编辑
修改了非对称代码并简化了所有代码块。