我有一个简单的函数,可以删除outliners并返回一个新的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函数添加了一些列,但这些列可以删除。因为不同的产品可能有不同的价格等级,所以我不能只对价格应用过滤器,而需要与组一起工作。
发布于 2019-06-11 18:20:41
所以我试着稍微修改一下你的函数(你可能不想在你的数据帧中有median和std ):
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)发布于 2019-06-11 18:04:52
试试这个:
df_wo_outliers = df[~((df < (Q1 - 1.5 * IQR)) |(df > (Q3 + 1.5 * IQR))).any(axis=1)]还有一篇很好的文章谈到了detecting and treating outliers。
希望能有所帮助。
https://stackoverflow.com/questions/56541073
复制相似问题