我有一个关于计算机程序日常使用的时间序列数据,这里是一个例子
- 2017-11-10: 0
- 2017-11-09: 14
- 2017-11-08: 0
- 2017-11-07: 6
- 2017-11-06: 102
- 2017-11-05: 0
- 2017-11-04: 0
如您所见,11-06 在 102 处有一个峰值。由于我们收集此数据的方式,我们知道数据可能是错误的,并且根据其他值我们确信 102 是不正确的。
所以我们需要清理这些脏值。
有没有数学方法可以做到这一点?有python库来帮助我们吗?
我有一个关于计算机程序日常使用的时间序列数据,这里是一个例子
如您所见,11-06 在 102 处有一个峰值。由于我们收集此数据的方式,我们知道数据可能是错误的,并且根据其他值我们确信 102 是不正确的。
所以我们需要清理这些脏值。
有没有数学方法可以做到这一点?有python库来帮助我们吗?
我认为你有几个选择:
x = [e for e in x if e < 100]可以做到这一点。否则,您可以采用聚类方法。在这里,我相信您的第一个镜头应该是 k-means 聚类。这非常容易构建和解释。请参阅下面的代码。
x = [0,14,0,6,102,0,0]
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=2).fit(np.array(x).reshape(-1, 1))
#First cluster:
np.array(x)[np.where(kmeans.labels_ == 0)]
#Second cluster (outliers):
np.array(x)[np.where(kmeans.labels_ == 1)]
众所周知,K-means 对异常值很敏感,因此您尝试过的更强大的方法(例如 MeanShift)是 k-means 的一个很好的竞争对手。我会同时运行两者,并坚持对我更有意义的结果。
希望这可以帮助!
一种解决方案是使用mean并variance检测时间序列中的异常值。例如:
>> data=np.array([0,0,102,6,0,14,0])
>> c = 1
>> abs(data - np.mean(data)) < c * np.std(data)
Output: array([ True, True, False, True, True, True, True], dtype=bool)
>> clean_data= data[abs(data - np.mean(data)) < c * np.std(data)]
Output: array([ 0, 0, 6, 0, 14, 0])
c你可以根据你的要求玩。
此外,您可以分别对时间序列的每个部分(例如每 30 天)使用此方法,而不是使用所有数据的均值和方差。因为在不同的时间间隔内可能会有不同的行为。
这是我正在使用的:
import numpy as np
from sklearn.cluster import MeanShift, estimate_bandwidth
x = [0,14,0,6,102,0,0]
X = list(zip(x,np.zeros(len(x))))
bandwidth = estimate_bandwidth(X, quantile=0.2)
ms = MeanShift(bandwidth=bandwidth, bin_seeding=True)
ms.fit(X)
labels = ms.labels_
cluster_centers = ms.cluster_centers_
labels_unique = np.unique(labels)
n_clusters_ = len(labels_unique)
X = np.array(X)
for k in range(n_clusters_):
my_members = labels == k
print(k, X[my_members, 0])
来源:http ://scikit-learn.org/stable/auto_examples/cluster/plot_mean_shift.html
我会使用四分位数范围(),其中异常值是大于,并且值小于, 在哪里和分别是第一和第三四分位数。这是一个很好的例子。