数据分析—-数据清洗
一、导入数据
1 2 3 4
| import pandas as pd import numpy as np from pandas import Series,DataFrame import xlrd
|
1 2
| df = DataFrame(pd.read_excel('datas/grades.xlsx')) print(df)
|
Unnamed: 0 Unnamed: 1 Unnamed: 2 Unnamed: 3
0 蒋广佳 43.0 69.0 61.0
1 廖菲 80.0 64.0 62.0
2 沈秀玲 68.0 74.0 98.0
3 韦丹 48.0 53.0 64.0
4 张梦雅 72.0 73.0 96.0
5 赵雅欣 60.0 NaN 70.0
6 曹海广 74.0 60.0 20.0
7 陈泽灿 38.0 21.0 92.0
8 NaN 88.0 67.0 84.0
9 高海亮 86.0 74.0 96.0
10 顾晓冬 84.0 60.0 90.0
11 侯星宇 64.0 111.0 NaN
12 江宜哲 60.0 33.0 70.0
13 NaN NaN NaN NaN
14 梁杨杨 68.0 54.0 94.0
15 刘辉 NaN 63.0 98.0
16 罗嘉豪 39.0 44.0 56.0
17 施亚君 90.0 63.0 90.0
18 孙添 64.0 63.0 78.0
19 王杰 74.0 NaN 76.0
20 王泽 52.0 48.0 94.0
21 NaN 60.0 69.0 74.0
22 杨福程 70.0 49.0 76.0
23 尤澳晨 91.0 67.0 86.0
24 翟佳 78.0 73.0 88.0
25 张旭 100.0 60.0 98.0
26 支星哲 80.0 63.0 100.0
27 邹湘涛 54.0 40.0 90.0
- 我们可以看见上面的数据是缺少标注的,列名缺少标注;并且有很多是空值,因此我们要对数据进行清洗,提高数据的质量。在这里数据清洗有四个要点简称“完全合一”
- 完整性:单条数据是否完整,统计的字段是否完善。
- 全面性:观察某一列的全部数值,选中一列,我们可以看到最大值,最小值,平均值。我们可以通过常识判断数据是否合理,比如:数据定义、单位标识、数值本身。
- 合法性:数据的类型、内容、大小的合法性。比如数据中存在非ASCII字符,性别存在未知,总分超过100等。
- 唯一性:数据是否存在重复记录,由于数据来源于不同的渠道,重复的情况是非常常见的。行数据、列数据都需要是唯一的。
- 事实上数据清洗的标准有差不多七八条,有兴趣的可以了解一下,这里归纳为“完全合一”四条,按照这四条基本上可以解决数据清洗中的大部分问题,使得数据标准、干净、连续。
二、开始数据清洗
1、完整性
problem 1:空行
1
| df.dropna(how="all",inplace=True)
|
problem 2:缺失值
- solution:
- 删除:删除数据缺失的记录
- 均值:使用当前列的均值
- 高频:使用当前列出现平率最高的数据
- 首先我们先把列的标注补上
1
| df = df.rename(columns={'Unnamed: 0':'index','Unnamed: 1':'math','Unnamed: 2':'english','Unnamed: 3':'c++'})
|
1
| df = df.drop(columns='index')
|
math english c++
0 43.0 69.0 61.0
1 80.0 64.0 62.0
2 68.0 74.0 98.0
3 48.0 53.0 64.0
4 72.0 73.0 96.0
5 60.0 NaN 70.0
6 74.0 60.0 20.0
7 38.0 21.0 92.0
8 88.0 67.0 84.0
9 86.0 74.0 96.0
10 84.0 60.0 90.0
11 64.0 111.0 NaN
12 60.0 33.0 70.0
14 68.0 54.0 94.0
15 NaN 63.0 98.0
16 39.0 44.0 56.0
17 90.0 63.0 90.0
18 64.0 63.0 78.0
19 74.0 NaN 76.0
20 52.0 48.0 94.0
21 60.0 69.0 74.0
22 70.0 49.0 76.0
23 91.0 67.0 86.0
24 78.0 73.0 88.0
25 100.0 60.0 98.0
26 80.0 63.0 100.0
27 54.0 40.0 90.0
- 现在我们想对df[‘math’]中缺失的值用平均值代替
1
| df['math'].fillna(df['math'].mean(),inplace=True)
|
math english c++
0 43.000000 69.0 61.0
1 80.000000 64.0 62.0
2 68.000000 74.0 98.0
3 48.000000 53.0 64.0
4 72.000000 73.0 96.0
5 60.000000 NaN 70.0
6 74.000000 60.0 20.0
7 38.000000 21.0 92.0
8 88.000000 67.0 84.0
9 86.000000 74.0 96.0
10 84.000000 60.0 90.0
11 64.000000 111.0 NaN
12 60.000000 33.0 70.0
13 68.653846 NaN NaN
14 68.000000 54.0 94.0
15 68.653846 63.0 98.0
16 39.000000 44.0 56.0
17 90.000000 63.0 90.0
18 64.000000 63.0 78.0
19 74.000000 NaN 76.0
20 52.000000 48.0 94.0
21 60.000000 69.0 74.0
22 70.000000 49.0 76.0
23 91.000000 67.0 86.0
24 78.000000 73.0 88.0
25 100.000000 60.0 98.0
26 80.000000 63.0 100.0
27 54.000000 40.0 90.0
- 如果想用最高频率的数据对english进行填充,可以通过value_counts获取math字段最高频次english_maxf,然后对其进行填充
1
| english_maxf = df['english'].value_counts().index[0]
|
1
| df['english'].fillna(english_maxf,inplace=True)
|
math english c++
0 43.000000 69.0 61.0
1 80.000000 64.0 62.0
2 68.000000 74.0 98.0
3 48.000000 53.0 64.0
4 72.000000 73.0 96.0
5 60.000000 63.0 70.0
6 74.000000 60.0 20.0
7 38.000000 21.0 92.0
8 88.000000 67.0 84.0
9 86.000000 74.0 96.0
10 84.000000 60.0 90.0
11 64.000000 111.0 NaN
12 60.000000 33.0 70.0
13 68.653846 63.0 NaN
14 68.000000 54.0 94.0
15 68.653846 63.0 98.0
16 39.000000 44.0 56.0
17 90.000000 63.0 90.0
18 64.000000 63.0 78.0
19 74.000000 63.0 76.0
20 52.000000 48.0 94.0
21 60.000000 69.0 74.0
22 70.000000 49.0 76.0
23 91.000000 67.0 86.0
24 78.000000 73.0 88.0
25 100.000000 60.0 98.0
26 80.000000 63.0 100.0
27 54.000000 40.0 90.0
2、全面性
problem:列数据单位不统一
solution:将不同的单位的找出来,将其进行迭代替换,比如说将榜(lbs)转化为千克(kgs)
1 2 3 4 5 6 7 8
| rows_with_lbs = df['weight'].str.contains('lbs').fillna(False) print df[rows_with_lbs]
for i,lbs_row in df[rows_with_lbs].iterrows(): weight = int(float(lbs_row['weight'][:-3])/2.2) df.at[i,'weight'] = '{}kgs'.format(weight)
|
3、合理性
problem:非ASCII字符
solution:对于非ASCII字符,我们可以采用删除或者替换的方式,我们直接选择删除
1
| df['name'].replace({r'[^\x00-\x7f]+':''},regex=True,inplace=True)
|
4、唯一性
problem1:一列有多个参数
solution:比如英文名字,是有两部分组成的,包含两个参数Firstname、Lastnamr,我们需要将name一列拆分为Firstname和Lastname两个字段,我们可以采用split方法,对其进行切分
1 2
| df['First_namr','Last_name'] = df['name'].str.split(expand=True) df.drop('name',axis=1,inplace=True)
|
problem2:重读数据
solution:我们校验数据是否存在重复数据,如果有重复数据,如果就用pandas提供的drop_duplicates()来删除重复数据。
1
| df.drop_duplicates(['First_name','Last_name'],inplace=True)
|