问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

数据清洗中异常值(离群值)的判别和处理方法

创作时间:
作者:
@小白创作中心

数据清洗中异常值(离群值)的判别和处理方法

引用
CSDN
1.
https://blog.csdn.net/dhr223/article/details/107086239

在数据清洗过程中,异常值(离群值)的处理是一个关键环节。异常值可能会影响数据分析和建模的准确性,因此需要采用合适的方法进行识别和处理。本文将介绍几种常见的异常值识别方法,并探讨不同的处理策略。

异常值甄别

1. 3σ准则

如果样本是正态分布或近似正态分布,可以考虑使用3σ方法。该方法认为99%以上的数据集中在均值上下3个标准差的范围内。具体来说,数值分布在(μ-3σ,μ+3σ)中的概率为99.73%,超过这个范围的极大或极小值,那就是异常值了。

以下是使用Python进行3σ准则异常值识别的示例代码:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# 导入试验数据
df = pd.read_csv(r'F:\数据分析项目\游戏数据分析\野蛮时代数据分析\tap_fun_train.csv')

# 从中取出100个数,先做一个直方图看看分布状态
df = df[df['wood_add_value']>0].head(100)
sns.distplot(df['wood_add_value'])
plt.show()

  • 计算均值:

    a = df['wood_add_value'].mean()
    

    均值为781190.89。

  • 然后计算标准差:

    b = df['wood_add_value'].std()
    

    标准差为2196896.04。

  • 计算排查范围:

    (a-3*b, a+3*b)
    

    得到结果:(-5809497.23,7371879.01)。

  • 使用上述区间作为条件进行筛选:

    df[(df['wood_add_value']>7371879)|(df['wood_add_value']<-5809497)]['wood_add_value']
    

    得出异常值为:15968730、9669530、8668980。

2. 使用箱型图

箱形图(Box-plot)又称为盒须图、盒式图或箱线图,是一种用作显示一组数据分散情况资料的统计图。因形状如箱子而得名。

还是以wood_add_value为例,因为由于这个数值受要塞等级bd_stronghold_level的影响非常大,所以做了不同要塞等级的箱型图分布。

使用seaborn绘图:

df2 = df[df['wood_add_value']>0] # 没有任何数值记录说明没玩游戏,所以没有分析的意义
plt.figure(figsize = (18,8))
sns.boxplot(x = df2['bd_stronghold_level'],y = df2['wood_add_value'])
plt.show()

随便选其中的一个等级,比如就15级吧,说明箱型图的意义:

df3 = df2[df2['bd_stronghold_level']==15]
plt.figure(figsize = (8,6))
sns.boxplot(x = df3['bd_stronghold_level'],y = df3['wood_add_value'],width = 0.2)
plt.show()

非异常值的范围都在上限和下限之间,超出上限和下限的就定位为异常值。

使用DataFrame自带的绘图工具:

这种方法不仅可以绘图,还可以方便的输出具体的异常值是哪些。由于只有DataFrame格式可以使用,所以数据不能是Series格式

df4 = df3[['bd_stronghold_level','wood_add_value']]
plt.figure(figsize = (8,6))
outlier = df4.boxplot(return_type = 'dict')
x = outlier['fliers'][1].get_xdata() # 这个get_xdata我不太清楚啥意思,可能是表示哪一个column的异常值。
y = outlier['fliers'][1].get_ydata() # 具体的异常值是什么
y1 = list(y)
print(y1)

最后得出15级要塞的wood_add_value的异常值是这些:
[327291568.0, 539691776.0, 765436570.0, 498063299.0]。实际处理中,除了箱型图进行客观的排查,还可以加入主观判断,对于超出范围的值,如果超出范围不是非常大,可以看做正常值。

异常值处理

异常值已经被找出来了,那么怎么处理呢?实际处理中没有固定的方法,要根据分析的目的来确定。

  • 删除。如果想找出一般的规律,而且异常值也不太多,可以考虑删除。因为异常值可能会影响结论。很多节目中计算选手最后得分往往去掉一个最高分,去掉一个最低分,可能就是这个道理。比如我们现在研究就是要塞等级bd_stronghold_level为15级的玩家的道具消耗特征,这时候异常值显然会拉高整体的水平,影响判断,所以可以考虑删除,我们要了解大多数玩家。

  • 放任不管。因为异常值代表的也是真实发生的事件,背后是具体的行为。有些值即使异常,也不会影响模型。比如我们研究wood_add_value和pay_price的关系,想做回归分析,也就是看道具消耗和充值金额的因果关系。我们能够很清楚的看到刚才找到的wood_add_value的4个异常值,虽然他们游离于群体之外,但是在对pay_price进行拟合的时候并没有使模型造成太大偏差。所以这种异常值对我们的模型来说很合理。

plt.figure(figsize = (12,6))
plt.subplot(1,2,1)
sns.scatterplot(x='wood_add_value', y='pay_price',data = df3)
plt.subplot(1,2,2)
sns.regplot(x='wood_add_value', y='pay_price',data = df3)
plt.show()
  • 视为缺失值进行填充。因为贸然删除数据可能会损失信息,而如果放任不管可能又影响我们的模型,所以可以考虑用均值、临近值进行填充。如下面这个例子,依旧是用wood_add_value对pay_price进行回归预测(样本不一样了)。从图上看绿圈和红圈那两个点,有可能会影响回归线的方向(蓝色线是python拟合的,绿线和红线是我自己画的)。所以这种异常值还是处理掉比较好。
sns.scatterplot(x='wood_add_value', y='pay_price',data = df2)
plt.show()

异常值到底该怎么处理,我也在学习。在用户分层的时候,发现异常值代表了一些极端的高价值用户,ARPU可能是平均水平的几千倍,可能也是需要把极端值单独提取出来,对用户进行实时的“监控”,这类用户流失造成的损失实在太大了。还有就是异常值的甄别和处理可能还有很多其他方法,目前我也还没学,暂且如此吧,且用且学且记。

本文原文来自CSDN

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号