首页 > 解决方案 > 如何在 r 中检测面板时间序列数据中的大跳跃和快速反转

问题描述

我有一个时间序列面板数据集,其结构如下:

df <- data.frame(
  year = c(2012L, 2013L, 2014L, 2012L, 2013L, 2014L),
  id = c(1L, 1L, 1L, 2L, 2L, 2L),
  c = c(11L, 13L, 13L, 16L, 15L, 15L)
)

#>   year id  c
#> 1 2012  1 11
#> 2 2013  1 26
#> 3 2014  1 13
#> 4 2012  2 16
#> 5 2013  2 15
#> 6 2014  2 19

在每个 id 中,我想在 c 列中发现巨大的异常变化和随后的逆转(即,变量在一个时期内翻倍或缩小 2 倍,类似于样本数据集中的第 2 行,并在下一个时期迅速恢复正常)

我想定义反转为正常的方式是确定是否在更改之前返回该值(在指定范围内),该值返回到例如原始值的 +/- 25%)。

我希望能够指定寻找逆转的时期(例如 3 个时期/年)

总而言之,我希望能够在一个时期内检测到两倍或更多的巨大跳跃或收缩,并在指定时期(3 年)内迅速恢复正常(原始值的 25%)。

我的最终目标是确定数据库中是否存在一些可能的错误,并选择所有有此类错误的 id。

标签: rdplyrtime-seriespanelanomaly-detection

解决方案


您可以使用该lag功能向后看。它尊重 a 中指定的组group_by

lag(or )的默认值lead是移动到当前行之前或之后的直接行,但是如果您提供一个整数作为第二个参数(在本例中为 2),它将进一步检查值。

lag并在没有可用行时lead返回NA,因为我们已经到达(分组)数据框的边界,所以在这里我coalesce用来强制那些NAs 进入FALSE. 您也可以使用原始函数的默认参数,但这似乎更容易。

df <- data.frame(
  year = c(2012L, 2013L, 2014L, 2012L, 2013L, 2014L),
  id = c(1L, 1L, 1L, 2L, 2L, 2L),
  c = c(11L, 26L, 13L, 16L, 15L, 15L)
)

df %>%
  group_by(id) %>%
  mutate(flag = (lag(c) >= 2*lag(c, 2) | lag(c) <= 0.5*lag(c, 2)) 
                & abs(1 - c/(lag(c, 2))) < 0.25) %>%
  mutate(flag = coalesce(flag, FALSE))

# A tibble: 6 x 4
# Groups:   id [2]
   year    id     c flag 
  <int> <int> <int> <lgl>
1  2012     1    11 FALSE
2  2013     1    26 FALSE
3  2014     1    13 TRUE 
4  2012     2    16 FALSE
5  2013     2    15 FALSE
6  2014     2    15 FALSE

推荐阅读