数据清洗的概念:

# 数据分析的过程和别的过程没什么区别 只要明确思路 其他都不难 拿做菜举例

# 类比定义

数据分析过程                做菜过程

  明确需求                  明确做什么菜品

  收集采集                  去菜市场买菜

  数据清洗                  洗菜切菜配菜

  数据分析                  炒菜

  数据报告 + 数据可视化            拍照发朋友圈吃

 

# 专业定义

  数据清洗是从记录表、表格、数据库中检测、纠正或删除损坏或不准确记录的过程

 

# 专业名词

  1.脏数据

    没有经过处理 自身含有一定问题的数据(缺失、异常、重复...)

  2.干净数据

    经过处理完全符合规范要求的数据

 

# 常用方法

  1.读取外部数据

1 # 读取不同文件格式命令
2     read_csv
3     read_excel
4     read_sql
5     read_html

  2.数据概览

1 # 
2     index
3     columns
4     head
5     tail
6     shape
7     describe
8     info
9     dtypes

  3.简单处理

    移除首尾空格 大小写转换...

  4.重复值处理

duplicated()    查看是否含有重复数据
drop_duplicates()    删除重复数据

  5.缺失值处理

    删除缺失值、填充缺失值

  6.异常值处理

    删除异常值、修正异常值(当做缺失值处理)

  7.字符串处理

    切割、筛选...

  8.时间格式处理

    Y m d H M S

"""以上步骤三到步骤八没有固定顺序"""

 

数据清洗实战案例:

1 # 先是导入数据分析三剑客模块
2     import numpy as np
3     import pandas as pd
4     import matplotlib.pyplot as plt
# 选择需要进行数据分析的软件
    df = pd.read_csv(r'qunar_freetrip.csv')

# 随后便是查看其数据 进行分析

 1 # 查看前五条数据 掌握大概
 2     df.head()
 3 # 查看表的行列总数
 4     df.shape
 5 # 查看所有的列字段
 6     df.columns  # 发现列字段有一些是有空格的
 7 # 查看数据整体信息
 8     df.info()  # 发现去程时间和回程时间是字符串类型需要做日期类型转换
 9 # 快速统计
10     df.describe()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

列字段处理:

 1 # 1.删除无用列字段
 2 # df.drop(columns='Unnamed: 0',axis=1,inplace=True)
 3 # 2.获取列字段
 4 cols = df.columns.values
 5 # 3.for循环依次取出列字段首位的空格
 6 
 7 # 方式1 比较繁琐
 8 # ccs = []
 9 # for col in cols:
10 #     ccs.append(col.strip())
11 # print(ccs)
12 
13 # 方式2 列表生成式
14 df.columns = [col.strip() for col in cols]
15 df.columns

 

 

重复值处理:

# 4.重复数据查找
# df.duplicated()
# 5.简单的楼一眼重复数据的模样(布尔值索引)  可以省略
# df[df.duplicated()]
# 6.针对重复的数据 一般情况下都是直接删除的
# df.drop_duplicates(inplace=True)
# 7.确认是否删除
# df.shape
# 8.行索引会不会因为数据的删除而自动重置(删除完数据之后行索引是不会自动重置的)
## 如何获取表的行索引值
# df.index
## 右侧加上赋值符号就是修改行索引值
# df.index = range(0,df.shape[0])
df.tail()

 

 

 

 

 

 

 

 

 

异常值处理:

# 利用快速统计大致筛选出可能有异常数据的字段
# df.describe()  # 价格小于节省 那么可能是价格有问题或者节省有问题

# 利用公式求证我们的猜想
sd = (df['价格'] - df['价格'].mean()) / df['价格'].std()  # 判断的标准
# 利用逻辑索引筛选数据
df[(sd > 3)|(sd < -3)]
# 利用绝对值
df[abs(sd) > 3]  # abs就是绝对值的意思(移除正负号)

# 同理验证节省是否有异常(不一定要使用)
# sd1 = (df['节省'] - df['节省'].mean()) / df['节省'].std()  # 判断的标准
# 利用逻辑索引筛选数据
# df[(sd > 3)|(sd < -3)]
# 利用绝对值
# df[abs(sd1) > 3]  # abs就是绝对值的意思(移除正负号)


# 直接简单粗暴找节省大于价格的数据(推荐下列方式)
df[df['节省'] > df['价格']]



# 删除价格和节省都有异常的数据
# 方式1:先拼接 再一次性删除
# 横向合并pd.merge()
# 纵向合并pd.concat()
# res = pd.concat([df[df['节省'] > df['价格']],df[abs(sd) > 3]])
## 获取要删除的行数据 索引值
# del_index = res.index
# 根据索引删除数据
df.drop(index=del_index,inplace=True)
# 再次重置索引
df.index = range(0,df.shape[0])
# 方式2: 得出一个结果就删一个

 

 

 

 

 

出发地缺失值处理:

# 查找具有缺失值的列名称
df.isnull().sum()  # 统计每个字段缺失数据条数

# 利用布尔值索引筛选出出发地有缺失的数据
df[df.出发地.isnull()]  

# 获取出发地缺失的数据的路线数据
df.loc[df.出发地.isnull(),'路线名'].values


# 利用字符串切割替换出发地缺失数据
df.loc[df.出发地.isnull(),'出发地'] = [i.split('-')[0] for i in df.loc[df.出发地.isnull(),'路线名'].values]
################################
# 操作数据的列字段需要使用loc方法
################################
# 针对缺失值的处理
#     1.采用数学公式依据其他数据填充
#     2.缺失值可能在其他单元格中含有
#     3.如果缺失值数量展示很小可删除

 

 

 

 

 

目的地缺失值处理:

# 针对目的地操作如上(筛选要比出发地难!!!)
# df[df.目的地.isnull()]  
# 获取目的地缺失的路线数据
# df.loc[df.目的地.isnull(),'路线名'].values
# 利用正则筛选出目的地
import re
# 案例演示
reg_exp = '-(.*?)\d'
# res = re.findall(reg_exp,'深圳-秦皇岛3天2晚 | 入住大连黄金山大酒店 + 南方航空/东海往返机票')

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

 

 

 

 

 

 

 添加新列表:

# 酒店类型

# 将酒店变为列表
[re.findall(' (.*?) ',i) for i in df['酒店'].values]
# 加入新列表
df['酒店类型']=[re.findall(' (.*?) ',i) for i in df['酒店'].values]
df

 

 

 

 

 

# 酒店评分

同上筛选出即可
另一种方法为
df.insert(6,'酒店评分',[re.findall(' (\d.\d)分',i) for i in df['酒店'].values])
df

 

 

# 游玩时间

# 同上
[re.findall('\d天\d晚',i) for i in df['路线名'].values]
df.insert(4,'游玩时间',[re.findall('\d天\d晚',i) for i in df['路线名'].values])
df

 

 

 补充:

"""MySQL中如何快速判断某列是否还有重复数据"""

# 思路:统计某个字段选数据的个数 在利用去重操作 两者结合判断

# 先统计数据个数(重复也会统计进去)
select count(name) from userinfo;

# 利用去重操作 先去重再计数
select count(distinct(name)) from userinfo;

# 如果两者数字相同表示name列没有重复的数据 不同则表示含有重复的数据