通过groupby删除大纲轮廓熊猫?

时间:2019-06-11 09:53:21

标签: python pandas pandas-groupby

我有一个简单的功能,该功能可以删除大纲器并返回一个新的DataFrame:

def remove_outliner(df):
   df.index = df.time
   df['median']= df['price'].rolling(15).median()
   df['std'] = df['price'].rolling(15).std()
   df["std+"] = df['median']+3*df['std']
   df["std-"] = df['median']-3*df['std']
   #filter setup
   df2 = df[(df.price <= df['median']+3*df['std']) &
            (df.price >= df['median']-3*df['std'])]
   return df2

有没有一种使用groupby来应用这种功能的方法?像这样(伪代码):

df.groupby(["product"]).filter(remove_outliner).concat_groups()

我幼稚的方法是遍历各个组。将它们保存在列表中,然后应用pd.concat。但我希望有一种更优雅的方法。非常感谢您提供任何提示!

PS:示例输入

                               product price 
          2014-08-25 01:00:00  A       1.2
          2014-08-25 02:00:00  B       7.2
          2014-08-25 03:00:00  A       1.2
          2014-08-25 04:00:00  B       7.2
          2014-08-25 04:00:00  A       1.2
          2014-08-25 05:00:00  A       99.2
          2014-08-25 06:00:00  A       1.2
          2014-08-25 06:00:00  B       7.2
          2014-08-25 21:00:00  A       1.2
          2014-08-25 22:00:00  B       88.2

预期结果

                               product price 
          2014-08-25 01:00:00  A       1.2
          2014-08-25 02:00:00  B       7.2
          2014-08-25 03:00:00  A       1.2
          2014-08-25 04:00:00  B       7.2
          2014-08-25 04:00:00  A       1.2
          2014-08-25 06:00:00  A       1.2
          2014-08-25 06:00:00  B       7.2
          2014-08-25 21:00:00  A       1.2

如果第一行消失了,那就好了。 remove_outliner函数添加了一些列,但可以将其删除。由于不同的产品可能具有不同的价格范围,因此我不能仅对价格应用过滤器,而需要与小组合作。

2 个答案:

答案 0 :(得分:2)

所以我尝试了一下修改您的功能(您可能不想在数据框中使用medianstd

def remove_outliner(df):
    roll_median= df['price'].rolling(15).median()
    roll_std = df['price'].rolling(15).std()

    #filter setup
    df2 = df[(df.price.le(roll_median + 3*roll_std) &
            (df.price.ge(roll_median - 3*roll_std)]

    return df2

# set_index here, not inside the function:
df.set_index('time').groupby('product', group_keys=False).apply(remove_outliner)

答案 1 :(得分:1)

尝试一下:

df_wo_outliers = df[~((df < (Q1 - 1.5 * IQR)) |(df > (Q3 + 1.5 * IQR))).any(axis=1)]

也有一篇不错的文章谈论detecting and treating outliers

希望有帮助。