python数据清洗实战入门笔记(六)数据预处理


数据集地址: https://pan.baidu.com/s/1kMH1AhE8RUyaT73rvJsVPQ
提取码:aai6
数据集介绍:

摩托车的销售情况数据
Condition:摩托车新旧情况(new:新的 和used:使用过的)
Condition_Desc:对当前状况的描述
Price:价格
Location:发获地址
Model_Year:购买年份
Mileage:里程
Exterior_Color:车的颜色
Make:制造商(牌子)
Warranty:保修
Model:类型
Sub_Model:车辆类型
Type:种类
Vehicle_Title:车辆主题
OBO:车辆仪表盘
Watch_Count:表数
N_Reviews:评测次数
Seller_Status:卖家身份
Auction:拍卖(Ture或者False)
Buy_Now:现买
Bid_Count:出价计数

import numpy as np
import pandas as pd
import os
os.chdir(r'G:\pythonProject\pc\Python数据清洗\data')
df = pd.read_csv('MotorcycleData.csv',encoding = 'gbk',na_values='Na')

1 重复值处理

• 数据清洗一般先从重复值和缺失值开始处理
• 重复值一般采取删除法来处理
• 但有些重复值不能删除,例如订单明细数据或交易明细数据等

image-20200518073420750

练习

df.head(5)

image-20200517225946903

对价格和里程数数据进行处理

# 自定义一个函数
def f(x):
    if '$' in str(x):
        x = str(x).strip('$')
        x = str(x).replace(',','')
    else:
        x = str(x).replace(',','')
    return float(x)
df['Price'] =  df['Price'] .apply(f)
df['Mileage'] = df['Mileage'].apply(f)
print ('数据集是否存在重复观测: \n', any(df.duplicated()))

df[df.duplicated()] #查看那些数据重复

image-20200517230208134

np.sum(df.duplicated()) #计算重复数量

image-20200517230228203

df.drop_duplicates() #删除所有变量都重复的行, 注意没有加inplace = True

image-20200517230514103

df.drop_duplicates(subset= ['Condition','Condition_Desc','Price','Location'],inplace=True) #按照两个变量重复来来去重
df.info()

image-20200517230443190

2 缺失值处理

• 缺失值首先需要根据实际情况定义
• 可以采取直接删除法
• 有时候需要使用替换法或者插值法
• 常用的替换法有均值替换、前向、后向替换和常数替换

image-20200518073535106

image-20200518073722048

练习

df.apply(lambda x: sum(x.isnull())/len(x),axis= 0) #缺失比例

image-20200517230714224

#删除法
df.dropna() #直接删除法

image-20200517230901963

df.dropna(how='any',axis = 1 ) #只要有缺失,就删除这一列

image-20200517231024769

df.dropna(how='any',axis = 0) #只要有缺失,就删除这一行,等价于df.dropna()

image-20200517231107609

axis = 0 或者 1代表的函数在数据集作用的方向,0代表沿着行的方向,1代表沿着列的方向

df.dropna(axis = 0,how='any',subset=['Condition','Price','Mileage']) # 1代表列,0代表行,只要有缺失,就删除这一行,基于三个变量

image-20200517231217785

在数据分析中,实际上大部分时候都是按照行来进行删除的,很少会基于列来进行删除 列代表的是变量,是否删除删除列很多时候主要取决于缺失比例

使用替换法进行缺失值的填补

替换法

df.head(5)

image-20200517231516910

df.Mileage.fillna(df.Mileage.mean()) # 年龄用均值填补

image-20200517231611671

df.Mileage.fillna(df.Mileage.median()) #中位数填补

image-20200517231650495

df[df['Exterior_Color'].isnull()]

image-20200517231721528

df.Exterior_Color.fillna(df.Exterior_Color.mode()[0]) #众数填补

image-20200517231842499

df.fillna(20) # 所有缺失用20填补

image-20200517231909059

# 婚姻状况使用众数,年龄使用均值,农户家庭人数使用中位数
df.fillna(value = {'Exterior_Color':df.Exterior_Color.mode()[0],'Mileage':df.Mileage.mean()})

image-20200517231945474

df['Exterior_Color'].fillna(method='ffill') #前向填补

image-20200517232015897

df['Exterior_Color'].fillna(method='bfill') #后向填补

image-20200517232046711

3 异常值处理

• 指那些偏离正常范围的值,不是错误值
• 异常值出现频率较低,但又会对实际项目分析造成偏差
• 异常值一般用过箱线图法(分位差法)或者分布图(标准差法)来判断
• 异常值往往采取盖帽法或者数据离散化

image-20200518073752510

练习

异常值检测可以使用均值的2倍标准差范围,也可以使用上下4分位数差方法

# 异常值检测之标准差法
xbar = df.Price.mean() 
xstd = df.Price.std()
print('标准差法异常值上限检测:\n',any(df.Price> xbar + 2.5 * xstd))
print('标准差法异常值下限检测:\n',any(df.Price< xbar - 2.5 * xstd))

image-20200518072415671

# 异常值检测之箱线图法
Q1 = df.Price.quantile(q = 0.25)
Q3 = df.Price.quantile(q = 0.75)
IQR = Q3 - Q1
print('箱线图法异常值上限检测:\n',any(df.Price > Q3 + 1.5 * IQR))
print('箱线图法异常值下限检测:\n',any(df.Price < Q1 - 1.5 * IQR))

image-20200518072448560

import matplotlib.pyplot as plt
%matplotlib inline
df.Price.plot(kind ='box')

image-20200518072612881

# 导入绘图模块
import matplotlib.pyplot as plt
# 设置绘图风格
plt.style.use('seaborn')
# 绘制直方图
df.Price.plot(kind = 'hist', bins = 30, density = True)
# 绘制核密度图
df.Price.plot(kind = 'kde')
# 图形展现
plt.show()

image-20200518072628979

# 用99分位数和1分位数替换
#计算P1和P99
P1 =df.Price.quantile(0.01); P99 = df.Price.quantile(0.99)
#先创建一个新变量,进行赋值,然后将满足条件的数据进行替换
df['Price_new'] = df['Price']
df.loc[df['Price'] > P99,'Price_new']  = P99
df.loc[df['Price'] < P1,'Price_new']  = P1
df[['Price','Price_new']].describe()

image-20200518072645755

再次使用箱线图可以发现离群值已被剔除

df.Price.plot(kind ='box')

image-20200518072756244

4 数据离散化

• 数据离散化就是分箱
• 一般常用分箱方法是等频分箱或者等宽分箱
• 一般使用pd.cut或者pd.qcut函数

image-20200518073813610

练习

pandas.cut(x, bins, right=True, labels=None, retbins=False, precision=3, include_lowest=False)

参数:

x,类array对象,且必须为一维,待切割的原形式

bins, 整数、序列尺度、或间隔索引。如果bins是一个整数,它定义了x宽度范围内的等宽面元数量,但是在这种情况下,x的范围在每个边上被延长1%,以保证包括x的最小值或最大值。如果bin是序列,它定义了允许非均匀bin宽度的bin边缘。在这种情况下没有x的范围的扩展。

right,布尔值。是否是左开右闭区间,right=True,左开右闭,right=False,左闭右开

labels,用作结果箱的标签。必须与结果箱相同长度。如果FALSE,只返回整数指标面元。

retbins,布尔值。是否返回面元

precision,整数。返回面元的小数点几位

include_lowest,布尔值。第一个区间的左端点是否包含

df.head(5)

image-20200518072851465

df['Price_bin'] =  pd.cut(df['Price_new'],5,labels=range(5))
df['Price_bin'].hist()

image-20200518072910841

这里发现分布不均匀,可以通过数据离散化让数据更加均匀

自定义分段标准和标签

df['Price_new'].describe()

image-20200518073016579

w = [100,1000,5000,10000,20000,50000]
df['Price_bin'] =  pd.cut(df['Price_new'], bins =w,labels=['低','便宜','划算','中等','高'],right=False)
df['Price_bin'].value_counts()

image-20200518073023739

pandas.qcut(x, q, labels=None, retbins=False, precision=3, duplicates=’raise’)

参数: x

q,整数或分位数组成的数组。

q, 整数 或分位数数组 整数比如 4 代表 按照4分位数 进行切割

labels, 用作结果箱的标签。必须与结果箱相同长度。如果FALSE,只返回整数指标面元。

原理都是基于分位数来进行离散化

k = 5
w = [1.0*i/k for i in range(k+1)] 
w

image-20200518073102399

df['Price_bin'] = pd.qcut(df['Price_new'],w,labels=range(k))
df['Price_bin'].hist()

image-20200518073110104

或者先计算分位数的值

k = 5
w1 = df['Price_new'].quantile([1.0*i/k for i in range(k+1)])#先计算分位数,在进行分段
w1[0] = w1[0]* 0.95 # 最小值缩小一点
w[-1] = w1[1]* 1.05 # 将最大值增大一点, 目的是为了确保数据在这个范围内
w1

image-20200518073140199

df['Price_bin'] = pd.cut(df['Price_new'],w1,labels=range(k))
df['Price_bin'].hist()

image-20200518073154449

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值