如何查找低于(或高于)平均值的值

时间:2016-10-10 04:09:15

标签: python pandas dataframe

从以下摘要中可以看出,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月份的计数。

3 个答案:

答案 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标准偏差。

使用absgt来识别异常值

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)]

enter image description here

以其他方式过滤

df[zscore(df['count']).abs().le(2)]

enter image description here

答案 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]), :]