python数据预处理: 使用pandas 进行数据清洗

问题:

介绍数据清洗方法。。html

解答:

所谓数据清洗主要处理的是数据中的缺失值、异常值和重复值:python

缺失值处理

数据缺失值指因为各类缘由致使数据中存在的空缺值:数据库中的null,python返回对象none,pandas或numpy中的nan;另空字符串是有实体的不算是缺失值,缺失值没有实体。git

处理数据缺失值通常有4中方法:github

  1. 丢弃
  2. 补全
  3. 真值转化
  4. 不处理

丢弃

若是缺失的数据量不大,且对其丢弃对数据特征的影响有限,能够选着丢弃,毕竟这样容易操做。某一列丢失的数据过多,为了不增长噪声,能够丢弃。web

补全

相对于丢弃补全更经常使用,毕竟数据的完整性很重要,可是补全的方式也很重要,会影响到后续的数据处理。
对全的方法:算法

  • 用平均值、中值、分位数、众数、随机值等替代。效果通常,由于等于人为增长了噪声。
  • 创建一个模型来“预测”缺失的数据。
  • 对于重要的数据,能够专家不足,或是调用数据源头补全,缺点是成本高

转化法

咱们认可缺失值的存在,而且把数据缺失也做为数据分布规律的一部分,这将变量的实际值和缺失值都做为输入维度参与后续数据处理和模型计算。可是变量的实际值能够做为变量值参与模型计算,而缺失值一般没法参与运算,所以须要对缺失值进行真值转换。数据库

以用户性别字段为例,不少数据库集都没法对会员的性别进行补足,但又舍不得将其丢弃,那么咱们将选择将其中的值,包括男、女、未知从一个变量的多个值分布状态转换为多个变量的真值分布状态。网络

不处理

一些模型能够本身处理缺失值,因此能够不对缺失值进行处理。常见的可以自动处理缺失值的模型包括:KNN、决策树和随机森林、神经网络和朴素贝叶斯、DBSCAN(基于密度的带有噪声的空间聚类)等dom

数据:机器学习

# 数据缺失值处理
import pandas as pd
import numpy as np
from sklearn.preprocessing import Imputer
import random
# 获取数据
df1 = pd.read_csv('https://raw.githubusercontent.com/ffzs/dataset/master/boston/train.csv')
df = df0.iloc[:10,:7]

# 查看是否有缺失值
df.isna().values.any()
# False 没有缺失值

# 数据行列
df.shape
# (10, 7) 10行 7列

# 制造10个缺失值
for i in range(10):
    df.iloc[random.choice(range(10)), random.choice(range(3,7))] = np.nan

看下数据:
在这里插入图片描述

# 查看缺失值分布
df.isna().sum()

ID       0
crim     0
zn       0
indus    1
chas     2
nox      3
rm       3
dtype: int64

# 丢弃缺失值
df_droped = df.dropna()
df_droped

  ID	crim	zn	indus	chas	nox	rm
2	4	0.03237	0.0	2.18	0.0	0.458	6.998
3	5	0.06905	0.0	2.18	0.0	0.458	7.147
9	15	0.63796	0.0	8.14	0.0	0.538	6.096

# 将缺失值替代为特定值
# 用后面的值替代缺失值
df.fillna(method='backfill')

  ID	crim	zn	indus	chas	nox	rm
0	1	0.00632	18.0	2.31	0.0	0.469	6.998
1	2	0.02731	0.0	7.07	0.0	0.469	6.998
2	4	0.03237	0.0	2.18	0.0	0.458	6.998
3	5	0.06905	0.0	2.18	0.0	0.458	7.147
4	7	0.08829	12.5	7.87	0.0	0.524	6.012
5	11	0.22489	12.5	7.87	0.0	0.524	6.377
6	12	0.11747	12.5	7.87	0.0	0.524	5.889
7	13	0.09378	12.5	7.87	0.0	0.524	5.889
8	14	0.62976	0.0	8.14	0.0	0.538	5.949
9	15	0.63796	0.0	8.14	0.0	0.538	6.096

# 限制每个后值只能替换一个缺失值
df.fillna(method='bfill', limit=1)

  ID	crim	zn	indus	chas	nox	rm
0	1	0.00632	18.0	2.31	0.0	0.469	NaN
1	2	0.02731	0.0	7.07	0.0	0.469	6.998
2	4	0.03237	0.0	2.18	0.0	0.458	6.998
3	5	0.06905	0.0	2.18	0.0	0.458	7.147
4	7	0.08829	12.5	7.87	0.0	NaN	6.012
5	11	0.22489	12.5	7.87	0.0	0.524	6.377
6	12	0.11747	12.5	7.87	0.0	0.524	5.889
7	13	0.09378	12.5	7.87	0.0	0.524	5.889
8	14	0.62976	0.0	8.14	0.0	0.538	5.949
9	15	0.63796	0.0	8.14	0.0	0.538	6.096

# 用前值替换缺失值,若是没有前值则无法替换
df.fillna(method='pad')

	ID	crim	zn	indus	chas	nox	rm
0	1	0.00632	18.0	2.31	NaN	NaN	NaN
1	2	0.02731	0.0	7.07	0.0	0.469	NaN
2	4	0.03237	0.0	2.18	0.0	0.458	6.998
3	5	0.06905	0.0	2.18	0.0	0.458	7.147
4	7	0.08829	12.5	7.87	0.0	0.458	6.012
5	11	0.22489	12.5	7.87	0.0	0.458	6.377
6	12	0.11747	12.5	7.87	0.0	0.524	6.377
7	13	0.09378	12.5	7.87	0.0	0.524	5.889
8	14	0.62976	0.0	7.87	0.0	0.538	5.949
9	15	0.63796	0.0	8.14	0.0	0.538	6.096

# 插值法就是经过两点(x0,y0),(x1,y1)估计中间点的值 必须有先后值
df.interpolate() 

    ID	crim	zn	indus	chas	nox	rm
0	1	0.00632	18.0	2.310	NaN	NaN	NaN
1	2	0.02731	0.0	7.070	0.0	0.469	NaN
2	4	0.03237	0.0	2.180	0.0	0.458	6.998
3	5	0.06905	0.0	2.180	0.0	0.458	7.147
4	7	0.08829	12.5	7.870	0.0	0.480	6.012
5	11	0.22489	12.5	7.870	0.0	0.502	6.377
6	12	0.11747	12.5	7.870	0.0	0.524	6.133
7	13	0.09378	12.5	7.870	0.0	0.524	5.889
8	14	0.62976	0.0	8.005	0.0	0.538	5.949
9	15	0.63796	0.0	8.140	0.0	0.538	6.096

# 用0值替换缺失值
df.fillna(0)

   ID	crim	zn	indus	chas	nox	rm
0	1	0.00632	18.0	2.31	0.0	0.000	0.000
1	2	0.02731	0.0	7.07	0.0	0.469	0.000
2	4	0.03237	0.0	2.18	0.0	0.458	6.998
3	5	0.06905	0.0	2.18	0.0	0.458	7.147
4	7	0.08829	12.5	7.87	0.0	0.000	6.012
5	11	0.22489	12.5	7.87	0.0	0.000	6.377
6	12	0.11747	12.5	7.87	0.0	0.524	0.000
7	13	0.09378	12.5	7.87	0.0	0.524	5.889
8	14	0.62976	0.0	0.00	0.0	0.538	5.949
9	15	0.63796	0.0	8.14	0.0	0.538	6.096

# 用不一样值替换
df.fillna(dict(nox=0.5, rm=6.0))

  ID	crim	zn	indus	chas	nox	rm
0	1	0.00632	18.0	2.31	NaN	0.500	6.000
1	2	0.02731	0.0	7.07	0.0	0.469	6.000
2	4	0.03237	0.0	2.18	0.0	0.458	6.998
3	5	0.06905	0.0	2.18	0.0	0.458	7.147
4	7	0.08829	12.5	7.87	0.0	0.500	6.012
5	11	0.22489	12.5	7.87	0.0	0.500	6.377
6	12	0.11747	12.5	7.87	0.0	0.524	6.000
7	13	0.09378	12.5	7.87	NaN	0.524	5.889
8	14	0.62976	0.0	NaN	0.0	0.538	5.949
9	15	0.63796	0.0	8.14	0.0	0.538	6.096

# 用平均数替代,选择各自列的均值
df.fillna(df.mean()['chas':'rm'])

    ID	crim	zn	indus	chas	nox	rm
0	1	0.00632	18.0	2.31	0.0	0.501286	6.352571
1	2	0.02731	0.0	7.07	0.0	0.469000	6.352571
2	4	0.03237	0.0	2.18	0.0	0.458000	6.998000
3	5	0.06905	0.0	2.18	0.0	0.458000	7.147000
4	7	0.08829	12.5	7.87	0.0	0.501286	6.012000
5	11	0.22489	12.5	7.87	0.0	0.501286	6.377000
6	12	0.11747	12.5	7.87	0.0	0.524000	6.352571
7	13	0.09378	12.5	7.87	0.0	0.524000	5.889000
8	14	0.62976	0.0	NaN	0.0	0.538000	5.949000
9	15	0.63796	0.0	8.14	0.0	0.538000	6.096000

异常值处理

异常数据,是脱离数据正常分布范围的数据,即噪声,对异常处理须要先辨别异常数据是否为真正须要去除掉的数据

一下几个状况无需对异常数据进行处理:

异常数据源于业务运营

因为业务部门特定的动做致使数据分布异常:如双十一销量猛增,若是数据被剔除的话就没法真实对业务作反馈

异常检测模型

模型自己就是为了检测出数据中的异常数据,若是剔除掉了这些数据,本末倒置,如信用卡欺诈、药物识别、疾病预测、网络攻击等。

非异常敏感模型

若是数据算法和模型对异常值不敏感,不对异常值进行处理也不会对模型形成负面影响,如决策树

# 制造异常值
df = df0.iloc[:10,:7]
df.iloc[4, 5] = 100
df

	ID	crim	zn	indus	chas	nox	rm
0	1	0.00632	18.0	2.31	0	0.538	6.575
1	2	0.02731	0.0	7.07	0	0.469	6.421
2	4	0.03237	0.0	2.18	0	0.458	6.998
3	5	0.06905	0.0	2.18	0	0.458	7.147
4	7	0.08829	12.5	7.87	0	100.000	6.012
5	11	0.22489	12.5	7.87	0	0.524	6.377
6	12	0.11747	12.5	7.87	0	0.524	6.009
7	13	0.09378	12.5	7.87	0	0.524	5.889
8	14	0.62976	0.0	8.14	0	0.538	5.949
9	15	0.63796	0.0	8.14	0	0.538	6.096

# 用过Z-Scores方法判断异常值
# 复制一个dataframe来存储score
df_zscore = df.copy()
for col in df.columns:
    df_col = df[col]
    # 计算每一个值的zscore
    z_score = (df_col - df_col.mean()) / df_col.std()
    # 判断Z-Score得分是否大于2.2
    df_zscore[col] = z_score.abs() > 2.2
df_zscore


      ID	crim	zn	indus	chas	nox	rm
0	False	False	False	False	False	False	False
1	False	False	False	False	False	False	False
2	False	False	False	False	False	False	False
3	False	False	False	False	False	False	False
4	False	False	False	False	False	True	False
5	False	False	False	False	False	False	False
6	False	False	False	False	False	False	False
7	False	False	False	False	False	False	False
8	False	False	False	False	False	False	False
9	False	False	False	False	False	False	False

经过箱型图判断:

# 经过箱型图
%matplotlib inline
import matplotlib.pyplot as plt
df.boxplot()

在这里插入图片描述

对于有固定业务规则的可直接套用业务规则,而对于没有固定业务规则的,能够采用常见的数学模型进行判断,即基于几率分布的模型(例如正态分布的标准差范围)、基于聚类的方法(例如KMeans)、基于密度的方法(例如LOF)、基于分类的方法(例如KNN)、基于统计的方法(例如分位数法)等,此时异常值的定义带有较强的主观判断色彩,具体须要根据实际状况选择。

重复值处理

重复值包括如下两种状况:数据彻底相同的多条数据;数据主体相同可是匹配到的惟一属性不一样,多见于数据仓库的变化维度表,同一个事实表的主体匹配到多个属性。

如下状况需慎重去重:

重复计入用于分析演变规律

商品类别的维度表中,每一个商品对应了同一类别的值是惟一的,可是在全部商品的类别的值重构或升级时,原有的商品可能被分配了类别中的不一样值,对于这种状况须要跟业务进行协商再决定作去重处理。

为解决样本不均衡产生的重复值

处理分类数据建模过程当中样本不均衡的问题,对数据量较少的样本类别偶简单过采样,这样会产生一些重复值也不能去重。

运营过程产生的重复记录

在运营过程当中重复的数据可能意味着重大的运营规则问题,特别是这些重复值出如今企业经营中金钱相关的场景,如重复的订单,重复充值

这些数据通常产生于误操做,重复点击生成订单,若是这样的数据被视为重复数据去除掉的话,运营人员就没法发现出现的问题,没法及时对误操做产生的后果作补救。

# 创造重复值
df = df0.iloc[:5,:7]
df0 = pd.concat([df, df])

# 判断重复数据
df0.duplicated()

0    False
1    False
2    False
3    False
4    False
0     True
1     True
2     True
3     True
4     True
dtype: bool

# 删除重复值 
df0.drop_duplicates()

	ID	crim	zn	indus	chas	nox	rm
0	1	0.00632	18.0	2.31	0	0.538	6.575
1	2	0.02731	0.0	7.07	0	0.469	6.421
2	4	0.03237	0.0	2.18	0	0.458	6.998
3	5	0.06905	0.0	2.18	0	0.458	7.147
4	7	0.08829	12.5	7.87	0	0.524	6.012

# 根据特定列进行删除重复值
df0.drop_duplicates(['zn', 'chas'])

   ID	crim	zn	indus	chas	nox	rm
0	1	0.00632	18.0	2.31	0	0.538	6.575
1	2	0.02731	0.0	7.07	0	0.469	6.421
4	7	0.08829	12.5	7.87	0	0.524	6.012

# inplace 为 true 改变dataframe
df0.drop_duplicates(['zn', 'chas'], inplace=True)
df0

  ID	crim	zn	indus	chas	nox	rm
0	1	0.00632	18.0	2.31	0	0.538	6.575
1	2	0.02731	0.0	7.07	0	0.469	6.421
4	7	0.08829	12.5	7.87	0	0.524	6.012

参考:
《python数据分析与数据化运营》 宋天龙
【Python数据分析基础】: 异常值检测和处理
机器学习中如何处理缺失数据?