数据清洗

数据清洗的理论

数据分析的工作流程
    1.明确需求
    	到底分析什么数据
    2.收集数据
    	数据的来源主要有三种
            1.公司内部直接提供
            2.网络爬虫获取
            3.花钱购买
    3.数据清洗(不能忽略)
    	我们收集上来的数据很有可能存在不同的缺陷
        1.缺失数据
        2.重复数据
        3.异常数据
        ...
    4.数据分析
    	基于数据进行建模 分析
    5.数据可视化
    	matplotlib
    6.撰写数据分析报告
  
数据清洗简介
	可以将数据清洗看成是做菜的过程
    	1.需求分析		做麻辣香锅
        2.收集数据		买菜
        3.数据清洗		洗菜
        4.数据分析		炒菜
        5.数据可视化	        上菜 拍照
        6.撰写分析报告           评价
        
数据清洗
	专业定义:数据清洗是从记录表、表格、数据库中检测、纠正或删除损坏或不准确记录的过程
      
脏数据
	残缺数据、错误数据、重复数据、不符合规则的数据……
干净的数据
	可以直接带入模型的数据

数据清洗常用方法
	1.数据读取
    	read_csv()
        	读取文本数据(.txt),表格表格数据(.csv)
        read_excel()
        	读取excel数据(.xlsx)
        read_sql()
        	读取MySQL表数据
    2.数据概览
    	head()
        	读取表格前五条数据
        tail()
        	读取表格后五条数据
        shape()
        	获取表格行数与列数
        index
        	获取行索引
        columns
        	获取列名称
        describe()
        	快速统计
        info()
        	查看列名称及数据类型等信息(数据清洗常用)
   3.简单处理
	尤其是字符串首尾空格 不容易被发现
    	In [1]: res = 'jAsOn'
        In [2]: res.upper()
        Out[2]: 'JASON'

        In [3]: res.lower()
        Out[3]: 'jason'

        In [4]: res.title()
        Out[4]: 'Jason'

        In [5]: res1 = 'my name is jason'

        In [6]: res1.title()
        Out[6]: 'My Name Is Jason'

        In [7]: res1.capitalize()
        Out[7]: 'My name is jason'
   4.重复值处理
	duplicated()查看是否有重复数据
    	drop_duplicates()删除重复数据
   5.缺失值处理
	isnull()
    	notnull()
        fillna()
        dropna()
        # 针对不同类型的缺失数据 如果需要填充应该采取不同的策略
            比如年龄缺失可以采用平均值
            比如薪资缺失可以采用中位数
            比如性别缺失可以采用众数
  6.异常值处理
  7.字符串处理
  8.日期格式处理
        pd.to_date()
  """上述流程没有固定的顺序,熟练之后顺序看你个人心情"""

数据清洗实战

数据概览

df.head()
df.tail()
df.shape  # (5100, 14)
df.index
df.columns  # 发现列名称首尾有空格
df.info()  # 发现个别字段存在缺失数据
df.describe()  # 价格和节省可能存在异常数据

列字段处理

# 1.先删除无用的列字段名称  Unnamed: 0
df.drop(columns=['Unnamed: 0',],axis=1,inplace=True)
# """
# 1.shift+tab
# 2.?+执行
# """
# 当修改操作直接返回结果说明并没有修改数据本身而是产生了新的数据

# 2.移除列字段名称首尾的空格
df.columns

# 方式1  普通的for循环
new_columns = []
for col in df.columns:
# 将字符串首尾空格移除之后添加到新的列表中
new_columns.append(col.strip())
new_columns

# 方式2  列表生成式
[col.strip() for col in df.columns]

# 没有赋值符号就是获取 有赋值符号就是修改
df.columns = [col.strip() for col in df.columns]

重复数据处理

# 查看是否存在重复的数据
# df.duplicated()  # 一个个判断是否重复  不太好识别
# 统计重复数据的个数
# df.duplicated().sum()

# 直接删除重复的数据
df.drop_duplicates(inplace=True)

# 删除重复的数据之后 行索引是不会自动重置的   是否需要重置取决于你自己或者业务需求
# 方式1  直接利用内置方法
df.reset_index(inplace=True)
# 方式2  自己修改索引值
df.index = range(0,df.shape[0])

# 如果上述方法执行出现一个index列名称  则删除即可
df.drop(columns=['index',],axis=1,inplace=True)

异常数据处理

# 针对异常数据 我们更加关心的时候数值类型的异常数据
df.describe()

# 利用公式求证我们的猜想
sd = (df['价格'] - df['价格'].mean()) / df['价格'].std()  # 判断的标准
# 根据结果是否大于3判断价格是否存在异常  由于上述结果可能存在负数 所以加上绝对值操作
# sd.abs()


# 方式1:利用逻辑索引筛选数据
# df[(sd > 3)|(sd < -3)]
# 方式2:利用绝对值
df[abs(sd) > 3]  # abs就是绝对值的意思(移除正负号)


# 针对节省异常 如何筛选取决于你自己(也可以继续使用公式判断)
df[df['节省']>df['价格']]

# 针对异常数据 可以修正也可以直接删除
# 方式1  直接边筛选边删除
# 方式2  先将所有需要删除的数据拼接到一起  然后一次性删除
# pandas中的拼接表操作
# 横向合并  pd.merge()
# 纵向合并  pd.concat()
res = pd.concat((df[abs(sd) > 3],df[df['节省']>df['价格']]))
res

# 获取需要删除的数据行索引值
# res.index
# 依据行索引值删除数据
df.drop(index=res.index,axis=0,inplace=True)

df.index = range(0,df.shape[0])  # 自己手动修改

缺失数据处理

# df.info()  # 得知四个字段都存在缺失数据
# isnull
# notnull
# fillna
# dropna
df.isnull().sum()  # 统计各个字段缺失数据个数
df.isnull().sum()/df.shape[0]  # 也可以计算缺失比例(有时候针对缺失数据 是通过判断缺失比例决定处理措施)

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

# 有时候针对缺失的数据很有可能隐藏在其他的字段数据内
df[df['出发地'].isnull()]['路线名'].values  # 结果虽然是数组 但是你可以看成是列表

# 如何从路线名中筛选出出发地
res = '大连-烟台3天2晚 | 入住烟台海阳黄金海岸大酒店 + 幸福航空/天津航空往返机票'
res1 = '哈尔滨-烟台3天2晚 | 入住烟台海阳黄金海岸大酒店 + 幸福航空/天津航空往返机票'

# 方式1  正则表达式
# import re
# re.findall('(.*?)-',res1)
# 方式2  字符串切割
res.split('-')[0]
# 方式3  切片操作(不太好  只是为了复习复习)

# 第一步  只少选出出发地是NaN的数据项
# df.loc[df.出发地.isnull(),'出发地']
# 第二步  利用列表生成式筛选出出发地
# [i.split('-')[0] for i in df.loc[df.出发地.isnull(),'路线名'].values]
# 第三步  加了赋值符号就是修改
df.loc[df.出发地.isnull(),'出发地'] = [i.split('-')[0] for i in df.loc[df.出发地.isnull(),'路线名'].values]

# 确认我们的操作是否有效
df.isnull().sum()

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

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

# 针对目的地的筛选
res = '深圳-大连3天2晚 | 入住大连黄金山大酒店 + 南方航空/东海往返机票'
res1 = '深圳-秦皇岛3天2晚 | 入住大连黄金山大酒店 + 南方航空/东海往返机票'
# 正则表达式是最佳的解决措施
re.findall('-(.*?)\d+',res1)

# 第一步  只选出目的地是NaN的数据项
# df.loc[df.出发地.isnull(),'出发地']
# 第二步  利用正则表达式筛选出目的地
# [re.findall('-(.*?)\d+',i)[0] for i in df.loc[df.目的地.isnull(),'路线名'].values]
# 第三步  加了赋值符号就是修改
df.loc[df.目的地.isnull(),'目的地'] = [re.findall('-(.*?)\d+',i)[0] for i in df.loc[df.目的地.isnull(),'路线名'].values]

# 确认我们的操作是否有效
df.isnull().sum()

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

# 计算价格的平均值并只保留一位小数
round(df['价格'].mean(),1)

df['价格'].fillna(round(df['价格'].mean(),1),inplace=True)

# 确认我们的操作是否有效
df.isnull().sum()

# 利用布尔值索引筛选出价格有缺失的数据
df[df['节省'].isnull()]  

# 计算节省的平均值并只保留一位小数
round(df['节省'].mean(),1)

df['节省'].fillna(round(df['节省'].mean(),1),inplace=True)

# 确认我们的操作是否有效
df.isnull().sum()

文本处理

# 先研究如何筛选出游玩时间
# res = '哈尔滨-北海10天9晚 | 入住北海祥丰嘉年华大酒店 + 春秋航空往返机票'
# re.findall('\d+天\d+晚',res)

# 再研究如何获取所有的路线游玩时间
# [re.findall('\d+天\d+晚',i)[0] for i in df['路线名'].values]

# 创建新的列字段
df['游玩时间'] = [re.findall('\d+天\d+晚',i)[0] for i in df['路线名'].values]

# 在python中使用正则表达式需要借助于re模块  在pandas中其实也可以直接使用正则
df['路线名'].str.extract('.*?(\d+天\d+晚)',expand=False)

res = '北海祥丰嘉年华大酒店 舒适型 4.7分/5分'
res1 = '天津逸海明珠大酒店 高档型 4.1分/5分'
# 方式1  切割
# res.split(' ')[1]
# 方式2  正则表达式
# re.findall(' (.*?) ',res1)
# 方式3  切片
# res1[-11:-8]


df['酒店类型'] = df['酒店'].str.extract(' (.*?) ',expand=False)

res = '北海祥丰嘉年华大酒店 舒适型 4.7分/5分'
# 正则表达式
re.findall('\d\.\d',res)
# 切割
res.split(' ')[-1].split('分')[0]
# 切片
res[-7:-4]


df['酒店评分'] = df['酒店'].str.extract('(\d\.\d)分',expand=False)
posted @ 2021-03-31 21:11  孔夫子挂妖刀  阅读(248)  评论(0)    收藏  举报