数据准备<1>:数据质量检查-理论篇

数据行业有一句很经典的话——“垃圾进,垃圾出”(Garbage in, Garbage out, GIGO),意思就是,如果使用的基础数据有问题,那基于这些数据得到的任何产出都是没有价值的。而对于数据分析挖掘而言,只有一份高质量的基础数据,才可能得到正确、有用的结论。本文主要介绍数据质量检查的基本思路和方法,具体包括:从哪些角度检查数据质量问题、发现数据质量问题后又如何处理两方面,并提供基于Python的实现方法。
另外,数据质量检查是数据治理中的一个重要课题,涉及内容广,由于笔者经验水平有限,本文不做涉及,只从分析挖掘中的数据质量检查工作说起。

**数据质量检查是在完成宽表数据开发后进行的,主要包括四个方面:重复值检查、缺失值检查、数据倾斜检查、异常值检查。**

0. 示例数据集说明

数据集:/labcenter/python/dataset.xlsx

#读取数据集
import pandas as pd
dataset = pd.read_excel("/labcenter/python/dataset.xlsx")

#打印数据集
dataset
Out[6]: 
   col1  col2  col3 col4      col5    col6  col7
0   101  38.0    96  aaa  572.0000  0.0017     1
1   102  20.0    13  bbb  174.3333  0.0115     0
2   103  44.0   160  ccc  191.3333  0.0000     1
3   104   NaN   128  aaa  236.0000  0.0000     0
4   105  22.0    10  bbb    0.0000 -0.3000     0
5   106  58.0    16  aaa    0.0000  0.0000     1
6   107  30.0    31  aaa  598.0000  0.0000     0
7   108  25.0    87  aaa   19.6667  0.0000     0
8   109  38.0   221  bbb       NaN  0.0000     1
9   110  35.0   115  ccc  425.6667  0.0094     0

##1. 重复值检查 ###1.1 什么是重复值 重复值的检查首先要明确一点,即重复值的定义。对于一份二维表形式的数据集来说,什么是重复值?可以从**两个层次**进行理解: ① 关键字段出现相同的记录,比如主索引字段出现重复; ② 所有字段出现相同的记录。 第一个层次是否是重复,必须从这份数据的业务含义进行确定,比如在一张表中,从业务上讲,一个用户应该只会有一条记录,那么如果某个用户出现了超过一条的记录,那么这就是重复值。第二个层次,就一定是重复值了。 ###1.2 重复值产生的原因 重复值的产生主要有**两种原因**,一是上游源数据造成的,二是数据准备脚本中的数据关联造成的。从数据准备角度来看,首先要检查数据准备的脚本,判断使用的源表是否有重复记录,同时检查关联语句的正确性和严谨性,比如关联条件是否合理、是否有限定数据周期等等。 比如:检查源表数据是否有重复的SQL:
SELECT MON_ID,COUNT(*),COUNT(DISTINCT USER_ID)
FROM TABLE_NAME
GROUP BY MON_ID;

如果是上游源数据出现重复,那么应该及时反映给上游进行修正;如果是脚本关联造成的,修改脚本,重新生成数据即可。
但在很多时候,用来分析的这份数据集是一份单独的数据集,并不是在数据仓库中开发得到的数据,既没有上游源数据,也不存在生成数据的脚本,比如公开数据集,那么如何处理其中的重复值?一般的处理方式就是直接删除重复值。

#判断重复数据
dataset.duplicated()    #全部字段重复是重复数据
Out[3]: 
0    False
1    False
2    False
3    False
4    False
5    False
6    False
7    False
8    False
9    False
dtype: bool

dataset.duplicated(['col2'])    #col2字段重复是重复数据
Out[4]: 
0    False
1    False
2    False
3    False
4    False
5    False
6    False
7    False
8     True
9    False
dtype: bool

#删除重复数据    
dataset.drop_duplicates()     #全部字段重复是重复数据
Out[5]: 
   col1  col2  col3 col4      col5    col6  col7
0   101  38.0    96  aaa  572.0000  0.0017     1
1   102  20.0    13  bbb  174.3333  0.0115     0
2   103  44.0   160  ccc  191.3333  0.0000     1
3   104   NaN   128  aaa  236.0000  0.0000     0
4   105  22.0    10  bbb    0.0000 -0.3000     0
5   106  58.0    16  aaa    0.0000  0.0000     1
6   107  30.0    31  aaa  598.0000  0.0000     0
7   108  25.0    87  aaa   19.6667  0.0000     0
8   109  38.0   221  bbb       NaN  0.0000     1
9   110  35.0   115  ccc  425.6667  0.0094     0

dataset.drop_duplicates(['col2'])   #col2字段重复是重复数据
Out[7]: 
   col1  col2  col3 col4      col5    col6  col7
0   101  38.0    96  aaa  572.0000  0.0017     1
1   102  20.0    13  bbb  174.3333  0.0115     0
2   103  44.0   160  ccc  191.3333  0.0000     1
3   104   NaN   128  aaa  236.0000  0.0000     0
4   105  22.0    10  bbb    0.0000 -0.3000     0
5   106  58.0    16  aaa    0.0000  0.0000     1
6   107  30.0    31  aaa  598.0000  0.0000     0
7   108  25.0    87  aaa   19.6667  0.0000     0
9   110  35.0   115  ccc  425.6667  0.0094     0

##2. 缺失值检查 **缺失值主要是指数据集中部分记录存在部分字段的信息缺失。** ###2.1 缺失值出现的原因 出现缺失值主要有**三种原因**: ① 上游源系统因为技术或者成本原因无法完全获取到这一信息,比如对用户手机APP上网记录的解析,一般来说,解析率相对较低; ② 从业务上讲,这一信息本来就不存在,比如一个学生的收入,一个未婚者的配偶姓名; ③ 数据准备脚本开发中出现的错误造成的。 第一种原因,短期内无法解决;第二种原因,数据的缺失并不是错误,而是一种不能避免的客观事实;第三种原因,则只需通过查证修改脚本即可。 缺失值的存在代表了某一部分信息的丢失,直接影响了挖掘分析结论的可靠性与稳定性,因此,必须对缺失值进行处理。 **一般来说:** **如果某字段的缺失值记录数超过了全部记录数的50%,则应该从数据集中直接剔除掉该字段,同时尝试从业务上寻找替代字段;** **如果某字段的缺失值记录数超过了全部记录数的20%,但没有超过50%,则应该首先看这个字段在业务上是否有替代字段,如果有,则直接剔除掉该字段,如果没有,则必须对其进行处理;** **如果某字段的缺失值记录数没有超过全部记录数的20%,不需要剔除该字段,但必须对其进行处理。**
#查看哪些字段有缺失值
dataset.isnull().any()    #获取含有NaN的字段
Out[13]: 
col1    False
col2     True
col3    False
col4    False
col5     True
col6    False
col7    False
dtype: bool

#统计各字段的缺失值个数
dataset.isnull().apply(pd.value_counts)
Out[14]: 
       col1  col2  col3  col4  col5  col6  col7
False  10.0     9  10.0  10.0     9  10.0  10.0
True    NaN     1   NaN   NaN     1   NaN   NaN

#删除含有缺失值的字段
nan_col = dataset.isnull().any()
dataset.drop(nan_col[nan_col].index,axis=1)
Out[15]: 
   col1  col3 col4    col6  col7
0   101    96  aaa  0.0017     1
1   102    13  bbb  0.0115     0
2   103   160  ccc  0.0000     1
3   104   128  aaa  0.0000     0
4   105    10  bbb -0.3000     0
5   106    16  aaa  0.0000     1
6   107    31  aaa  0.0000     0
7   108    87  aaa  0.0000     0
8   109   221  bbb  0.0000     1
9   110   115  ccc  0.0094     0

2.2 缺失值的处理

缺失值的处理主要有两种方式:过滤和填充。

(1)缺失值的过滤

直接删除含有缺失值的记录,总体上会影响样本个数,如果要删除的样本过多或者数据集本来就很小时,这种方式并不建议采用。

#删除含有缺失值的记录
dataset.dropna()
Out[20]: 
   col1  col2  col3 col4      col5    col6  col7
0   101  38.0    96  aaa  572.0000  0.0017     1
1   102  20.0    13  bbb  174.3333  0.0115     0
2   103  44.0   160  ccc  191.3333  0.0000     1
4   105  22.0    10  bbb    0.0000 -0.3000     0
5   106  58.0    16  aaa    0.0000  0.0000     1
6   107  30.0    31  aaa  598.0000  0.0000     0
7   108  25.0    87  aaa   19.6667  0.0000     0
9   110  35.0   115  ccc  425.6667  0.0094     0

(2)缺失值的填充

缺失值的填充主要三种方法
① 方法一:使用特定值填充
使用缺失值字段的平均值、中位数、众数等统计量填充。
优点:简单、快速
缺点:容易产生数据倾斜
② 方法二:使用算法预测填充
将缺失值字段作为因变量,将没有缺失值字段作为自变量,使用决策树、随机森林、KNN、回归等预测算法进行缺失值的预测,用预测结果进行填充。
优点:相对精确
缺点:效率低,如果缺失值字段与其他字段相关性不大,预测效果差
③ 方法三:将缺失值单独作为一个分组,指定值进行填充
从业务上选择一个单独的值进行填充,使缺失值区别于其他值而作为一个分组,从而不影响后续的分析计算。
优点:简单,实用
缺点:效率低,需要逐一进行填充

##使用Pandas进行特定值填充
#不同字段的缺失值都用0填充
dataset.fillna(0)
Out[16]: 
   col1  col2  col3 col4      col5    col6  col7
0   101  38.0    96  aaa  572.0000  0.0017     1
1   102  20.0    13  bbb  174.3333  0.0115     0
2   103  44.0   160  ccc  191.3333  0.0000     1
3   104   0.0   128  aaa  236.0000  0.0000     0
4   105  22.0    10  bbb    0.0000 -0.3000     0
5   106  58.0    16  aaa    0.0000  0.0000     1
6   107  30.0    31  aaa  598.0000  0.0000     0
7   108  25.0    87  aaa   19.6667  0.0000     0
8   109  38.0   221  bbb    0.0000  0.0000     1
9   110  35.0   115  ccc  425.6667  0.0094     0

#不同字段使用不同的填充值
dataset.fillna({'col2':20,'col5':0})
Out[17]: 
   col1  col2  col3 col4      col5    col6  col7
0   101  38.0    96  aaa  572.0000  0.0017     1
1   102  20.0    13  bbb  174.3333  0.0115     0
2   103  44.0   160  ccc  191.3333  0.0000     1
3   104  20.0   128  aaa  236.0000  0.0000     0
4   105  22.0    10  bbb    0.0000 -0.3000     0
5   106  58.0    16  aaa    0.0000  0.0000     1
6   107  30.0    31  aaa  598.0000  0.0000     0
7   108  25.0    87  aaa   19.6667  0.0000     0
8   109  38.0   221  bbb    0.0000  0.0000     1
9   110  35.0   115  ccc  425.6667  0.0094     0

#分别使用各字段的平均值填充
dataset.fillna(dataset.mean())
Out[18]: 
   col1       col2  col3 col4        col5    col6  col7
0   101  38.000000    96  aaa  572.000000  0.0017     1
1   102  20.000000    13  bbb  174.333300  0.0115     0
2   103  44.000000   160  ccc  191.333300  0.0000     1
3   104  34.444444   128  aaa  236.000000  0.0000     0
4   105  22.000000    10  bbb    0.000000 -0.3000     0
5   106  58.000000    16  aaa    0.000000  0.0000     1
6   107  30.000000    31  aaa  598.000000  0.0000     0
7   108  25.000000    87  aaa   19.666700  0.0000     0
8   109  38.000000   221  bbb  246.333333  0.0000     1
9   110  35.000000   115  ccc  425.666700  0.0094     0

#分别使用各字段的中位数填充
dataset.fillna(dataset.median())
Out[19]: 
   col1  col2  col3 col4      col5    col6  col7
0   101  38.0    96  aaa  572.0000  0.0017     1
1   102  20.0    13  bbb  174.3333  0.0115     0
2   103  44.0   160  ccc  191.3333  0.0000     1
3   104  35.0   128  aaa  236.0000  0.0000     0
4   105  22.0    10  bbb    0.0000 -0.3000     0
5   106  58.0    16  aaa    0.0000  0.0000     1
6   107  30.0    31  aaa  598.0000  0.0000     0
7   108  25.0    87  aaa   19.6667  0.0000     0
8   109  38.0   221  bbb  191.3333  0.0000     1
9   110  35.0   115  ccc  425.6667  0.0094     0


##使用sklearn中的预处理方法进行缺失值填充(只适用于连续型字段)
from sklearn.preprocessing import Imputer
#删除非数值型字段
dataset2 = dataset.drop(['col4'],axis=1)
#打印新数据集
dataset2
Out[35]: 
   col1  col2  col3      col5    col6  col7
0   101  38.0    96  572.0000  0.0017     1
1   102  20.0    13  174.3333  0.0115     0
2   103  44.0   160  191.3333  0.0000     1
3   104   NaN   128  236.0000  0.0000     0
4   105  22.0    10    0.0000 -0.3000     0
5   106  58.0    16    0.0000  0.0000     1
6   107  30.0    31  598.0000  0.0000     0
7   108  25.0    87   19.6667  0.0000     0
8   109  38.0   221       NaN  0.0000     1
9   110  35.0   115  425.6667  0.0094     0

#创建填充规则(平均值填充)
nan_rule1 = Imputer(missing_values='NaN',strategy='mean',axis=0)
#应用规则
pd.DataFrame(nan_rule1.fit_transform(dataset2),columns=dataset2.columns)    
Out[36]: 
    col1       col2   col3        col5    col6  col7
0  101.0  38.000000   96.0  572.000000  0.0017   1.0
1  102.0  20.000000   13.0  174.333300  0.0115   0.0
2  103.0  44.000000  160.0  191.333300  0.0000   1.0
3  104.0  34.444444  128.0  236.000000  0.0000   0.0
4  105.0  22.000000   10.0    0.000000 -0.3000   0.0
5  106.0  58.000000   16.0    0.000000  0.0000   1.0
6  107.0  30.000000   31.0  598.000000  0.0000   0.0
7  108.0  25.000000   87.0   19.666700  0.0000   0.0
8  109.0  38.000000  221.0  246.333333  0.0000   1.0
9  110.0  35.000000  115.0  425.666700  0.0094   0.0

#创建填充规则(中位数填充)
nan_rule2 = Imputer(missing_values='NaN',strategy='median',axis=0) 
#应用规则
pd.DataFrame(nan_rule2.fit_transform(dataset2),columns=dataset2.columns)    
Out[37]: 
    col1  col2   col3      col5    col6  col7
0  101.0  38.0   96.0  572.0000  0.0017   1.0
1  102.0  20.0   13.0  174.3333  0.0115   0.0
2  103.0  44.0  160.0  191.3333  0.0000   1.0
3  104.0  35.0  128.0  236.0000  0.0000   0.0
4  105.0  22.0   10.0    0.0000 -0.3000   0.0
5  106.0  58.0   16.0    0.0000  0.0000   1.0
6  107.0  30.0   31.0  598.0000  0.0000   0.0
7  108.0  25.0   87.0   19.6667  0.0000   0.0
8  109.0  38.0  221.0  191.3333  0.0000   1.0
9  110.0  35.0  115.0  425.6667  0.0094   0.0

#创建填充规则(众数填充)
nan_rule3 = Imputer(missing_values='NaN',strategy='most_frequent',axis=0)  
#应用规则
pd.DataFrame(nan_rule3.fit_transform(dataset2),columns=dataset2.columns)   
Out[38]: 
    col1  col2   col3      col5    col6  col7
0  101.0  38.0   96.0  572.0000  0.0017   1.0
1  102.0  20.0   13.0  174.3333  0.0115   0.0
2  103.0  44.0  160.0  191.3333  0.0000   1.0
3  104.0  38.0  128.0  236.0000  0.0000   0.0
4  105.0  22.0   10.0    0.0000 -0.3000   0.0
5  106.0  58.0   16.0    0.0000  0.0000   1.0
6  107.0  30.0   31.0  598.0000  0.0000   0.0
7  108.0  25.0   87.0   19.6667  0.0000   0.0
8  109.0  38.0  221.0    0.0000  0.0000   1.0
9  110.0  35.0  115.0  425.6667  0.0094   0.0

##3. 数据倾斜检查 **数据倾斜是指字段的取值分布主要集中在某个特定类别或者特定区间。** ###3.1 数据倾斜问题的原因 出现这一问题主要有**三种原因**: ① 上游源数据存在问题; ② 数据准备脚本的问题; ③ 数据本身的分布就是如此。 如果某个字段出现数据倾斜问题,必须首先排查上述第一、二种原因,如果都没有问题或者无法检查(如:单独的数据集),那么就要考虑这个字段对后续的分析建模是否有价值。一般来说,有严重的数据倾斜的字段对目标变量的区分能力很弱,对分析建模的价值不大,应该直接剔除掉。 ###3.2 如何衡量数据的倾斜程度 衡量数据的倾斜程度,主要采用频数分析方法,但因数据类别的不同而有所差异: ① 针对连续型字段,需要首先采用等宽分箱方式进行离散化,然后计算各分箱的记录数分布; ② 针对离散型字段,直接计算各类别的记录数分布。 一般来说,如果某个字段90%以上的记录数,主要集中在某个特定类别或者特定区间,那么这个字段就存在严重的数据倾斜问题。
#对于连续型变量进行等宽分箱
pd.value_counts(pd.cut(dataset['col3'],5))  #分成5箱
Out[39]: 
(9.789, 52.2]     4
(94.4, 136.6]     3
(178.8, 221]      1
(136.6, 178.8]    1
(52.2, 94.4]      1
Name: col3, dtype: int64

#对于离散型变量进行频数统计
pd.value_counts(dataset['col4'])
Out[40]: 
aaa    5
bbb    3
ccc    2
Name: col4, dtype: int64

##4. 异常值检查 **异常值是指数据中出现了处于特定分布、范围或者趋势之外的数据,这些数据一般会被称为异常值、离群点、噪声数据等。** ###4.1 异常值产生的原因 异常值的产生主要有**两种原因**: ① 数据采集、生成或者传递过程中发生的错误; ② 业务运营过程出现的一些特殊情况。 将第一种原因产生的异常值称为**统计上的异常**,这是错误带来的数据问题,需要解决;将第二种原因产生的异常值称为**业务上的异常**,反映了业务运营过程的某种特殊结果,它不是错误,但需要深究,在数据挖掘中的一种典型应用就是异常检测模型,比如信用卡欺诈,网络入侵检测、客户异动行为识别等等。 ###4.2 异常值的识别方法 异常值的识别方法主要有以下几种: ####(1)极值检查 主要检查字段的取值是否超出了合理的值域范围。 **① 方法一:最大值最小值** 使用最大值、最小值进行判断。比如客户年龄的最大值为199岁,客户账单的最小费用为-20,这些都明显存在异常。 **② 方法二:3σ原则** 如果数据服从正态分布,在3σ原则下,异常值被定义为与平均值的偏差超过了3倍标准差的值。这是因为,在正态分布的假设下,具体平均值3倍标准差之外的值出现的概率低于0.003,属于极个别的小概率事件。 **③ 方法三:箱线图分析** 箱线图提供了识别异常的标准:异常值被定义为小于下四分位-1.5倍的四分位间距,或者大于上四分位+1.5倍的四分位间距的值。 箱线图分析不要求数据服从任何分布,因此对异常值的识别比较客观。
#获取描述性统计量
statDF = dataset2.describe()
#打印统计量
statDF
Out[45]: 
            col1       col2        col3        col5       col6       col7
count   10.00000   9.000000   10.000000    9.000000  10.000000  10.000000
mean   105.50000  34.444444   87.700000  246.333333  -0.027740   0.400000
std      3.02765  11.959422   71.030588  235.303647   0.095759   0.516398
min    101.00000  20.000000   10.000000    0.000000  -0.300000   0.000000
25%    103.25000  25.000000   19.750000   19.666700   0.000000   0.000000
50%    105.50000  35.000000   91.500000  191.333300   0.000000   0.000000
75%    107.75000  38.000000  124.750000  425.666700   0.001275   1.000000
max    110.00000  58.000000  221.000000  598.000000   0.011500   1.000000

#计算平均值+3倍标准差
statDF.loc['mean+3std'] = statDF.loc['mean'] + 3 * statDF.loc['std']
#计算平均值-3倍标准差
statDF.loc['mean-3std'] = statDF.loc['mean'] - 3 * statDF.loc['std']
#计算上四分位+1.5倍的四分位间距
statDF.loc['75%+1.5dist'] = statDF.loc['75%'] + 1.5 * (statDF.loc['75%'] - statDF.loc['25%'])  
#计算下四分位-1.5倍的四分位间距
statDF.loc['25%-1.5dist'] = statDF.loc['25%'] - 1.5 * (statDF.loc['75%'] - statDF.loc['25%']) 

#再次打印统计量
statDF
Out[50]: 
                   col1       col2        col3         col5       col6       col7
count         10.000000   9.000000   10.000000     9.000000  10.000000  10.000000
mean         105.500000  34.444444   87.700000   246.333333  -0.027740   0.400000
std            3.027650  11.959422   71.030588   235.303647   0.095759   0.516398
min          101.000000  20.000000   10.000000     0.000000  -0.300000   0.000000
25%          103.250000  25.000000   19.750000    19.666700   0.000000   0.000000
50%          105.500000  35.000000   91.500000   191.333300   0.000000   0.000000
75%          107.750000  38.000000  124.750000   425.666700   0.001275   1.000000
max          110.000000  58.000000  221.000000   598.000000   0.011500   1.000000
mean+3std    114.582951  70.322711  300.791764   952.244274   0.259538   1.949193
mean-3std     96.417049  -1.433822 -125.391764  -459.577607  -0.315018  -1.149193
75%+1.5dist  114.500000  57.500000  282.250000  1034.666700   0.003187   2.500000
25%-1.5dist   96.500000   5.500000 -137.750000  -589.333300  -0.001912  -1.500000

#获取各字段最大值、最小值
statDF.loc[['max','min']]
Out[51]: 
      col1  col2   col3   col5    col6  col7
max  110.0  58.0  221.0  598.0  0.0115   1.0
min  101.0  20.0   10.0    0.0 -0.3000   0.0

#判断取值是否大于平均值+3倍标准差
dataset3 = dataset2 - statDF.loc['mean+3std']
dataset3[dataset3>0]
Out[52]: 
   col1  col2  col3  col5  col6  col7
0   NaN   NaN   NaN   NaN   NaN   NaN
1   NaN   NaN   NaN   NaN   NaN   NaN
2   NaN   NaN   NaN   NaN   NaN   NaN
3   NaN   NaN   NaN   NaN   NaN   NaN
4   NaN   NaN   NaN   NaN   NaN   NaN
5   NaN   NaN   NaN   NaN   NaN   NaN
6   NaN   NaN   NaN   NaN   NaN   NaN
7   NaN   NaN   NaN   NaN   NaN   NaN
8   NaN   NaN   NaN   NaN   NaN   NaN
9   NaN   NaN   NaN   NaN   NaN   NaN

#判断取值是否小于平均值-3倍标准差
dataset4 = dataset2 - statDF.loc['mean-3std']
dataset4[dataset4<0]
Out[53]: 
   col1  col2  col3  col5  col6  col7
0   NaN   NaN   NaN   NaN   NaN   NaN
1   NaN   NaN   NaN   NaN   NaN   NaN
2   NaN   NaN   NaN   NaN   NaN   NaN
3   NaN   NaN   NaN   NaN   NaN   NaN
4   NaN   NaN   NaN   NaN   NaN   NaN
5   NaN   NaN   NaN   NaN   NaN   NaN
6   NaN   NaN   NaN   NaN   NaN   NaN
7   NaN   NaN   NaN   NaN   NaN   NaN
8   NaN   NaN   NaN   NaN   NaN   NaN
9   NaN   NaN   NaN   NaN   NaN   NaN

#判断取值是否大于上四分位+1.5倍的四分位间距
dataset5 = dataset2 - statDF.loc['75%+1.5dist']
dataset5[dataset5>0]
Out[54]: 
   col1  col2  col3  col5      col6  col7
0   NaN   NaN   NaN   NaN       NaN   NaN
1   NaN   NaN   NaN   NaN  0.008313   NaN
2   NaN   NaN   NaN   NaN       NaN   NaN
3   NaN   NaN   NaN   NaN       NaN   NaN
4   NaN   NaN   NaN   NaN       NaN   NaN
5   NaN   0.5   NaN   NaN       NaN   NaN
6   NaN   NaN   NaN   NaN       NaN   NaN
7   NaN   NaN   NaN   NaN       NaN   NaN
8   NaN   NaN   NaN   NaN       NaN   NaN
9   NaN   NaN   NaN   NaN  0.006213   NaN

#判断取值是否大于上四分位-1.5倍的四分位间距
dataset6 = dataset2 - statDF.loc['25%-1.5dist']
dataset6[dataset6<0]
Out[55]: 
   col1  col2  col3  col5      col6  col7
0   NaN   NaN   NaN   NaN       NaN   NaN
1   NaN   NaN   NaN   NaN       NaN   NaN
2   NaN   NaN   NaN   NaN       NaN   NaN
3   NaN   NaN   NaN   NaN       NaN   NaN
4   NaN   NaN   NaN   NaN -0.298088   NaN
5   NaN   NaN   NaN   NaN       NaN   NaN
6   NaN   NaN   NaN   NaN       NaN   NaN
7   NaN   NaN   NaN   NaN       NaN   NaN
8   NaN   NaN   NaN   NaN       NaN   NaN
9   NaN   NaN   NaN   NaN       NaN   NaN

(2)记录数分布检查

主要检查字段的记录数分布是否超出合理的分布范围,包括三个指标:零值记录数、正值记录数、负值记录数。

(3)波动检查

波动检查主要适用于有监督的数据,用于检查随着自变量的变化,因变量是否发生明显的波动情况。
以上异常值的识别方法主要针对连续型字段,而对于离散型字段的异常识别主要通过检查类别出现是否出现了合理阈值外的数据,比如苹果终端型号字段,出现了“P20”的取值。

4.3 异常值的处理

对于统计上的异常值的处理,主要采取两种方式:剔除或者替换。剔除是指直接将被标记为异常值的记录从数据集中删除掉,而替换是指将异常值用一个非异常值进行替换,比如边界值,或者有监督情况下的目标变量表征相似的某个值。
对于业务上的异常值的处理,原则就是进行深入探索分析,查找出现这一特殊情况的根本原因。


##5.参考与感谢 \[1] [Python数据分析与数据化运营](https://book.douban.com/subject/27608466/) \[2] [Python数据分析与数据挖掘实战](https://book.douban.com/subject/26677686/)

posted @ 2018-04-22 21:49  hbsygfz  阅读(5265)  评论(0编辑  收藏  举报