我有一个 pandas 数据框,我想在其中检测单个列上的异常值。请记住,我在数据处理/清理方面没有经验。
你可以在下图中看到我确实有一些异常值,最明显的是 08:00:00 标记上方的那个。
我想要的是检测这些异常值,而不是删除它们,我想将它们修改为它之前的 10 个值的平均值(因此第 11 行的值将更改为第 1 行的平均值-10).
我研究过计算 z 分数并以此为基础寻找异常值,但它似乎关注的是总数据集的标准差,而不仅仅是局部范围。您可以在下面看到我为此编写的代码。
def dfCleaning(df):
df.reset_index(drop=True, inplace=True)
z = np.abs(stats.zscore(df['MW']))
for x in np.where((z > 3) | (z < -3)):
for index in x:
df.loc[index, 'MW'] = df.iloc[max(0, index-11) : max(1,index-1)]['MW'].mean()
return df
因此,如果有一种方法可以根据数据集中的一系列行(可能是焦点行上下 50 行)来检测异常值,如果有人能向我解释一下,我将不胜感激。
这是移除离群值函数的示例。但我建议将您的数据分成多个时间。每天或每周应用删除离群值函数,然后将其连接起来。
def remove_outliers(df_in, col_name):
q1 = df_in[col_name].quantile(0.25)
q3 = df_in[col_name].quantile(0.75)
iqr = q3 -q1
fence_low = q1 -1.5 *iqr
fence_high = q3 +1.5 *iqr
df_out = df_in.loc[(df_in[col_name] > fence_low) & (df_in[col_name] < fence_high)]
return df_out
您可以使用:
def zscore(s, window, thresh=3, return_all=False):
roll = s.rolling(window=window, min_periods=1, center=True)
avg = roll.mean()
std = roll.std(ddof=0)
z = s.sub(avg).div(std)
m = z.between(-thresh, thresh)
if return_all:
return z, avg, std, m
return s.where(m, avg)
df['MW2'] = zscore(df['MW'], window=50)