从以下摘要中可以看出,9月1日(1542677)的计数低于每月的平均数。
from StringIO import StringIO
myst="""01/01/2016 8781262
01/02/2016 8958598
01/03/2016 8787628
01/04/2016 9770861
01/05/2016 8409410
01/06/2016 8924784
01/07/2016 8597500
01/08/2016 6436862
01/09/2016 1542677
"""
u_cols=['month', 'count']
myf = StringIO(myst)
import pandas as pd
df = pd.read_csv(StringIO(myst), sep='\t', names = u_cols)
是否有一个数学公式可以定义这种“低于或过高”(模糊)概念?
如果我定义限制(例如9或10%),这很容易。但是我希望脚本能够为我决定并返回值,如果最低和最后一个最低值之间的差异大于总体5%。在这种情况下,应该返回9月份的计数。
答案 0 :(得分:3)
过滤异常值的一种非常常见的方法是使用标准偏差。在这种情况下,我们将计算zscore
,它将快速确定每个观测值与平均值相差多少标准偏差。然后我们可以过滤那些大于2个标准差的观测值。对于正态分布的随机变量,这应该在大约5%的时间内发生。
定义zscore函数
def zscore(s):
return (s - np.mean(s)) / np.std(s)
将其应用于count
列
zscore(df['count'])
0 0.414005
1 0.488906
2 0.416694
3 0.831981
4 0.256946
5 0.474624
6 0.336390
7 -0.576197
8 -2.643349
Name: count, dtype: float64
请注意,9月份的观察结果是2.6标准偏差。
使用abs
和gt
来识别异常值
zscore(df['count']).abs().gt(2)
0 False
1 False
2 False
3 False
4 False
5 False
6 False
7 False
8 True
Name: count, dtype: bool
再次,九月回归正确。
将所有内容组合在一起以过滤原始数据框
df[zscore(df['count']).abs().gt(2)]
以其他方式过滤
df[zscore(df['count']).abs().le(2)]
答案 1 :(得分:3)
首先,"方式低于或高于"你提到的概念被称为Outlier,并引用维基百科(不是最佳来源),
对于什么构成异常值没有严格的数学定义;确定观察是否是异常值最终是一种主观行为。
但另一方面:
一般而言,如果人口分布的性质是先验已知的,则可以测试异常值的数量是否与预期的偏差显着。
因此,在我看来,这归结为这个问题,是否有可能对数据的性质做出假设,以便能够自动化这些决定。
STRAIGHTFORWARD方法
如果您有幸拥有相对较大的样本量,并且您的不同样本没有相关性,则可以应用central limit theorem,其中指出您的值将遵循正态分布(有关与python相关的说明,请参阅this。)
在此上下文中,您可以快速获得给定数据集的平均值和标准差。通过将the corresponding function(使用这两个参数)应用于每个给定值,您可以计算其属于"群集的概率" (有关可能的python解决方案,请参阅此stackoverflow post。)
然后你做必须设置下限,因为只有当一个点与平均值无限远时,这个分布才会返回0%的概率。但好处是(如果假设是真的)这个界限将很好地适应每个不同的数据集,因为它具有指数,标准化的性质。此界限通常以 Sigma unities表示,并广泛用于科学和统计学。事实上,2013年物理学诺贝尔奖,致力于发现希格斯玻色子,在达到5-sigma范围后被授予,引用链接:
高能物理学需要更低的p值来宣布证据或发现。 "粒子证据的阈值,"对应于p = 0.003,以及"发现的标准"是p = 0.0000003。
替代方案
如果您无法对数据的外观做出如此简单的假设,您可以随时让程序推理。这种方法是大多数机器学习算法的核心功能,如果正确调整,它可以很好地适应强相关甚至偏斜的数据。如果这就是你所需要的,那么Python有很多很好的库,甚至可以放在一个小脚本中(我最熟悉的是来自谷歌的tensorflow。)
在这种情况下,我会考虑两种不同的方法,这取决于您的数据如何:
监督学习:如果你有一个训练集,它会说明哪些样本属于哪些样本,哪些样本不属于哪些(称为标记 ),有像support vector machine这样的算法虽然很轻,但可以很好地适应高度非线性的边界。
无监督学习:这可能是我首先尝试的:当你只是拥有未标记的数据集时。 "直截了当的方法"我之前提到过的是异常检测器的最简单的情况,因此可以进行高度调整和定制,以便在kernel trick的同时考虑甚至无限多维度的相关性。为了理解基于ML的异常探测器的动机和方法,我建议在这件事上看看Andrew Ng的videos。
我希望它有所帮助! 干杯
答案 2 :(得分:2)
过滤异常值的一种方法是四分位数范围(IQR,wikipedia),这是75%(Q3)和25%四分位数(Q1)之间的差异。
如果数据低于Q1-k * IQR,则定义异常值。高于Q3 + k * IQR。
您可以根据您的领域知识选择常数k(常见的选择是1.5)。
根据数据,pandas中的过滤器可能如下所示:
iqr_filter = pd.DataFrame(df["count"].quantile([0.25, 0.75])).T
iqr_filter["iqr"] = iqr_filter[0.75]-iqr_filter[0.25]
iqr_filter["lo"] = iqr_filter[0.25] - 1.5*iqr_filter["iqr"]
iqr_filter["up"] = iqr_filter[0.75] + 1.5*iqr_filter["iqr"]
df_filtered = df.loc[(df["count"] > iqr_filter["lo"][0]) & (df["count"] < iqr_filter["up"][0]), :]