(此答案回答了“ 检测未决事件”中的一个重复问题(现已关闭),该问题以图形形式显示了一些数据。)
离群值检测取决于数据的性质以及您愿意对它们假设的内容。 通用方法依赖可靠的统计信息。这种方法的精神在于以不受任何异常值影响的方式表征大量数据,然后指向不适合该表征的任何单个值。
由于这是一个时间序列,因此增加了持续不断地需要(重新)检测异常值的复杂性。如果在系列展开时要这样做,那么我们只能使用较旧的数据进行检测,而不能使用将来的数据!而且,作为对许多重复测试的保护,我们希望使用一种假阳性率非常低的方法。
这些考虑因素建议对数据进行简单,健壮的移动窗口离群值测试。有很多可能性,但是一种简单,容易理解和容易实现的方法是基于运行中的MAD:相对于中位数的中位数绝对偏差。这是一种非常稳健的衡量数据变化的方法,类似于标准偏差。外围峰将是几个MAD或大于中位数。
R
X = (1 ,2 ,... ,Ñ )n = 1150ÿ
# Parameters to tune to the circumstances:
window <- 30
threshold <- 5
# An upper threshold ("ut") calculation based on the MAD:
library(zoo) # rollapply()
ut <- function(x) {m = median(x); median(x) + threshold * median(abs(x - m))}
z <- rollapply(zoo(y), window, ut, align="right")
z <- c(rep(z[1], window-1), z) # Use z[1] throughout the initial period
outliers <- y > z
# Graph the data, show the ut() cutoffs, and mark the outliers:
plot(x, y, type="l", lwd=2, col="#E00000", ylim=c(0, 20000))
lines(x, z, col="Gray")
points(x[outliers], y[outliers], pch=19)
应用于问题所示的红色曲线之类的数据集,它会产生以下结果:
数据显示为红色,中位数+ 5 * MAD阈值的30天窗口显示为灰色,而异常值(仅是灰色曲线上方的那些数据值)显示为黑色。
(只能从初始窗口的末尾开始计算阈值。对于该初始窗口内的所有数据,将使用第一个阈值:这就是为什么灰色曲线在x = 0和x = 30之间平坦的原因。)
更改参数的影响是:(a)增加的值window
会趋于平滑灰色曲线,(b)增大threshold
会增加灰色曲线。知道这一点,就可以获取数据的初始片段,并快速确定参数值,以最佳地将外围峰与其余数据区分开。将这些参数值应用于检查其余数据。如果图表显示该方法随着时间的推移而恶化,则意味着数据的性质正在改变,并且可能需要重新调整参数。
请注意,该方法对数据的假设很少:它们不必以正态分布;他们不需要表现出任何周期性;他们甚至不必非负数。所有这假设是,数据相当类似的方式随着时间的推移表现和外围峰值明显低于其余数据更高。
如果有人想尝试(或将其他解决方案与此处提供的解决方案进行比较),这是我用来生成问题中所示数据的代码。
n.length <- 1150
cycle.a <- 11
cycle.b <- 365/12
amp.a <- 800
amp.b <- 8000
set.seed(17)
x <- 1:n.length
baseline <- (1/2) * amp.a * (1 + sin(x * 2*pi / cycle.a)) * rgamma(n.length, 40, scale=1/40)
peaks <- rbinom(n.length, 1, exp(2*(-1 + sin(((1 + x/2)^(1/5) / (1 + n.length/2)^(1/5))*x * 2*pi / cycle.b))*cycle.b))
y <- peaks * rgamma(n.length, 20, scale=amp.b/20) + baseline