Skip to content

一、评估数据

评估数据时,我们主要看两方面:结构和内容

(一)、结构

  1. 结构方面需要清理的数据叫做乱数据;结构方面不需要清理的数据叫做整洁数据。
  2. 整洁数据,根据埃德加科德的第三范式,包括以下三个特点:

1)每列是一个变量

2)每行是一个观察值

3)每个单元格是一个值

任何不符合以上三个特点的数据都是乱数据。

不整洁的数据存在多种多样的例子:比如存在合并单元格的表格或者每列存在多个变量。

很多方便人类理解的数据,并不是整洁数据;

而整洁数据有时不太直观。

因为整洁数据并不是方便人类理解,而是让代码更加高效处理和达成分析目的的。

(二)、内容

1、概念

内容方面需要清理的数据叫脏数据,内容方面不需要清理的数据叫干净数据。

2、脏数据可能存在问题

  1. 丢失数据
    1. 有些值为空缺。
    2. 空缺值的影响大小取决于具体情况,有些时候允许某些列的数据不全。
  2. 有些值为空缺。
    1. 但我们仍然要进行评估,否则可能导致错误的分析,比如:如果我们没有考虑到有同学缺考,存在成绩缺失,直接用总分数除以总人头数求平均,就会导致计算结果被缺失值拉低。
  3. 重复数据
    1. 即数据中有些观察值重复出现。
    2. 有些值的重复不是问题,比如说班级里学生的性别。
    3. 但假如数据中作为唯一表示符的属性存在重复,或者数据中存在有数据实例所有属性值均相同的情况,就是有问题
  4. 不一致数据
    1. 即不同数据值实际含义相同,或不同数据值实际指代统一目标
    2. 比如:数字单位不一致、全称和简写混用、中文数字和阿拉伯数字混用等等
  5. 无效或错误数据
    1. 脱离现实规则的数据都是无效数据,比如:负数的身高
    2. 虽然符合规则但并不准确的数据是错误数据,比如:一个成年人的体重是3公斤

二、评估数据整洁度

数据的整洁度比干净度更好评估,因为结构性问题相比内容性问题,更直观和容易被发现。

通过DataFrame的概况信息,和实际数据,来评估数据的整洁度。

(一)、info方法列名

DataFrame的info方法,它能提供数据的概况信息,其中列名首先能透露一些关于结构的信息。

比如:如果有列叫做'销售额_2010',说明这列应该是同时包含了销售额和年份两个变量,不符合每列只能表示一个变量的整洁性规则。

(二)、head/tail/sample方法

  1. 通过head/tail/sample方法,来获取开头/结尾/随机N行。

通过部分数据来评估,是否符合每列是一个变量,每行是一个观察值,每个单元格是一个值的规则。

  1. 在输出部分行检查结构时,如果DataFrame由于列数太多,或者值太长,而展示不全的话,可以通过set_option函数,调整列数或值长度展示的上限。

三、评估数据的干净度

准备数据

python
import pandas as pd
import numpy as np
scores = pd.DataFrame({"001": {"姓名": "小陈", "考试1": 85, "考试2": 95, "考试3": 92},  "002": {"姓名": "小李", "考试1": 91, "考试2": 92, "考试3": 94},  "003": {"姓名": "小王", "考试1": 86, "考试2": 81, "考试3": np.nan},  "004": {"姓名": "小张", "考试1": 79, "考试2": 89, "考试3": 95},  "005": {"姓名": "小赵", "考试1": 96, "考试2": 91, "考试3": 91},  "006": {"姓名": "小周", "考试1": 81, "考试2": np.nan, "考试3": 92} }).T
scores
姓名考试1考试2考试3
001小陈859592
002小李919294
003小王8681NaN
004小张798995
005小赵969191
006小周81NaN92

(一)、评估丢失数据

1、info方法

将行的数量,与每列非空缺值的数量进行对比,就能知道这列是否存在空缺值。

2、isnull方法

Series和DataFrame都有一个方法叫isnull,作用是检查值是否为空缺值

1)Series中的isnull方法

用在Series上,它会返回一个布尔值组成的Series,告诉我们原Series里的各个值是否为空缺值,是的话就是True,不是就是False

python
scores.考试2

001     95
002     92
003     81
004     89
005     91
006    NaN
Name: 考试2, dtype: object
python
scores.考试2.isnull()

001    False
002    False
003    False
004    False
005    False
006     True
Name: 考试2, dtype: bool
2)DataFrame中的isnull方法

用在DataFrame上,会返回一个布尔值组成的DataFrame,告诉我们原DataFrame里各个值是否为空缺值。

python
scores
姓名考试1考试2考试3
001小陈859592
002小李919294
003小王8681NaN
004小张798995
005小赵969191
006小周81NaN92
python
scores.isnull()
姓名考试1考试2考试3
001FalseFalseFalseFalse
002FalseFalseFalseFalse
003FalseFalseFalseTrue
004FalseFalseFalseFalse
005FalseFalseFalseFalse
006FalseFalseTrueFalse

直接对DataFrame调用isnull方法,并不能直观的评估丢失数据

3)提取丢失数据的行

根据条件筛选DataFrame中的行的原理是:DataFrame的列是Series类型,而Series和条件结合起来,会返回一个布尔值组成的Series,它的长度和DataFrame的行数相对应。DataFrame会用布尔值的Series进行索引,保留True所对应的索引的行。

而在这里,对DataFrame的列调用isnull方法,也会返回一个布尔值组成的Series。将其放在方括号里,DataFrame会用布尔值的Series进行索引,保留True所对应的索引的行,即提取出那列丢失数据的行。

python
scores[scores["考试3"].isnull()]
姓名考试1考试2考试3
003小王8681NaN

3、连续调用isnull方法和sum方法

由于True和False布尔值,用在数学计算里,会被分别视为数字1和数字0,所以再调用求和方法,就是在算True的数量

python
True + 5
6
False + 5
5
1)Series

计算空缺值的数量

python
scores['考试2'].isnull().sum()
1
2)DataFrame

由于sum方法默认沿着纵向操作,会返回一个列名作为标签索引的Series;

又由于DataFrame的列就是Series,所以返回的Series的值,就是各个列里空缺值的数量

a、计算某列空缺值的个数

python
scores.考试3.isnull().sum()
1

b、计算每列空缺值的个数

python
scores.isnull().sum()

姓名     0
考试1    0
考试2    1
考试3    1
dtype: int64

(二)、评估重复数据

Series和DataFrame都有一个方法叫duplicated,作用是检查值或行是否存在重复

python
name = pd.Series(["小陈", "小李", "小王", "小张", "小赵", "小李", "小周"])
gender = pd.Series(["女", "女", "男", "男", "女", "女", "女"])
height = pd.Series([172.5, 168.0, 178.2, 181.3, 161.7, 168.0, 158.5])
student_number = pd.Series(["001", "002", "003", "002", "005", "002", "006"])
students = pd.DataFrame({"学号": student_number, "姓名": name, "性别": gender, "身高": height})
students
学号姓名性别身高
0001小陈172.5
1002小李168.0
2003小王178.2
3002小张181.3
4005小赵161.7
5002小李168.0
6006小周158.5

1、Series中的duplicated方法

会返回布尔值组成的Series,表明当前值是否在前面存在过,某个值第一次出现时是False,说明前面不存在重发;但当它第二次、第三次出现时是True,说明这个属于重复值

python
students.学号

0    001
1    002
2    003
3    002
4    005
5    002
6    006
Name: 学号, dtype: object
python
students.学号.duplicated()

0    False
1    False
2    False
3     True
4    False
5     True
6    False
Name: 学号, dtype: bool

2、DataFrame中的duplicated方法

会返回布尔值组成的Series

1)查看所有属性是否存在重复

默认查看所有属性是否存在重复,当这一行里所有值和前面某行完全一样时,才会是True

python
students.duplicated()

0    False
1    False
2    False
3    False
4    False
5     True
6    False
dtype: bool
2)查看任意属性是否存在重复

给duplicated传入可选参数subset,赋值给一个列表,里面放上我们想查看是否存在重复的任意属性。当这些属性同时出现重复的时候,才会是True

python
students.duplicated(subset=['学号', '性别'])

0    False
1    False
2    False
3    False
4    False
5     True
6    False
dtype: bool
3)提取重复数据的行

原理是根据条件筛选DataFrame中的行。

在这里,对DataFrame调用duplicated方法时,会返回一个布尔值组成的Series。将其放在方括号里,DataFrame会用布尔值的Series进行索引,保留True所对应的索引的行,即提取出包含重复数据的行。

对于长数据,评估重复数据,无法直接查看,只能提取重复数据的行

python
students[students.duplicated(subset=['学号', '性别'])]
学号姓名性别身高
5002小李168.0

(三)、评估不一致数据

Series的value_counts方法

会返回Series里各个值的个数。

我们可以用value_counts,看到DataFrame某列下面所有值的种类,以及各个种类出现的次数,帮我们确定有没有不同值在表示同一目标的情况。

python
name = pd.Series(["小陈", "小李", "小李", "小王", "小张", "小赵", "小周"])
gender = pd.Series(["女", "女", "女", "男", "男", "女", "女"])
class_number = pd.Series(["1 班", "1班", "1 班", "一班", "二班", "2 班", "2 班"])
student_number = pd.Series(["001", "002", "002", "003", "004", "005", "006"])
students2 = pd.DataFrame({"学号": student_number, "姓名": name, "性别": gender, "班级": class_number})
students2
学号姓名性别班级
0001小陈1 班
1002小李1班
2002小李1 班
3003小王一班
4004小张二班
5005小赵2 班
6006小周2 班
python
students2['班级']

0    1
1     1班
2    1
3     一班
4     二班
5    2
6    2
Name: 班级, dtype: object
python
students2['班级'].value_counts()

12
22
1班     1
一班     1
二班     1
Name: 班级, dtype: int64

(四)、评估无效/错误数据

评估无效/错误数据的评估难度很大,比如拿到一个陌生数据集的时候,无法知道上面的地址是不是有效的,某个人的身高是不是准确的,这些都超出了我们能够评估的范围。

但对于特别离谱的数据,还是可以通过某些方法,结合常识,来检查是否存在无效数据

python
name = pd.Series(["小陈", "小李", "小李", "小王", "小张", "小赵", "小周"])
gender = pd.Series(["女", "女", "女", "男", "男", "女", "女"])
height = pd.Series([172.5, 168.0, 1168.0, 178.2, 181.3, -161.7, 158.5])
students3 = pd.DataFrame({"姓名": name, "性别": gender, "身高": height})
students3
姓名性别身高
0小陈172.5
1小李168.0
2小李1168.0
3小王178.2
4小张181.3
5小赵-161.7
6小周158.5

1、Series的sort_values方法

可以对某列的值进行排序,能帮我们发现异常的小值或异常的大值

python
students3.身高.sort_values()
python
5    -161.7
6     158.5
1     168.0
0     172.5
3     178.2
4     181.3
2    1168.0
Name: 身高, dtype: float64

2、describe方法

会展示数字列的最小值、最大值等,可以帮我们确实是否有异常数据的存在

python
students3.describe()
身高
count7.000000
mean266.400000
std416.596447
min-161.700000
25%163.250000
50%172.500000
75%179.750000
max1168.000000

除了这些之外,数据还可能存在其它类型的问题,或者需要其它方法才能评估。

Released under the MIT License.