Python数据分析—评估数据

Python

# 一、评估数据

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

# (一)、结构

  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函数,调整列数或值长度展示的上限。

# 三、评估数据的干净度

准备数据

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
4
姓名 考试1 考试2 考试3
001 小陈 85 95 92
002 小李 91 92 94
003 小王 86 81 NaN
004 小张 79 89 95
005 小赵 96 91 91
006 小周 81 NaN 92

# (一)、评估丢失数据

# 1、info方法

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

# 2、isnull方法

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

# 1)Series中的isnull方法

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

scores.考试2

001     95
002     92
003     81
004     89
005     91
006    NaN
Name: 考试2, dtype: object
1
2
3
4
5
6
7
8
9
scores.考试2.isnull()

001    False
002    False
003    False
004    False
005    False
006     True
Name: 考试2, dtype: bool
1
2
3
4
5
6
7
8
9
# 2)DataFrame中的isnull方法

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

scores
1
姓名 考试1 考试2 考试3
001 小陈 85 95 92
002 小李 91 92 94
003 小王 86 81 NaN
004 小张 79 89 95
005 小赵 96 91 91
006 小周 81 NaN 92
scores.isnull()
1
姓名 考试1 考试2 考试3
001 False False False False
002 False False False False
003 False False False True
004 False False False False
005 False False False False
006 False False True False

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

# 3)提取丢失数据的行

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

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

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

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

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

True + 5
6
False + 5
5
1
2
3
4
# 1)Series

计算空缺值的数量

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

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

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

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

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

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

scores.isnull().sum()

姓名     0
考试1    0
考试2    1
考试3    1
dtype: int64
1
2
3
4
5
6
7

# (二)、评估重复数据

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

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
1
2
3
4
5
6
学号 姓名 性别 身高
0 001 小陈 172.5
1 002 小李 168.0
2 003 小王 178.2
3 002 小张 181.3
4 005 小赵 161.7
5 002 小李 168.0
6 006 小周 158.5

# 1、Series中的duplicated方法

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

students.学号

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

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

# 2、DataFrame中的duplicated方法

会返回布尔值组成的Series

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

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

students.duplicated()

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

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

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

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

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

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

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

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

# (三)、评估不一致数据

Series的value_counts方法

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

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

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
1
2
3
4
5
6
学号 姓名 性别 班级
0 001 小陈 1 班
1 002 小李 1班
2 002 小李 1 班
3 003 小王 一班
4 004 小张 二班
5 005 小赵 2 班
6 006 小周 2 班
students2['班级']

0    11     12    13     一班
4     二班
5    26    2 班
Name: 班级, dtype: object
1
2
3
4
5
6
7
8
9
10
students2['班级'].value_counts()

12
22
11
一班     1
二班     1
Name: 班级, dtype: int64
1
2
3
4
5
6
7
8

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

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

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

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
1
2
3
4
5
姓名 性别 身高
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方法

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

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

# 2、describe方法

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

students3.describe()
1
身高
count 7.000000
mean 266.400000
std 416.596447
min -161.700000
25% 163.250000
50% 172.500000
75% 179.750000
max 1168.000000

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

最近修改于: 2024/12/11 00:00:05
和宇宙温柔的关联
房东的猫