数据行业有一句很经典的话——“垃圾进,垃圾出”(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/)

数据挖掘实战<1>:数据质量检查的更多相关文章

  1. 数据准备<2>:数据质量检查-实战篇

    上一篇文章:<数据质量检查-理论篇>主要介绍了数据质量检查的基本思路与方法,本文作为补充,从Python实战角度,提供具体的实现方法. 承接上文,仍然从重复值检查.缺失值检查.数据倾斜问题 ...

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

    数据行业有一句很经典的话--"垃圾进,垃圾出"(Garbage in, Garbage out, GIGO),意思就是,如果使用的基础数据有问题,那基于这些数据得到的任何产出都是没 ...

  3. 顶尖大数据挖掘实战平台(TipDM-H8)产品白皮书

        顶尖大数据挖掘实战平台 (TipDM-H8)           产  品  说  明  书 广州泰迪智能科技有限公司 版权所有 地址: 广州市经济技术开发区科学城232号 网址: http: ...

  4. SAS数据挖掘实战篇【五】

    SAS数据挖掘实战篇[五] SAS--预测模型 6.1 测模型介绍 预测型(Prediction)是指由历史的和当前的数据产生的并能推测未来数据趋势的知识.这类知识可以被认为是以时 间为关键属性的关联 ...

  5. SAS数据挖掘实战篇【四】

    SAS数据挖掘实战篇[四] 今天主要是介绍一下SAS的聚类案例,希望大家都动手做一遍,很多问题只有在亲自动手的过程中才会有发现有收获有心得. 1 聚类分析介绍 1.1 基本概念 聚类就是一种寻找数据之 ...

  6. SAS数据挖掘实战篇【三】

    SAS数据挖掘实战篇[三] 从数据挖掘概念到SAS EM模块和大概的流程介绍完之后,下面的规划是[SAS关联规则案例][SAS聚类][SAS预测]三个案例的具体操作步骤,[SAS的可视化技术]和[SA ...

  7. SAS数据挖掘实战篇【二】

    SAS数据挖掘实战篇[二] 从SAS数据挖掘实战篇[一]介绍完目前的数据挖掘基本概念之外,对整个数据挖掘的概念和应用有初步的认识和宏观的把握之后,我们来了解一下SAS数据挖掘实战篇[二]SAS工具的应 ...

  8. SAS数据挖掘实战篇【一】

    SAS数据挖掘实战篇[一] 1数据挖掘简介 1.1数据挖掘的产生 需求是一切技术之母,管理和计算机技术的发展,促使数据挖掘技术的诞生.随着世界信息技术的迅猛发展,信息量也呈几何指数增长,如何从巨量.复 ...

  9. SAS数据挖掘实战篇【七】

    SAS数据挖掘实战篇[七] 6.5  SAS EM数据挖掘-----预测模型 1  问题定义 目标:建立模型预测贷款申请的信用状态,选择最优的模型来预测和减少损失. 数据集:SAMPSIO.DMAGE ...

随机推荐

  1. iOS中滤镜种类及相关介绍

  2. Faster R-CNN 的 RPN 是啥子?

     Faster R-CNN,由两个模块组成: 第一个模块是深度全卷积网络 RPN,用于 region proposal; 第二个模块是Fast R-CNN检测器,它使用了RPN产生的region p ...

  3. 新概念英语(1-103)The French Test

    Lesson 103 The French test 法语考试 Listen to the tape then answer this question. How long did the exam ...

  4. 基于python的统计公报关键数据爬取 update

    由于之前存在的难以辨别市本级,全市相关数据的原因,经过考虑采用 把含有关键词的字段全部提取进行人工辨别的方法 在其余部分不改变的情况下,更改test部分 def test(real_Title,rea ...

  5. 使用 Angular CLI 和 Webpack 分析包尺寸

    使用 Angular CLI 和 Webpack 分析包尺寸 对于 Web app 来说,高性能总是最高优先级,对于 Angular 也不例外.但是随着应用复杂度的不断增长,我们如何才能知道哪些内容打 ...

  6. CSS优先级和定位

    overflow属性 hidden scroll auto hidden 超出隐藏 scroll 滚动条 Auto 自动 display属性 block inline inline-block non ...

  7. Python基础--函数的定义和调用

    一.函数的作用: 提高代码的可读性,减少代码的冗余,方便调用和修改,组织结构清晰 二.函数的定义:函数遵循先定义后调用的原则 1.无参函数 def funcname(): #def 是关键字,后跟函数 ...

  8. SpringBoot(二):设置springboot同一接口程序启动入口

    根据上一篇文章中搭建了一个springboot简单工程,在该工程中编写HelloWordController.java接口类,并在该类中写了一个main函数,做为该类的接口服务启动入口.此时如果新增多 ...

  9. POJ-1573 Robot Motion模拟

    题目链接: https://vjudge.net/problem/POJ-1573 题目大意: 有一个N*M的区域,机器人从第一行的第几列进入,该区域全部由'N' , 'S' , 'W' , 'E' ...

  10. RTKLIB源码解析(一)——单点定位(pntpos.c)

    RTKLIB源码解析(一)--单点定位(pntpos.c) 标签: GNSS RTKLIB 单点定位 [TOC] pntpos int pntpos (const obsd_t *obs, int n ...