11 数据科学家80%时间都花费在了这些清洗任务上?
假如采集的数据如下图所示:
如果刚看到这些数据可能我们无法下手,因为这些数据中都没有标注,所以我们对这些数据进行重新整理。
- 首先这些数据的代表含义是:这是一家服装店的会员数据,最上一行是列坐标,最左侧一列是行坐标
- 列坐标中第0列代表的是序号,第1列代表的是会员姓名,第2列代表的是年龄,第3列代表体重,第46列代表男性会员三围尺寸,第79列代表女性会员三围尺寸。
数据质量的准则
- 看到这些数据,我们会想到,应该用什么规则来规范这些数据的质量呢?
- 在这里将清洗规则总结为以下4个关键点,统一起来叫“完全合一”,那么什么意思呢?
- 1.完整性:单条数据是否存在空值,统计的字段是否完整。
- 2.全面性:观察某一列的全部数值,如在Excel中,我们可选中一列,可以看到该列的平均值、最大值、最小值。也可通过常识来判断该列是否存在问题,如:数据定义、单位的标识、数值本身。
- 3.合法性:数据的类型、内容、大小的合法性。比如数据中存在非ASCII字符,性别存在未知,年龄超过了150岁等。
- 4.唯一性:数据是否存在重复记录,因为数据来自于不同来源的汇总,很有可能发生重复。行、列数据都需要是唯一的,比如一个人不能重复记录多次,且一个人的体重也不能在列指标中重复记录多次。
清洗数据,一一击破
1. 完整性
-
问题1:缺失值
-
在数据中有些年龄、体重数值是缺失的,这往往是因为数据量较大,在采集过程中,没有采集到。通常我们采用以下三种方法:
-
删除:删除数据缺失的记录
-
均值:适用当前列的均值
-
高频:使用当前列出现频率最高的数据
-
比如我们想对df[‘Age’]中缺失的数值用平均年龄进行填充,可以写成
-
df['Age'].fillna(df['Age'].mean(),inplace=True)
-
-
如果用最高频的数据进行填充,可先通过value_counts获取Age字段最高频次age_maxf,然后再对Age字段中缺失的数据用age_maxf进行填充:
-
age_maxf=train_features['Age'].value_counts().index[0] train_features['Age'].fillna(age_maxf,inplace=True)
-
-
-
-
问题2:空行
-
我们发现数据中有一个空行,除了index之外,全部的值都是NaN。因为Pandas的read_csv()并没有可选参数忽略空行,所以还需要再数据被读取之后再使用dropna()进行处理,删除空行。
-
#删除全部空行 df.dropna(how="all",inplace=True)
-
-
2. 全面性
-
问题:列数据的单位不统一
-
从数据中我们发现weight列的单位不统一,有的为千克(kgs),有的是磅(lbs)。我们采用将千克作为统一的度量单位,将磅(lbs)转化为千克(kgs)
-
# 获取 weight 数据列中单位为 lbs 的数据 rows_with_lbs = df['weight'].str.contains('lbs').fillna(False) print df[rows_with_lbs] # 将 lbs 转换为 kgs, 2.2lbs=1kgs for i,lbs_row in df[rows_with_lbs].iterrows(): # 截取从头开始到倒数第三个字符之前,即去掉 lbs。 weight = int(float(lbs_row['weight'][:-3])/2.2) df.at[i,'weight'] = '{}kgs'.format(weight)
-
-
3. 合理性
-
问题:非ASCII字符
-
从数据集中我们发现在Firstname和Lastname有一些非ASCII字符。我们可以采用删除或替换的方法来解决,这里采用删除:
-
# 删除非 ASCII 字符 df['First_Name'].replace({r'[^\x00-\x7F]+':''}, regex=True, inplace=True) df['Last_Name'].replace({r'[^\x00-\x7F]+':''}, regex=True, inplace=True)
-
-
4. 唯一性
-
问题一:一列有多个参数
-
在数据集中,姓名列(Name)由两个参数FirstName和LastName。为了数据的整洁,我们可将Name列设置为FirstName和LastName两个字段。使用python的split方法,str.split(expand=True),将列表拆成新的列,并删除原来的Name列
-
# 切分名字,删除源数据列 df[['First_Name','Last_Name']] = df['Name'].str.split(expand=True) df.drop('Name', axis=1, inplace=True)
-
-
-
问题二:重复数据
-
利用Pandas提供的drop_duplicates()来删除重复数据。
-
# 删除重复数据行 df.drop_duplicates(['First_Name','Last_Name'],inplace=True)
-
完整代码:
-
# 11. 数据科学家80%时间都发费在了这些清洗任务上 # -*- coding: utf-8 -*- import pandas as pd from pandas import DataFrame df = pd.read_csv('./11data.csv',engine='python') # print(df) df = df.drop(columns=['Unnamed: 0']) df.rename(columns={'0': 'Index', '1': 'Name','2': 'Age','3': 'Weight', '4': 'm0006','5': 'm0612','6': 'm1218', '7': 'f0006','8': 'f0612','9': 'f1218'}, inplace = True) df = df.drop(columns=['Index']) # 1.完整性 # 1.1 用平均年龄填充 # df['Age'].fillna(df['Age'].mean(),inplace=True) # 1.2 采用最高频次的数据进行填充 # age_maxf = df['Age'].value_counts().index[0] # df['Age'].fillna(age_maxf,inplace=True) # 1.3 删除空行 df.dropna(how='all',inplace=True) # 2. 全面性 # 2.1 列数据单位不统一 # 获取weight数据列中单位为lbs的数据 rows_with_lbs = df['Weight'].str.contains('lbs').fillna(False) # print(df[rows_with_lbs]) # 将lbs转为kgs,2.2lbs=1kgs for i,lbs_row in df[rows_with_lbs].iterrows(): #截取从头开始到倒数第三个字符之前,即去掉lbs weight = int(float(lbs_row['Weight'][:3])/2.2) df.at[i,'Weight'] = '{}kgs'.format(weight) # 4. 唯一性 # 4.1 切分名字,删除源数据列 df[['First_Name','Last_Name']] = df['Name'].str.split(expand=True) df.drop('Name', axis=1, inplace=True) # 3. 合理性 # 删除非 ASCII 字符 df['First_Name'].replace({r'[^\x00-\x7F]+':''}, regex=True, inplace=True) df['Last_Name'].replace({r'[^\x00-\x7F]+':''}, regex=True, inplace=True) # 4.2 删除重复数据 df.drop_duplicates(['First_Name','Last_Name'],inplace=True) #显示所有列 pd.set_option('display.max_columns', None) #显示所有行 pd.set_option('display.max_rows', None) #设置value的显示长度为100,默认为50 pd.set_option('max_colwidth',100) print(df) # 数据结果 # Age Weight m0006 m0612 m1218 f0006 f0612 f1218 First_Name Last_Name # 0 56.0 70kgs 72 69 71 - - - Micky Mous # 1 34.0 70kgs - - - 85 84 76 Donald Duck # 2 16.0 NaN - - - 65 69 72 Mini Mouse # 3 NaN 78kgs 78 79 72 - - - Scrooge McDuck # 4 54.0 89kgs - - - 69 NaN 75 Pink Panther # 5 52.0 85kgs - - - 68 75 72 Huey McDuck # 6 19.0 56kgs - - - 71 78 75 Dewey McDuck # 7 32.0 78kgs 78 76 75 - - - Sc??py Doo # 10 12.0 45kgs - - - 92 95 87 Louie McDuck