现在被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
函数有两个参数,data
和target
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. Call
rlang::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 天以分解和检测它们。
(注我会标记tsibble
和anomalize
,但我没有代表来制作这些标签)
方法 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]>