# Author:Nimo_Ding
'''
数据分析师的数据清洗占据了80%的时间。
没有高质量的数据,就没有高质量的数据挖掘,而清洗是高质量数据的一道保障。
养成数据审核的习惯非常重要。
数据清洗规则:
完全合一
完整性:单条数据是否存在空值,统计的字段是否完善。
全面性:观察某一列的全部数值,看平均值 最大值 最小值来判断该列是否有问题。比如数据定义 单位标识 数值本身。
合法性:数据类型 内容 大小的合法性,比如数据中存在非ASCII字符,性别存在了未知,年龄超过120岁等。
唯一性:数据是否存在重复记录
# fillna 后面inplace参数的取值:True、False
# True:直接修改原对象
# False:创建一个副本,修改副本,原对象不变(缺省默认)
'''
print('\n# 1、完整性')
# 缺失值
# 年龄体重缺失,由于数据量较大,这些数值没有被采集到,通常我们有三种解决方法:
# 删除数据缺失的记录
# 使用当前列的均值代替
# 使用当前列出现频率最高的数据代替。
import numpy as np
import pandas as pd
from pandas import Series,DataFrame
data = {
'name':['nimo','jack','ross','zijie'],
'age':[23,34,45,None]
}
df=DataFrame(data,
columns=['name','age'])
df.loc[0,'age']=34 # 使得第一行第二行的age相等。
print(df)
'''
结果:
name age
0 nimo 34.0
1 jack 34.0
2 ross 45.0
3 zijie NaN
'''
print('\n# 用平均年龄填充:')
# df['age'].fillna(df['age'].mean(),inplace=True)
print('\n# 用最高频的数据进行填充,value_counts对每个值进行计数,index第1个就是最高频的。')
age_maxf=df['age'].value_counts().index[0]
df['age'].fillna(age_maxf,inplace=True)
print(df)
'''
结果:
name age
0 nimo 34.0
1 jack 34.0
2 ross 45.0
3 zijie 34.0
'''
print('# 处理全空的空列')
df['test']=np.nan
print(df)
# 结果:
# name age test
# 0 nimo 34.0 NaN
# 1 jack 34.0 NaN
# 2 ross 45.0 NaN
# 3 zijie 34.0 NaN
df=df.dropna(axis=1)
print(df)
'''
结果:
name age
0 nimo 34.0
1 jack 34.0
2 ross 45.0
3 zijie 34.0
'''
print('\n# 2、全面性')
print('\n# 问题:列数据weight的单位不统一:kgs\lbs')
df=DataFrame({
'num':[1,2,3,4,5,None,6,7],
'name':['nimo ding','jack wang','ross li','zijie t','hello k',None,'world','hi'],
'age':[23,34,None,45,34,None,45,65],
'weight':['70kgs','154lbs',None,'78kgs','189lbs',None,'67kgs','45kgs']
})
print(df)
'''
结果:
num name age weight
0 1.0 nimo ding 23.0 70kgs
1 2.0 jack wang 34.0 154lbs
2 3.0 ross li NaN None
3 4.0 zijie t 45.0 78kgs
4 5.0 hello k 34.0 189lbs
5 NaN None NaN None
6 6.0 world 45.0 67kgs
7 7.0 hi 65.0 45kgs
'''
print('\n# 获取weight数据列中单位为lbs的数据')
row_with_lbs=df['weight'].str.contains('lbs').fillna(False)
print(df[row_with_lbs])
# 结果为:
# num name age weight
# 1 2.0 jack wang 34.0 154lbs
# 4 5.0 hello k 34.0 189lbs
# 将单位磅lbs转化为千克kgs:
for i,lbs_row in df[row_with_lbs].iterrows():
weight=int(float(lbs_row['weight'][:-3])/2.2)
df.at[i,'weight']='{}.kgs'.format(weight)
print(df)
print('\n# 3、合理性:包含了非ASCII字符,删除或替换掉。我的例子中好像没有?')
df['name'].replace({r'[^\x00-\x7F]+':''},regex=True,inplace=True)
print('\n# 4、唯一性')
# 问题:一列有多个参数,name列可以拆分为firstname和lastname
# 拆分之后再将name列删除
df[['firstname','lastname']]=df['name'].str.split(expand=True)
df.drop('name',axis=1,inplace=True)
print(df)
# 结果:
# num age weight firstname lastname
# 0 1.0 23.0 70kgs nimo ding
# 1 2.0 34.0 70.kgs jack wang
# 2 3.0 NaN None ross li
# 3 4.0 45.0 78kgs zijie t
# 4 5.0 34.0 85.kgs hello k
# 5 NaN NaN None None None
# 6 6.0 45.0 67kgs world None
# 7 7.0 65.0 45kgs hi None
# 问题:重复数据
# 删除
df.drop_duplicates(['firstname','lastname'],inplace=True)
print('\n# 作业:如下美食数据请做清洗')
# ounces盎司 重量
df=DataFrame({
'food':['bacon','pulled pork','bacon','Pastrami','corned beef',
'Bacon','pastrami','honey ham','nova lox'],
'ounces':[4,3,np.nan,6,7.5,8,-3,5,6],
'animal':['pig','pig','pig','cow','cow','pig','cow','pig','salmon']
})
print(df)
# 结果:
# food ounces animal
# 0 bacon 4.0 pig
# 1 pulled pork 3.0 pig
# 2 bacon NaN pig
# 3 Pastrami 6.0 cow
# 4 corned beef 7.5 cow
# 5 Bacon 8.0 pig
# 6 pastrami -3.0 cow
# 7 honey ham 5.0 pig
# 8 nova lox 6.0 salmon
print('\n# 1、全面性:food统一变成小写')
df['food']=df['food'].str.lower()
print(df)
print('\n# 2、唯一性:删除重复行') # 可放到最后一步骤
df.drop_duplicates()
print(df)
print('\n# 3、合法性,将ounces中负值删除')
print(df[df['ounces']<0].index)
df=df.drop(df[df['ounces']<0].index)
print(df)
# df=df[df['ounces']>0] # 保留ounces>0的数据
print('\n# 4、完整性,将nan值替换成平均值')
df['ounces'].fillna(round(df['ounces'].mean(),1),inplace=True)
print(df)
# 最后将索引重新生成
df=df.reset_index(drop=True)
print(df)
11 数据清洗工作
最新推荐文章于 2023-07-29 16:30:33 发布