数据清洗操作 学习笔记

导入模块
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
导入数据集
df = pr.read_csv('qunar_freetrip.csv' , index_col=0)
df.head()	#简单查看
df.shape	#查看数据形状,13列显示13个特征
df.info()	#查看数据结构(是否有缺失值,数据类型等)
df.describe() # 快速统计(只展示数值型数据的统计)

简单数据处理

df.columns	#查看列名称 可能会出现列名称多空格的情况导致无法直接点出

df.head(2)	# 对比列名称是否有空格
# 移除列名称里面多余的空格
col = df.columns.values # 列名变成支持for循环的ndarray
#for循环加strip移除字符串首尾空格
df.columns = [i.strip() for i in col]
df.columns

列字段处理

# 1.删除无用列字段
df.drop(columns='Unnamed: 0',axis=1,inplace=True)
# 轴用来为超过一维的数组定义的属性,二维数据拥有两个轴:第0轴沿着行的垂直往下,第1轴沿着列的方向水平延伸

# 2.获取列字段
cols = df.columns.values
# 3.for循环依次取出列字段首位的空格
# 方式1 比较繁琐
ccs = []
for col in cols:
    ccs.append(col.strip())
print(ccs)
# 方式2 列表生成式
df.columns = [col.strip() for col in cols]

重复值处理

# 4.重复数据查找
df.duplicated()
# 5.简单的看一眼重复数据的模样(布尔值索引)  可以省略
df[df.duplicated()]

# 6.针对重复的数据 一般情况下都是直接删除的
df.drop_duplicates(inplace=True)
# 7.确认是否删除

# 简单查看
df.shape	# (5100,13) 查看数据数量 >>> (5000,13)

# 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()  # 判断的标准
# 利用逻辑索引筛选数据 找出大于3(根据实际情况更改)倍标准差的就是数据有异常 
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.shape[0]  # 例如规定占比小于0.1%可以直接删除

"""
针对缺失数据有几种处理方式
    1.占比过小可以直接删除
    2.利用均值、统一值直接填充
    3.根据不同的情况采用不同的计算公式填充
常用的四个方法    
    isnull	有缺失值
    notnull	无缺失值
    fillna	补充缺失值
    dropna	删除缺失值
保留几位小数
    round(数据,保留几位)
"""
# 筛选出所有价格缺失的数据
df[df['价格'].isnull()]
# 直接利用价格的均值填充缺失数据
df['价格'].mean()  	# 1732.5140901771338
round(df['价格'].mean(),1)
df['价格'].fillna(round(df['价格'].mean(),1),inplace=True)

# 同理针对节省的数据也做中位数填充(其实应该结合实际采用不同的方法)
df['节省'].fillna(round(df['节省'].mean(),1),inplace=True)

# 验证
df.isnull().sum()

出发地缺失值处理

# 查找具有缺失值的列名称
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]

如何辨别数据是否是异常值,我们可以使用公式
(单个数据 - 整体均值) / 整体的标准差
结果如果大于3或者小于-3说明是异常值…

文本处理

酒店的评分
# 针对酒店评分如何操作
# 1.获取评分及总分
df['酒店'].str[-8:]
# 2.只获取酒店评分不要总分
df['酒店'].str[-8:-3]  # 切片
###############################################
# DataFrame的str方法内部也支持直接使用正则extract
df['酒店评分'] = df['酒店'].str.extract('(\d\.\d)分/5分',expand=False)
"""
expand=False		返回index/series
expand=True			返回DataFrame

\.     是取消. 的特殊含义 就是一个普通点
"""
################################################


酒店类型
# 针对酒店类型
# 方式1还是利用字符串的切片操作
df['酒店'].str[-12:-8]
# 方式2还是利用正则表达式操作
df['酒店'].str.extract(' (.*?) ',expand=False)

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

游玩时间
# 游玩时间
# 利用字符串的切割不太方便,应该考虑直接使用正则
df['路线名'].str.extract('.*?(\d天\d晚)',expand=False)
df['游玩时间'] = df['路线名'].str.extract('.*?(\d天\d晚)',expand=False)

操作excel表格模块openpyxl

即使python模块 也是pandas内部操作excel表格的底层模块

"""
扩展1:
python中操作excel表格的模块有很多,其中最出名的有两个
现阶段使用较多的:openpyxl
之前使用较多的:xlrd(读excel)、xlwt(写excel)

扩展2:
excel
2003版本之前后缀名是xls
2003版本之后更名为xlsx

openpyxl模块只能操作03版本之后的excel文件
xlrd、xlwt既可以操作03版本之前的也可以操作03版本之后的
"""

# 下载
pip3 install openpyxl

创建文件及工作簿

# 参考官网:https://openpyxl.readthedocs.io/en/stable/tutorial.html
from openpyxl import Workbook

# 生成一个excel文件对象
wb = Workbook()

# 创建一个工作簿
w1 = wb.create_sheet('MySheet01')
# 还可以动态调整工作簿的位置(index后面是索引)
w1 = wb.create_sheet('MySheet01',index=0)
# 还可以二次修改工作簿的名称
w1.title = '工作簿01'

# 一次性创建多个工作簿
w2 = wb.create_sheet('MySheet02')
w3 = wb.create_sheet('MySheet03')
w4 = wb.create_sheet('MySheet04')

# 给excel表格命名
wb.save('aaa.xlsx')
"""
要理解excel文件名和工作簿名称的区别   
    一个excel文件内可以包含多个工作簿
"""

写入数据

# 写入数据的方式1
w1['A3'] = 666  # 在列名称是A行索引是3的单元格内写入数据

# 写入数据的方式2
w1.cell(row=3, column=4, value=999)   # 在第三行第四列的位置上写数据999

# 插入公式
w1['A4'] = 123
w1['A5'] = 321
w1['A6'] = '=sum(A3:A5)'  # 求A3到A5的和 注意等号一定要加

# 查看所有工作簿名称
# print(wb.sheetnames)
# 给excel表格命名
wb.save('a.xlsx')
"""
要理解excel文件名和工作簿名称的区别   
    一个excel文件内可以包含多个工作簿
"""

from openpyxl import Workbook

wb = Workbook()
w1 = wb.create_sheet('批量写入',index=0)

# 先写表头(列名称)
w1.append(['id','name','age','gender','phone'])
# 再写表单(真实数据)
# w1.append([1,'jad',18,'male',110])
# w1.append([2,'tony',32,'male',130])
# w1.append([3,'tom',30,'female',120])
"""后续实际应用肯定采用的是for循环"""

# 填写数据的时候多了(没有列字段对应)
# w1.append([1,'jad',18,'male',110,'read'])
# 填写数据的时候少了(完全错乱)
# w1.append([1,'jad','male',110])
"""针对缺失的数据也要用一个值来占位(补位)"""
w1.append([1,'jad','','male',110])
w1.append([2,'Tony',None,'female',120])

wb.save(r'bbb.xlsx')

读数据

from openpyxl import load_workbook
wb = load_workbook(r'a.xlsx',data_only=True)

# 查看所有的工作簿名称
print(wb.sheetnames)  # ['MySheet01', 'Sheet']
# 指定需要操作的工作簿
w1 = wb['MySheet01']

# 读入单元格数据
# 方式1
print(w1['A3'])  # 仅仅是获取到了单元格对象
print(w1['A3'].value)  # 获取单元格数据需要加value
# 方式2
print(w1.cell(row=3,column=1))
print(w1.cell(row=3,column=1).value)

# 针对公式计算的数据  value只会拿到原始计算公式而不是结果
print(w1['A6'])
print(w1['A6'].value)

"""
如果需要获取计算结果而不是公式
# 第一需要加一个参数
    read_only=True,data_only=True
# 第二需要人为的先去修改一下用程序产生的excel表格
    (不可能用程序产生excel文件之后又直接再用程序去读入,
    这样没有任何实际意义 通常用程序创建好表格后给人看,
    人讲自己修改的表格再交由程序处理)
"""

wb = load_workbook(r'b.xlsx',data_only=True)
w1 = wb['批量写入']

for row in w1.rows:  # row行 column列
    print(row)  # 获取到所有有数据的单元格组成的元组
    for data in row:
        print(data.value)

# 获取一列列的数据(如果想获取 必须把readonly去掉)
for column in w1.columns:  # 拿到每一列的数据
    for r in column:  # 拿到一列列数据里面每一个单元格的数据
        print(r.value)

# 获取最大的行数和列数
print(w1.max_row)
print(w1.max_column)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值