Pandas通过Zscore

时间:2017-07-21 17:23:17

标签: python pandas

我有一个带有列的数据框" group"可以有50个不同的值和一个列"值"这是数字。

一个例子可能是:

pd.DataFrame({'group':['a','b','c','a','a','b','a','c','c'],'value':[2,123,4,2.3,2.5,127,128,4,0.003]})

group   value
0   a   2.000
1   b   123.000
2   c   4.000
3   a   2.300
4   a   2.500
5   b   127.000
6   a   128.000
7   c   4.000
8   c   0.003

我想从数据框中删除其组的异常值,例如abs(zscore)> 3或类似的东西。在示例中,值a,128将被删除,因为它对于组a是异常的,并且值c,0.003也将被删除。 123和127是正常的,因为他们的小组是" b"。

输出应该是(带有z分数列):

group   value
0   a   2.0
1   b   123.0
2   c   4.0
3   a   2.3
4   a   2.5
5   b   127.0
6   c   4.0

这样做的有效方法是什么?

谢谢!

2 个答案:

答案 0 :(得分:4)

为z得分创建一个列,按特定组分组:

df['z_score'] = df.groupby('group')['value'].apply(lambda x: (x - x.mean())/x.std())

根据您的阈值过滤df:

df[abs(df['z_score']) > 3]

答案 1 :(得分:0)

这是每组中的绝对z分数

df.groupby('group').value.transform(lambda x: (x - x.mean()) / x.std()).abs()

0    0.504239
1    0.707107
2    0.577350
3    0.499467
4    0.496286
5    0.707107
6    1.499992
7    0.577350
8    1.154701
Name: value, dtype: float64

不幸的是,数据集非常小,以至于128比你想象的更重要。它的z得分只有1.5。

我建议计算数据点的z分数相对于其他所有的统计时刻。

这是一个能够做到这一点的功能。请注意,我需要在组中至少有4个点才能执行此操作。如果组的长度小于4,则我为整个组返回0。

def _zscore(x):
    if len(x) > 3:
        v = x.values

        m = (v.sum() - v) / (v.size - 1)

        vm = v - m[:, None]
        np.fill_diagonal(vm, 0)

        s = ((vm ** 2).sum(1) / (v.size - 2)) ** .5

        return (v - m) / s
    else:
        return np.zeros_like(x)

现在,如果我们groupbytransform

df.groupby('group').value.transform(_zscore)

0     -0.582866
1      0.000000
2      0.000000
3     -0.576658
4     -0.572532
5      0.000000
6    499.613605
7      0.000000
8      0.000000
Name: value, dtype: float64

我们可以清楚地看到128得到_zscore 499。我们可以从一个简单的假设检验中得出结论,128不太可能来自与该组中其他数据相同的分布。

我们可以过滤它:

df[df.groupby('group').value.transform(_zscore) <= 3]

  group    value
0     a    2.000
1     b  123.000
2     c    4.000
3     a    2.300
4     a    2.500
5     b  127.000
7     c    4.000
8     c    0.003