r语言 - 在滑动/平铺窗口上应用时间序列分解(和异常检测)



现在被Twitter放弃的异常检测方法已经在anomalize包和hrbrmstr/AnomalyDetection分叉中分别分叉和维护。两者都实现了"整洁"的功能。

工作静态版本

tidyverse_cran_downloads %>% 
filter(package == "tidyr") %>% 
ungroup() %>% 
select(-package) -> one_package_only
one_package_only %>% 
anomalize::time_decompose(count,
merge = TRUE,
method = "twitter",
frequency = "7 days") -> one_package_only_decomp
one_package_only_decomp %>%
anomalize::anomalize(remainder, method = "iqr") %>%
anomalize::time_recompose()

one_package_only_decomp %>% 
select(date, remainder) %>%
AnomalyDetection::ad_ts(max_anoms = 0.02,
direction = 'both')

这些按预期工作。

我想将平铺窗口上的 Twitter 异常检测过程应用于我的数据集,该数据集在结构上与anomalize::tidyverse_cran_downloads数据集相似。一个值的常规集合,包含 100 多个观测值,按分类定义分组。

tsibble包(取代旧tibbletime)具有通过幻灯片,平铺和拉伸以类似purrr语法应用函数的方法。这可以包括根据purrr在另一个类似数据帧的对象中返回一个完整的数据帧类对象。(什么句子!

我已经浏览了窗口功能小插图,但运气不佳。

尝试 1slide2

anomalize::decompose_twitter函数有两个参数,datatarget

tidyverse_cran_downloads %>%
mutate(
Monthly_MA = slide2_dfr(
.x = .,
.y = count,
~ anomalize::decompose_twitter,
.size = 5
)
)

Error: Element 1 has length 3, not 1 or 425. Callrlang::last_error()to see a backtrace

也许我误解了.x .y语法的工作原理?

尝试 2:pmap

my_diag <- function(...) {
data <- tibble(...)
fit <- anomalize::decompose_twitter(data = data, target = count)
}
tidyverse_cran_downloads %>%
nest(-package) %>%
filter(package %in% c("tidyr", "lubridate")) %>%  # just to make it quick
mutate(diag = purrr::map(data, ~ pslide_dfr(., my_diag, .size = 7)))

Error in stats::stl(., s.window = "periodic", robust = TRUE) : series is not periodic or has less than two periods

似乎有什么东西正在运行,但观察之间的时间段以某种方式关闭或未被解析?

尝试 3:ad_ts

ad_ts只接受一个参数,所以忽略我们还没有找到计算分解后余数的方法这一事实,我应该能够通过slide使用它。它还预计它x是:

作为两列数据框的时间序列,其中第一列由时间戳组成,第二列由观测值组成。

因此,在嵌套数据后,我们不必对数据执行太多操作。

tidyverse_cran_downloads %>%
nest(-package, .key = "my_data") %>%
mutate(
Daily_MA = slide_dfr(
.f = AnomalyDetection::ad_ts,
.x = my_data
)
)

Error in .f(.x[[i]], ...) : data must be a single data frame.

所以该函数至少被调用,但它被多个数据帧调用?

我想:

  • 通过 Twitter 算法应用分解过程,然后对其余部分进行异常检测
  • 使用
  • 两个异常情况检测包之一来执行此操作,或混合使用这两个包
  • 将其应用于时间窗口
  • 过度分组的分类数据

我的数据集唯一不同的是,我在几个月的时间内对值进行了半小时的观测,实际上我只需要每天重新计算异常(即每 48 次观测一次),其中窗口回顾前30 天以分解和检测它们。

(注我会标记tsibbleanomalize,但我没有代表来制作这些标签)

方法 2 应该按预期工作吗?错误消息与需要至少两个季节性期间来估计的stl()相关。例如,每日数据至少需要 14 个观测值才能运行stl()。增加窗口大小.size = 7 * 3工作正常。

my_decomp <- function(...) {
data <- tibble(...)
anomalize::decompose_twitter(data, count)
}
library(dplyr)
library(anomalize)
tidyverse_cran_downloads %>%
group_by(package) %>% 
tidyr::nest() %>% 
mutate(diag = purrr::map(data, ~ tsibble::pslide_dfr(., my_decomp, .size = 7 * 3)))
#> # A tibble: 15 x 3
#>    package   data               diag                
#>    <chr>     <list>             <list>              
#>  1 tidyr     <tibble [425 × 2]> <tibble [8,506 × 5]>
#>  2 lubridate <tibble [425 × 2]> <tibble [8,506 × 5]>
#>  3 dplyr     <tibble [425 × 2]> <tibble [8,506 × 5]>
#>  4 broom     <tibble [425 × 2]> <tibble [8,506 × 5]>
#>  5 tidyquant <tibble [425 × 2]> <tibble [8,506 × 5]>
#>  6 tidytext  <tibble [425 × 2]> <tibble [8,506 × 5]>
#>  7 ggplot2   <tibble [425 × 2]> <tibble [8,506 × 5]>
#>  8 purrr     <tibble [425 × 2]> <tibble [8,506 × 5]>
#>  9 glue      <tibble [425 × 2]> <tibble [8,506 × 5]>
#> 10 stringr   <tibble [425 × 2]> <tibble [8,506 × 5]>
#> 11 forcats   <tibble [425 × 2]> <tibble [8,506 × 5]>
#> 12 knitr     <tibble [425 × 2]> <tibble [8,506 × 5]>
#> 13 readr     <tibble [425 × 2]> <tibble [8,506 × 5]>
#> 14 tibble    <tibble [425 × 2]> <tibble [8,506 × 5]>
#> 15 tidyverse <tibble [425 × 2]> <tibble [8,506 × 5]>

最新更新