数据清洗

概要

  • 数据清洗的概念

  • 数据清洗实战案例


详细

  • 数据清洗的概念

数据清洗:在数据分析之前,对数据进行各项处理以达到分析要求的过程

# 我们可以把数据分析的过程比作制作一道菜
数据分析          ——>       做菜
明确需求          ——>       明确要做什么菜
采集数据          ——>       去菜市场等买菜
数据清洗          ——>       洗菜、切菜、配菜
数据分析          ——>       炒菜
撰写报告+可视化    ——>       装盘拍照发朋友圈+给别人吃

 

准确定义

# 数据清洗 
  从记录表(文本文件),表格(Excel文件),数据库(db)中检测、纠正、删除损坏以及不准确记录的过程。
​
# 脏数据
  未经处理的自身含有一定问题的数据(缺失、异常、重复...等)。
# 干净数据 
  经过处理的完全符合分析必要的规范的数据。

 

数据清洗的常用流程

1.读取外部数据: 根据数据来源选择
    read_csv
    read_excel
    read_sql
    read_html
2.数据概览: 掌握现有数据的大概情况
    index
    columns
    head
    tail
    shape
    describe
    info: 该属性返回个数、是否含有缺失数据以及类型
    dtypes
3.初步处理
    移除首尾空格 .strip()、大小写转换等
4.重复值处理
    duplicated()    查看是否含有重复数据
    drop_duplicates()   删除重复数据
5.缺失值处理
    删除缺失值 dropna()、填充缺失值 fillna()
6.异常值处理
    删除异常值、修正异常值(当做缺失值处理)
7.字符串处理
    切割、筛选等
8.时间格式处理
    Y-年、m-月、d-日、H-时、M-分、S-"""
    步骤3->步骤8无固定顺序,按照具体情况选择合适的顺序即可
"""

  • 数据清洗实战案例

数据概览

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
​
# 首先读取数据
df = pd.read_csv(r'qunar_freetrip.csv')

 1、可以先查看前五条,掌握大概形式

df.head()

2、查看行与列的数目

df.shape

3、查看所有列字段

df.columns

4、查看数据整体信息

df.info

5、快速统计

df.describe()

列字段处理

1、删除无用列字段

df.drop(columns='Unnamed: 0',axis=1,inplace=True)

2、获取列字段

cols = df.columns.values

3、使用for循环一次去除列首尾的空格

# 常规循环写法
ccs = []
for col in cols:
    ccs.append(col.strip())
print(ccs)
# 列表生成式(优化)
df.columns = [col.strip() for col in cols]

重复值处理

4、查找重复数据

df.duplicated()

5、了解重复数据的大概情况

df[df.duplicated()]

6、重复数据一般可以直接删除

df.drop_duplicates(inplace=True)

7、确认是否成功删除

df.shape

8、这里要注意一点,删除数据后,行索引不会自动重置

  (1) 获取行索引值

df.index

  (2) 按照当前行数修改行索引值

df.index = range(0, df.shape[0])

  (3) 查看修改完的行索引值

df.tail()

异常值处理

1、利用快速统计大致筛选出可能有异常数据的字段,如优惠力度大于原价的数据

df.describe()

2、利用公式判断可能出现异常的数据

价格的标准分数 = (价格-价格的平均值)/价格的标准差

这里引入一个概念,标准分数—standard score

 

用公式表示为:z=(x-μ)/σ;其中z为标准分数;x为某一具体分数,μ为平均数,σ为标准差

 

Z值的量代表着原始分数和母体平均值之间的距离,是以标准差为单位计算。

在原始分数低于平均值时Z则为负数,反之则为正数。

一般情况下,标准分数的绝对值大于3则为极端值,即异常数据。

 

sd = (df['价格']-df['价格'].mean()) / df['价格'].std()
# 判断sd的绝对值是否大于3
df[(sd > 3)|(sd < -3)]
df[abs(sd) > 3]

# 查找优惠力度大于原价的数据(推荐下列方式)
df[df['节省'] > df['价格']]

3、删除异常数据
  (1) 先拼接,再删除(也可以按照结果依次删除)
    横向合并: pd.merge()
    纵向合并: pd.concat()

res = pd.concat(
[df[df['节省'] > df['价格']],
df[abs(sd) > 3]]
)

  (2) 获取要删除的行数据的行索引

del_index = res.index

  (3) 根据行索引删除数据

df.drop(index=del_index, inplace=True)

  (4) 重置行索引

df.index = range(0, df.shape[0])

出发地缺失值处理

1、查找具有缺失值的列字段名称以及数目

df.isnull()
df.isnull().sum()

2、利用布尔值索引筛选出缺失出发地的数据

df[df.出发地.isnull()]

3、获取缺失出发地的数据的路线数据

df.loc[df.出发地.isnull(), '路线名'].values

4、利用字符串切割提取出发地替换出发地这一列的的缺失数据

df.loc[df.出发地.isnull(), '出发地'] = [i.split('-')[0] for i in df.loc[df.出发地.isnull(), '出发地'].values]
"""
    1.操作数据的列字段需要使用loc方法
    不支持直接使用[]
    2.缺失值处理
        (1)采用数学公式依据其他数据填充
        (2)其他单元格中可能含有缺失值数据
        (3)缺失值占比特别小的情况下有时可以删除
"""

 

目的地缺失值处理

1、利用布尔值索引筛选出缺失目的地的数据

df[df.目的地.isnull()]

2、获取缺失目的地的数据的路线数据

df.loc[df.目的地.isnull(), '路线名'].values

3、由于需要的字符串不在首尾,更适合利用正则筛选目的地

import re
reg_exp = '-(.*?)\d'
# 正则案例
resTest = re.findall(reg_exp, '深圳-秦皇岛3天2晚 | 入住大连黄金山大酒店 + 南方航空/东海往返机票')

# 具体操作
df.loc[df.目的地.isnull(), '目的地'] = [re.findall(reg_exp, i) for i in df.loc[df.目的地.isnull(), '路线名'].values]

价格/节省缺失值处理

1、筛选出所有缺失价格的数据

df[df['价格'].isnull()]

2、利用均值填充缺失数据

avgP = df['价格'].mean()
# 四舍五入
p = round(avgP, 1)
df['价格'].fillna(p, inplace=True)
​
# 对于缺失节省的数据可以采用中位数填充,根据实际情况采用不同的方法
df['节省'].fillna(round(df['节省'].mean(),1),inplace=True)

验证处理结果

# 缺失数据的数目
df.isnull().sum()

在MySQL中判断是否含有重复的数据

# 思路
    先统计某字段数据个数,再统计去重后的数据个数,之后作对比。
    相同-无重复数据|不相同-存在重复
select count(name) from userinfo;
select count(distinct(name)) from userinfo;
  • 作业

1、添加三列,酒店类型、酒店评分、游玩时间。

# 思路
1.筛选酒店字段
hotelTypes = []
for hotelType in df['酒店'].values:
    # 使用空格匹配
    hotelTypes.append(re.findall(' (.*?) ', hotelType))
# 创建新的列—酒店类型    
df['酒店类型'] = hotelTypes
# dataframe类型自带匹配正则的方法
df['酒店类型'] = df['酒店'].str.extract(' (.*?) ')
2.筛选酒店评分 hotelScores = [] for hotelScore in df['酒店'].values: # 使用空格匹配 hotelScores.append(re.findall('(\d\.\d)分', hotelScore)[0]) .需要取消转义 # 创建新的列—酒店评分 df['酒店评分'] = hotelScores 3.筛选游玩时间 days = [] for routeName in df['路线名'].values: # 使用晚字前的天数匹配 days.append(re.findall('(\d.*?晚)', routeName)[0]) \d+天\d+晚 # 创建新的列—游玩时间 df['游玩时间'] = days

posted @ 2021-10-20 14:01  Leguan001  阅读(321)  评论(0)    收藏  举报