【问题标题】:Outlier detection based on the moving mean in PythonPython中基于移动均值的异常值检测
【发布时间】:2020-10-22 20:12:20
【问题描述】:

我正在尝试将算法从 MATLAB 转换为 Python。该算法适用于大型数据集,需要应用异常值检测和消除技术。

在 MATLAB 代码中,我使用的异常值删除技术是movmedian

   Outlier_T=isoutlier(Data_raw.Temperatura,'movmedian',3);
   Data_raw(find(Outlier_T),:)=[]

通过在三值移动窗口的中心找到不成比例的值检测具有滚动中值的异常值。因此,如果我在第 3 行有一个 40 的列“Temperatura”,则会检测到它并删除整行。

         Temperatura     Date       
    1        24.72        2.3        
    2        25.76        4.6        
    3        40           7.0        
    4        25.31        9.3        
    5        26.21       15.6
    6        26.59       17.9        
   ...        ...         ...

据我了解,这是通过pandas.DataFrame.rolling 实现的。我看过几篇文章举例说明了它的使用,但我没有设法让它与我的代码一起工作:

尝试 A:

Dataframe.rolling(df["t_new"]))

尝试 B:

df-df.rolling(3).median().abs()>200

#基于@Ami Tavory 的answer

我在这里遗漏了什么明显的东西吗?这样做的正确方法是什么? 感谢您的宝贵时间。

【问题讨论】:

  • 有一个错字。尝试用median替换meadian
  • 对不起,我写了这个,但错字不在代码中
  • 好的。谢谢。在下面发布了一个使用滚动中位数的答案。

标签: python pandas outliers rolling-computation


【解决方案1】:

下面的代码根据阈值删除行。该阈值可以根据需要进行调整。不过不确定它是否复制了 Matlab 代码。

# Import Libraries
import pandas as pd
import numpy as np

# Create DataFrame
df = pd.DataFrame({
    'Temperatura': [24.72, 25.76, 40, 25.31, 26.21, 26.59],
    'Date':[2.3,4.6,7.0,9.3,15.6,17.9]
})

# Set threshold for difference with rolling median
upper_threshold = 1
lower_threshold = -1

# Calculate rolling median
df['rolling_temp'] = df['Temperatura'].rolling(window=3).median()

# Calculate difference
df['diff'] = df['Temperatura'] - df['rolling_temp']

# Flag rows to be dropped as `1`
df['drop_flag'] = np.where((df['diff']>upper_threshold)|(df['diff']<lower_threshold),1,0)

# Drop flagged rows
df = df[df['drop_flag']!=1]
df = df.drop(['rolling_temp', 'rolling_temp', 'diff', 'drop_flag'],axis=1)

输出

print(df)

   Temperatura  Date
0        24.72   2.3
1        25.76   4.6
3        25.31   9.3
4        26.21  15.6
5        26.59  17.9

【讨论】:

  • 感谢您的回答!我遇到了这个错误:文件“home/.../pandas/core/indexes/base.py”,第 4404 行,在 get_value return self._engine.get_value(s, k, tz=getattr(series.dtype) , "tz", 无)) KeyError: 445
  • 您能否发布一个导致错误的示例 DataFrame?我希望上面的代码在答案中使用 DataFrame 在您这边运行得很好?
  • 更新:这行代码似乎产生了错误:在到达它之前,代码正确识别了'40'的异常值,并在drop_flag列中为其分配了一个1 i> df = df[df['drop_flag']!=1]
  • 好的。答案中发布的代码在我的计算机上运行良好。 (1) 您能否确认上述代码是否按原样在您这边运行而没有错误?,(2) 您能否发布错误以及导致错误的DataFrame
  • 我解决了这个问题。您的代码完美运行。谢谢!
【解决方案2】:

Nilesh 的答案非常有效,你也可以迭代他的代码:

upper_threshold = 1
lower_threshold = -1

# Calculate rolling median
df['rolling_temp'] = df['Temp'].rolling(window=3).median()
# all in one line 
df = df.drop(df[(df['Temp']-df['rolling_temp']>upper_threshold)|(df['Temp']- df['rolling_temp']<lower_threshold)].index) 
# if you want to drop the column as well
del df["rolling_temp"]

【讨论】:

  • 感谢您的意见。我无法让 Nilseh 的代码像你一样工作。我用获得的错误编辑了我的原始帖子。知道为什么会发生这种情况吗?
  • 不确定,可能有很多。你能试试我的版本吗?这也可能是索引问题。 df 中的 445 值在哪里?
【解决方案3】:

根据 Nilesh Ingle 的回答,派对迟到了。修改为更通用、更详细(图表!)和百分比阈值,而不是数据的实际值。

# Calculate rolling median
df["Temp_Rolling"] = df["Temp"].rolling(window=3).median()

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
df["Temp_Rolling"] = scaler.fit_transform(df["Temp_Rolling"].values.reshape(-1, 1))

# Calculate difference
df["Temp_Diff"] = df_scaled["Temp"] - df["Temp_Rolling"]

import numpy as np
import matplotlib.pyplot as plt

# Set threshold for difference with rolling median
upper_threshold = 0.4
lower_threshold = -0.4

# Flag rows to be keepped True
df["Temp_Keep_Flag"] = np.where( (df["Temp_Diff"] > upper_threshold) | (df["Temp_Diff"] < lower_threshold), False, True)

# Keep flagged rows
print('dropped rows')
print(df[~df["Temp_Keep_Flag"]].index)
print('Your new graph')
df_result = df[df["Temp_Keep_Flag"].values]
df_result["Temp"].plot()

一旦您对数据清理感到满意

# Satisfied, replace data
df = df[df["Temp_Keep_Flag"].values]
df.drop(columns=["Temp_Rolling", "Temp_Diff", "Temp_Keep_Flag"], inplace=True)
df.plot()

【讨论】:

    猜你喜欢
    • 2014-05-13
    • 1970-01-01
    • 2013-06-11
    • 2020-06-02
    • 2019-09-15
    • 2019-07-24
    • 1970-01-01
    • 2022-10-08
    • 2016-02-28
    相关资源
    最近更新 更多