数据预处理(二)——数据清洗

主要内容:
数据预处理的必要性
数据清洗
数据集成
数据标准化
数据规约
数据变换与离散化
利用sklearn进行数据预处理
小结

二、数据清洗

1.缺失值的处理
(1)忽略元组
(2)人工填写缺失值
(3)使用一个全局常量填充缺失值
(4)使用属性的中心度量(如均值或中位数)填充缺失值
(5)使用与给定元组属同一类的所有样本的属性均值或中位数
(6)使用最可能的值填充缺失值

2.噪声数据的处理
噪声(Noise)是被测量的变量的随机误差或方差。噪声的处理方法一般有分箱、回归和离群点分析等方法。
(1)分箱
(2)回归
(3)离群点分析

利用Pandas进行数据清洗

1.检测与处理缺失值
Pandas使用浮点值NaN表示缺失数据。
(1)缺失值的检测与统计

利用isnull()函数检测缺失值。

import pandas as pd
import numpy as np
string_data = pd.Series(['aardvark','artichoke',np.nan,'avocado'])
print(string_data)
string_data.isnull()

# 0     aardvark
# 1    artichoke
# 2          NaN
# 3      avocado
# dtype: object
# 0    False
# 1    False
# 2     True
# 3    False
# dtype: bool

Series中的None值处理

string_data = pd.Series(['aardvark','artichoke',np.nan,'avocado'])
string_data.isnull()

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

(2)缺失值的统计

利用isnull().sum()方法统计缺失值

df = pd.DataFrame(np.arange(12).reshape(3,4),columns = ['A','B','C','D'])
df.ix[2,:] = np.nan
df[3] = np.nan
print(df)
df.isnull().sum()

#  A    B    C    D   3
# 0  0.0  1.0  2.0  3.0 NaN
# 1  4.0  5.0  6.0  7.0 NaN
# 2  NaN  NaN  NaN  NaN NaN
# A    1
# B    1
# C    1
# D    1
# 3    3
# dtype: int64

df.ix[] 既可以通过整数索引进行数据选取,也可以通过标签索引进行数据选取,换句话说,df.ix[]是df.loc[]和df.iloc[]的功能集合,且在同义词选取中,可以同时使用整数索引和标签索引。

利用info()方法查看DataFrame的缺失值

df.info()

# 
# RangeIndex: 3 entries, 0 to 2
# Data columns (total 5 columns):
# A    2 non-null float64
# B    2 non-null float64
# C    2 non-null float64
# D    2 non-null float64
# 3    0 non-null float64
# dtypes: float64(5)
# memory usage: 200.0 bytes

2.缺失值的处理
(1)删除缺失值
dropna()函数:删除具有缺失值的行。

dropna(axis = 0,how = 'any', thresh = None, subset = None, inplace = False)
参数 说明
axis 默认为 axis=0,当某行出现缺失值时,将该行丢弃并返回;当axis=1时,为某列出现缺失值,将该列丢弃
how 确定缺失值个数,默认how='any’表明,只要某行有缺失值就将该行丢弃;how='all’表明某行全部为缺失值才将其丢弃
thresh 阈值设定,行列中非默认值的数量小于给定的值,就将该行丢弃
subset 部分标签中删除某行列,如subset=[‘a’,‘d’],即丢弃子列a和d中含有缺失值的行
inplace 布尔值,默认为False,当inplace = True时,即对原数据操作,无返回值

对于Series,dropna()函数返回一个仅含非空数据和索引值的Series。

from numpy import nan as NA
data = pd.Series([1,NA,3.5,NA,7])
print(data)
print(data.dropna())

# 0    1.0
# 1    NaN
# 2    3.5
# 3    NaN
# 4    7.0
# dtype: float64
# 0    1.0
# 2    3.5
# 4    7.0
# dtype: float64

布尔型索引选择过滤非缺失值。

not_null = data.notnull()
print(not_null)
print(data[not_null])

# 0     True
# 1    False
# 2     True
# 3    False
# 4     True
# dtype: bool
# 0    1.0
# 2    3.5
# 4    7.0
# dtype: float64

对于DataFrame对象,dropna()函数默认丢弃任何含有缺失值的行。

from numpy import nan as NA
data = pd.DataFrame([[1.,5.5,3.],[1.,NA,NA],[NA,NA,NA],[NA,5.5,3.]])
print(data)
cleaned = data.dropna()
print('删除缺失值后的:\n',cleaned)

#     0    1    2
# 0  1.0  5.5  3.0
# 1  1.0  NaN  NaN
# 2  NaN  NaN  NaN
# 3  NaN  5.5  3.0
# 删除缺失值后的:
#      0    1    2
# 0  1.0  5.5  3.0

传入how=‘all’ 将只丢弃全为NA的那些行。

data = pd.DataFrame([[1.,5.5,3.],[1.,NA,NA],[NA,NA,NA],[NA,5.5,3.]])
print(data)
print(data.dropna(how='all'))

#      0    1    2
# 0  1.0  5.5  3.0
# 1  1.0  NaN  NaN
# 2  NaN  NaN  NaN
# 3  NaN  5.5  3.0
#  	   0	1	 2
# 0  1.0  5.5  3.0
# 1  1.0  NaN  NaN
# 3  NaN  5.5  3.0

丢弃DataFrame的列。只须传入axis=1即可。

data = pd.DataFrame([[1.,5.5,NA],[1.,NA,NA],[NA,NA,NA],[NA,5.5,NA]])
print(data)
print(data.dropna(axis = 1,how='all'))

#      0    1   2
# 0  1.0  5.5 NaN
# 1  1.0  NaN NaN
# 2  NaN  NaN NaN
# 3  NaN  5.5 NaN
#      0    1
# 0  1.0  5.5
# 1  1.0  NaN
# 2  NaN  NaN
# 3  NaN  5.5

当thresh=N时,表示要求一行至少具有N个非NaN才能保留。

df = pd.DataFrame(np.random.randn(7,3))
df.iloc[:4,1] = NA
df.iloc[:2,2] = NA
print(df)
print(df.dropna(thresh=2))

#           0         1         2
# 0 -0.344574       NaN       NaN
# 1 -1.036411       NaN       NaN
# 2  1.350421       NaN -0.299612
# 3  1.801679       NaN -1.674728
# 4  0.072237  1.331576 -0.393538
# 5 -1.155418 -0.727690 -0.306949
# 6  0.537618 -1.820370 -0.118417
#           0         1         2
# 2  1.350421       NaN -0.299612
# 3  1.801679       NaN -1.674728
# 4  0.072237  1.331576 -0.393538
# 5 -1.155418 -0.727690 -0.306949
# 6  0.537618 -1.820370 -0.118417

(2)填充缺失值
缺失值替换方法fillna():

pandas.DataFrame.fillna(value=None,method=None,axsi=None,inplace=False,limit=None)
参数 说明
value 用于填充缺失值的标量值或字典对象
method 插值方式
axis 待填充的轴,默认axis=0
inplace 修改调用者对象而不产生副本
limit (对于前向和后向填充)可以连续填充的最大数量

通过字典形式填充缺失值。

df = pd.DataFrame(np.random.randn(5,3))
df.loc[:3,1] = NA
df.loc[:2,2] = NA
print(df)
print(df.fillna({1:0.88,2:0.66}))

#           0         1         2
# 0  1.487451       NaN       NaN
# 1 -0.594379       NaN       NaN
# 2 -0.125070       NaN       NaN
# 3  0.905233       NaN -1.448934
# 4 -0.264390 -1.201126 -0.660528
#           0         1         2
# 0  1.487451  0.880000  0.660000
# 1 -0.594379  0.880000  0.660000
# 2 -0.125070  0.880000  0.660000
# 3  0.905233  0.880000 -1.448934
# 4 -0.264390 -1.201126 -0.660528

fillna()函数中参数method的应用。

df = pd.DataFrame(np.random.randn(6,3))
df.iloc[2:,1] = NA
df.iloc[4:,2] = NA
print(df)
print(df.fillna(method = 'ffill'))

#           0         1         2
# 0  0.140363  0.504090 -0.595635
# 1  0.451219  0.445143 -1.690518
# 2 -0.759913       NaN  2.837122
# 3  0.879716       NaN -1.009732
# 4 -1.656160       NaN       NaN
# 5 -0.128482       NaN       NaN
#           0         1         2
# 0  0.140363  0.504090 -0.595635
# 1  0.451219  0.445143 -1.690518
# 2 -0.759913  0.445143  2.837122
# 3  0.879716  0.445143 -1.009732
# 4 -1.656160  0.445143 -1.009732
# 5 -0.128482  0.445143 -1.009732

用Series的均值填充。

data = pd.Series([1.,NA,3.5,NA,7])
data.fillna(data.mean())

# 0    1.000000
# 1    3.833333
# 2    3.500000
# 3    3.833333
# 4    7.000000
# dtype: float64

DataFrame中用均值填充。

df = pd.DataFrame(np.random.randn(4,3))
df.iloc[2:,1] = NA
df.iloc[3:,2] = NA
print(df)
df[1] = df[1].fillna(df[1].mean())
print(df)

#           0         1         2
# 0 -0.651648  0.026439  1.933004
# 1  0.150372 -0.556725  0.365933
# 2 -0.231654       NaN -1.678729
# 3  1.563050       NaN       NaN
#           0         1         2
# 0 -0.651648  0.026439  1.933004
# 1  0.150372 -0.556725  0.365933
# 2 -0.231654 -0.265143 -1.678729
# 3  1.563050 -0.265143       NaN

3.数据值替换
使用replace()方法替换数据值。

data = {'姓名':['张三','小明','马芳','国志'],'性别':['0','1','0','1'],'籍贯':['北京','甘肃','','上海']}
df = pd.DataFrame(data)
df = df.replace('','不详')
print(df)

#    姓名 性别  籍贯
# 0  张三  0  北京
# 1  小明  1  甘肃
# 2  马芳  0  不详
# 3  国志  1  上海

传入列表实现多值替换。

df = df.replace(['不详','甘肃'],['兰州','兰州'])
print(df)

#    姓名 性别  籍贯
# 0  张三  0  北京
# 1  小明  1  兰州
# 2  马芳  0  兰州
# 3  国志  1  上海

传入字典实现多值替换。

df = df.replace({'1':'男','0':'女'})
print(df)

#    姓名 性别  籍贯
# 0  张三  女  北京
# 1  小明  男  兰州
# 2  马芳  女  兰州
# 3  国志  男  上海

4.利用函数或映射进行数据转换
map()方法映射数据。

data = {'姓名':['张三','小明','马芳','国志'],'性别':['0','1','0','1'],'籍贯':['北京','兰州','兰州','上海']}
df = pd.DataFrame(data)
df['成绩'] = [58,86,91,78]
print(df)
def grade(x):
    if x>=90:
        return '优'
    elif 70<=x<90:
        return '良'
    elif 60<=x<70:
        return '中'
    else:
        return '差'
df['等级'] = df['成绩'].map(grade)
print(df)

#    姓名 性别  籍贯  成绩
# 0  张三  0  北京  58
# 1  小明  1  兰州  86
# 2  马芳  0  兰州  91
# 3  国志  1  上海  78
#    姓名 性别  籍贯  成绩 等级
# 0  张三  0  北京  58  差
# 1  小明  1  兰州  86  良
# 2  马芳  0  兰州  91  优
# 3  国志  1  上海  78  良

5.异常值检测
(1)散点图方法

import pandas as pd
wdf = pd.DataFrame(np.arange(20),columns = ['W'])
wdf['Y'] = wdf['W']*1.5+2
wdf.iloc[3,1] = 128
wdf.iloc[18,1] = 150
wdf.plot(kind = 'scatter',x = 'W',y = 'Y')

数据预处理(二)——数据清洗_第1张图片
(2)箱线图分析

盒图:利用箱线图进行异常值检测时,根据经验,将最大(最小)值设置为与四分位数值间距为1.5个IQR(IQR=Q3-Q2)的值,即min=Q1-1.5IQR,max=Q3+1.5IQR,小于min和大于max的值被认为是异常值。

import matplotlib.pyplot as plt
plt.boxplot(wdf['Y'].values,notch = True)

数据预处理(二)——数据清洗_第2张图片
(3)3σ法则

若数据服从正态分布,在3σ原则下,异常值被定义为一组测定值中与平均值的偏差超过3倍标准差的值,因为在正态分布的假设下,距离平均值3σ之外的值出现的概率小于0.003。因此根据小概率事件,可以认为超出3σ之外的值为异常数据。

def outRange(S):
    blidx = (S.mean()-3*S.std()>S)|(S.mean()+3*S.std()<S)
    idx = np.arange(S.shape[0])[blidx]
    outRange = S.iloc[idx]
    return outRange
outier = outRange(wdf['Y'])
outier

# 18    150.0
# Name: Y, dtype: float64

你可能感兴趣的:(python机器学习与数据挖掘,python,机器学习)