数据分析—-数据清洗

一、导入数据

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:空行

  • solution: 删除
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')
1
print(df)
     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)
1
print(df)
          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)
1
print(df)
          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
# 获取 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、合理性

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)