Python 通过箱线图去除异常值以计算序列/数据帧的平均值?
我试图计算数据帧中没有异常值的每列(系列)的平均值。我使用seaborn的箱线图完成此任务:Python 通过箱线图去除异常值以计算序列/数据帧的平均值?,python,dataframe,seaborn,boxplot,outliers,Python,Dataframe,Seaborn,Boxplot,Outliers,我试图计算数据帧中没有异常值的每列(系列)的平均值。我使用seaborn的箱线图完成此任务: plt.figure(figsize=(50, 10),dpi=200) sns.boxplot(x='Unit_Code',y='Leadtime',hue='Has_Weekend?',data=df ,palette='winter') plt.xticks(rotation=90); 这就是我得到的: 我真的很想得到没有异常值的每个单位(x轴)的平均值。这背后的原因是,如果我错了,请纠正我,
plt.figure(figsize=(50, 10),dpi=200)
sns.boxplot(x='Unit_Code',y='Leadtime',hue='Has_Weekend?',data=df ,palette='winter')
plt.xticks(rotation=90);
这就是我得到的:
我真的很想得到没有异常值的每个单位(x轴)的平均值。这背后的原因是,如果我错了,请纠正我,我希望得到这个特性的平均值,没有异常值,如下所示
他们把它弄歪了
谢谢 可以通过多种方式删除异常值。此示例使用z-score方法删除异常值 一旦去除了异常值,计算平均值就非常简单,只需在数据帧的每一列上调用
.mean()
函数,或使用.descripe()
函数即可
在不涉及太多细节的情况下,这是一种确定值与平均值之间的标准偏差的方法。其实很简单,就是每个值减去平均值,除以数据集的标准偏差。一般来说,对于接近平均值的正态分布数据,z分数为3可以用作过滤器,如下例所示
计算z分数的一种简单方法是使用scipy.stats
模块,并使用
对于这个例子,我合成了一个数据集,可以在这个答案的底部找到。此外,由于我比seaborn更熟悉plotly,所以我选择使用plotly进行绘图
让我们继续吧
之前:
此示例代码与问题无关,只是绘制代码
l = {'title': 'Boxplot - With Outliers'}
t = []
t.append({'y': df['AZGD01'], 'type': 'box', 'name': 'AZGD01'})
t.append({'y': df['AZPH01'], 'type': 'box', 'name': 'AZPH01'})
t.append({'y': df['AZPV01'], 'type': 'box', 'name': 'AZPV01'})
iplot({'data': t, 'layout': l})
输出:
使用z分数进行筛选:
这显示了如何在数据帧的每列上计算z分数的示例,其中过滤的值存储到第二个数据帧
步骤:
- 迭代每个列
- 使用
scipy.stats.zscore()函数计算z分数
- 筛选以仅保留z分数大于3的记录
- 存储到新的数据帧中
from scipy import stats
df_z = pd.DataFrame()
for c in df:
# Calculate z-score for each column.
z = stats.zscore(df[c])
# Filter to keep records with z-scores < 3.
df_z[f'{c}_z'] = df.loc[z<3, c]
输出:
样本数据集构造:
下面是更无关的代码,用于构建示例数据集
import numpy as np
import pandas as pd
from plotly.offline import iplot
from sklearn.preprocessing import MinMaxScaler
mms = MinMaxScaler((0, 100))
np.random.seed(7)
vals1 = mms.fit_transform(np.random.randn(1000).reshape(-1, 1)).ravel()
np.random.seed(3)
vals2 = mms.fit_transform(np.random.randn(1000).reshape(-1, 1)).ravel()
np.random.seed(73)
vals3 = mms.fit_transform(np.random.randn(1000).reshape(-1, 1)).ravel()
outl1 = np.arange(150, 200, 10)
outl2 = np.arange(200, 250, 10)
outl3 = np.arange(250, 300, 10)
data1 = np.concatenate([vals1, outl1])
data2 = np.concatenate([vals2, outl2])
data3 = np.concatenate([vals3, outl3])
df = pd.DataFrame({'AZGD01': data1, 'AZPH01': data2, 'AZPV01': data3})
有趣的问题。(无论如何对我来说)。我只是给你一个答案,并试图尽可能多地解释,这使它简单明了。帮帮忙这帮你上车!嘿,谢谢你的帮助!试图运行代码,但在计算z_分数的代码块中出现以下错误:“值的长度与索引的长度不匹配”。同样奇怪的是,剔除异常值后,平均值似乎在0左右。这是正确的吗?我想知道为什么这不是seaborn的一个选项,因为我认为有人会很容易地得到一个没有异常值的平均值。再次感谢!更新。我为“after”示例中的零均值表示歉意,感谢您指出这一点。愚蠢的我绘制了z分数,而不是通过z分数过滤的数据。这一点已得到纠正。请告诉我你进展如何。更改:1)过滤行已更新为:
df_z[f'{c}u z']=df.loc[zYes,它现在可以工作了。谢谢!所以您只需通过z_分数过滤掉,我自己也可以使用它。我认为Seaborn的箱线图是基于四分位数的计算和IQR(75%-25%)之上的他们计算一个下限和一个上限,并标记这些异常值,如果它们延伸到胡须之上/之下。根据你的经验,z_分数比他们用来计算异常值的分数更好吗?顺便说一句,我从你的代码中学到了很多,所以谢谢你。非常感谢!非常好,很高兴它起作用。请你点击e在答案中打勾表示您已接受?(标准SO实践)。有很多方法可以跟踪异常值-但是,是的,z-score通常是我的第一站,因为它可以查看标准偏差。此外,您可以绘制数据的直方图并直观地确定异常值边界…任何真正符合目的的方法。关于代码,谢谢。有更有效的方法来编写其中一些,但选择了t他是最具可读性的选择。干杯,伙计。干杯,伙计,祝你一切顺利!
import numpy as np
import pandas as pd
from plotly.offline import iplot
from sklearn.preprocessing import MinMaxScaler
mms = MinMaxScaler((0, 100))
np.random.seed(7)
vals1 = mms.fit_transform(np.random.randn(1000).reshape(-1, 1)).ravel()
np.random.seed(3)
vals2 = mms.fit_transform(np.random.randn(1000).reshape(-1, 1)).ravel()
np.random.seed(73)
vals3 = mms.fit_transform(np.random.randn(1000).reshape(-1, 1)).ravel()
outl1 = np.arange(150, 200, 10)
outl2 = np.arange(200, 250, 10)
outl3 = np.arange(250, 300, 10)
data1 = np.concatenate([vals1, outl1])
data2 = np.concatenate([vals2, outl2])
data3 = np.concatenate([vals3, outl3])
df = pd.DataFrame({'AZGD01': data1, 'AZPH01': data2, 'AZPV01': data3})