【问题标题】:Detecting outliers within one column for ranges of rows在一列中检测行范围内的异常值
【发布时间】:2019-12-24 04:15:47
【问题描述】:

在给定的数据框中,我有这两列:

 neighbourhood_group
 price

价格列包含所有neighbourhood_group的所有价格:

    neighbourhood_group price
 0  Brooklyn            149
 1  Manhattan           225
 2  Manhattan           150
 3  Brooklyn            89
 4  Manhattan           80
 5  Manhattan           200
 6  Brooklyn            60
 7  Manhattan           79
 8  Manhattan           79
 9  Manhattan           150

我正在尝试检测每个 neighbourhood_group 的异常值。

到目前为止,我想到的唯一想法是按 neighbourhood_group 按价格分组,检测每个组中的异常值并为需要删除的行创建掩码。

 data.groupby('neighbourhood_group')['price']

我怀疑可能有更简单的解决方案。

【问题讨论】:

  • 在这种情况下,您的值都不是异常值,对吧?

标签: python pandas outliers


【解决方案1】:

我会手动做一点:

假设你的 df 是这个(注意我在底部添加了 2 行)

    neighbourhood_group price
0   Brooklyn    149
1   Manhattan   225
2   Manhattan   150
3   Brooklyn    89
4   Manhattan   80
5   Manhattan   200
6   Brooklyn    60
7   Manhattan   79
8   Manhattan   79
9   Manhattan   150
10  Manhattan   28
11  Manhattan   280

让我们在这里添加 2 列以方便:

df['mean']=df.groupby('neighbourhood_group').transform('mean')
df['std'] = df.groupby('neighbourhood_group')['price'].transform('std')

如果is_outlier,让我们询问真/假

df['is_outlier'] = df.apply(lambda x: x['price']+x['std']<x['mean'] or x['price']-x['std']>x['mean'], axis=1)

结果

    neighbourhood_group price   mean              std   is_outlier
0   Brooklyn            149     99.333333   45.390895   True
1   Manhattan           225     141.222222  82.308532   True
2   Manhattan           150     141.222222  82.308532   False
3   Brooklyn            89      99.333333   45.390895   False
4   Manhattan           80      141.222222  82.308532   False
5   Manhattan           200     141.222222  82.308532   False
6   Brooklyn            60      99.333333   45.390895   False
7   Manhattan           79      141.222222  82.308532   False
8   Manhattan           79      141.222222  82.308532   False
9   Manhattan           150     141.222222  82.308532   False
0   Manhattan           28      141.222222  82.308532   True
1   Manhattan           280     141.222222  82.308532   True

另外:@Willem Van Onsem 请注意,“异常值”的定义通常高于/低于平均值 3 sigma。在你的工作中考虑这一点,你可以定义你与平均值的偏差(我使用 std=1)

【讨论】:

  • 次要备注:在统计中,如果平均值和值之间存在三个或更多标准差,则通常定义为异常值。
  • @Willem Van Onsem。 3 sigma - 正确 - 我会更新我的答案。
  • 感谢您思考问题@adhg。它也有效
【解决方案2】:

我认为使用 groupby 非常有意义。然后我会得到单个组,例如使用 get_group 方法。最后你可以做任何你需要的分析,看看这个例子以防你错过了

Detect and exclude outliers in Pandas data frame

干得好,我也会关注这个问题,因为我也有兴趣

【讨论】:

  • 尊敬的,您没有为 OP 提供任何解决方案。我强烈建议您为该问题提供自己的工作,而不是提供链接。 (我很确定 Gara 之前用谷歌搜索过)
【解决方案3】:

您可以使用Groupby.apply,然后获取所有超出3 * std 范围的值,同时用mean 减去每个值:

m = df.groupby('neighbourhood_group')['price'].apply(lambda x: x.sub(x.mean()).abs() <= (x.std()*3))

df[m]

输出

  neighbourhood_group  price
0            Brooklyn    149
1           Manhattan    225
2           Manhattan    150
3            Brooklyn     89
4           Manhattan     80
5           Manhattan    200
6            Brooklyn     60
7           Manhattan     79
8           Manhattan     79
9           Manhattan    150

注意:在这种情况下,我们会取回所有行,因为没有异常值。

【讨论】:

  • 您的解决方案有问题。仅当它低于平均值 3 标准时,您才定义异常值。如果它高于平均值 3std 怎么办? (你的 m 输出也应该是真/假)
  • @adhg: 这就是abs() 的用武之地。
  • @Willem Van Onsem 好的,我在这里可能错了,但平均值(应该)总是积极的,所以腹肌不能提供太多。不?潜艇可能在这里让我感到困惑。
  • @adhg: 不是mean,而是.abs(),而是x.sub(x.mean())(所以平均值和x之间的差异。
  • 谢谢@Erfan。没错,显示的值的 sn-p 不包含异常值。您的解决方案是最优雅和最有效的,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多