数据清洗
大约 5 分钟PythonPythonPandas
数据清洗
1 介绍
数据清洗是数据分析和机器学习过程中的重要步骤。它涉及识别和修正数据中的错误或不一致,使数据更适合用于分析。一个好的数据集应该尽量减少噪声、缺失值、重复项等问题。
1.1 数据问题
- 缺失值:数据集中某些观测值未被记录。
- 重复数据:数据集中相同记录出现多次。
- 错误或异常值:数据集中与其他值明显不同的观测值。
- 数据不一致性:数据中的格式、单位、编码等不一致。
- 不规范的数据格式:数据格式不符合预期的要求。
1.2 数据准备
import pandas as pd
import numpy as np
# 创建示例数据
data = {
'姓名': ['Alice', 'Bob', 'Charlie', 'David', 'Eva', 'Frank', 'Grace', 'Henry'],
'成绩': [85, np.nan, 70, 92, None, 65, 78, 80],
'学科': ['Math', 'English', 'Physics', 'Chemistry', 'Biology', 'History', 'Geography', 'Physics'],
'学期': ['2023-1', '2023-2', '2023-1', '2023-2', '2023-1', '2023-2', '2023-1', '2023-1']
}
# 创建DataFrame
df = pd.DataFrame(data)
# 添加一些重复数据和错误数据
df = df.append({'姓名': 'Alice', '成绩': 90, '学科': 'Math', '学期': '2023-1'}, ignore_index=True)
df = df.append({'姓名': 'Bob', '成绩': 75, '学科': 'English', '学期': '2023-2'}, ignore_index=True)
原始数据如下
姓名 | 成绩 | 学科 | 学期 | |
---|---|---|---|---|
0 | Alice | 85.0 | Math | 2023-1 |
1 | Bob | NaN | English | 2023-2 |
2 | Charlie | 70.0 | Physics | 2023-1 |
3 | David | 92.0 | Chemistry | 2023-2 |
4 | Eva | None | Biology | 2023-1 |
5 | Frank | 65 | History | 2023-2 |
6 | Grace | 78.0 | Geography | 2023-1 |
7 | Henry | 80.0 | Physics | 2023-1 |
8 | Alice | 90.0 | Math | 2023-1 |
9 | Bob | 75.0 | English | 2023-2 |
2 缺失值处理
由于数据来源的复杂性与不确定性,数据中难免会存在字段值不全、缺失等情况。
2.1 查看
在处理缺失值之前,首先要了解数据集中是否存在缺失值。
查看每列缺失值的数量:
print(df.isnull().sum())
姓名 0
成绩 2
学科 0
学期 0
dtype: int64
数据集中总缺失值数量
print(df.isnull().sum().sum())
2
查看缺失值的位置
# 以布尔形式返回缺失值的位置
print(df.isnull())
姓名 成绩 学科 学期
0 False False False False
1 False True False False
2 False False False False
3 False False False False
4 False True False False
5 False False False False
6 False False False False
7 False False False False
8 False False False False
9 False False False False
2.2 缺失值筛选
可以筛选出缺失值的位置。
print(df[df.isna().any(1)])
姓名 成绩 学科 学期
1 Bob NaN English 2023-2
4 Eva NaN Biology 2023-1
2.2 删除重复数据
对于某些情况下,可能需要直接删除包含缺失值的行或列。
删除包含缺失值的行
df_dropped_rows = df.dropna()
print(df_dropped_rows)
姓名 成绩 学科 学期
0 Alice 85.0 Math 2023-1
2 Charlie 70.0 Physics 2023-1
3 David 92.0 Chemistry 2023-2
5 Frank 65.0 History 2023-2
6 Grace 78.0 Geography 2023-1
7 Henry 80.0 Physics 2023-1
8 Alice 90.0 Math 2023-1
9 Bob 75.0 English 2023-2
删除包含缺失值的列
df_dropped_columns = df.dropna(axis=1)
print(df_dropped_columns)
姓名 学科 学期
0 Alice Math 2023-1
1 Bob English 2023-2
2 Charlie Physics 2023-1
3 David Chemistry 2023-2
4 Eva Biology 2023-1
5 Frank History 2023-2
6 Grace Geography 2023-1
7 Henry Physics 2023-1
8 Alice Math 2023-1
9 Bob English 2023-2
2.3 填充
另一种处理缺失值的方法是用其他合理的值填充它们。
df['成绩'].fillna(df['成绩'].mean())
print(df)
姓名 成绩 学科 学期
0 Alice 85.000 Math 2023-1
1 Bob 79.375 English 2023-2
2 Charlie 70.000 Physics 2023-1
3 David 92.000 Chemistry 2023-2
4 Eva 79.375 Biology 2023-1
5 Frank 65.000 History 2023-2
6 Grace 78.000 Geography 2023-1
7 Henry 80.000 Physics 2023-1
8 Alice 90.000 Math 2023-1
9 Bob 75.000 English 2023-2
也可以使用其他的值填充。
# 用指定值填充
df_filled_value = df.fillna(0)
# 用前一个有效值填充
df_filled_forward = df.fillna(method='ffill')
# 用后一个有效值填充
df_filled_backward = df.fillna(method='bfill')
2.4 插值填充
可以通过插值的方法填充数据,默认为线性插值,根据数据的前后两个数字计算。
s = pd.Series([0, 5, np.nan, 7])
# 插值填充
s.interpolate()
0 0.0
1 5.0
2 6.0
3 7.0
dtype: float64
3 重复值的处理
3.1 筛选重复值
在数据清洗过程中,使用 duplicated
方法可以识别数据中的重复值。
subset
是指定需要判断重复的列,这里不考虑成绩列。
print(df.duplicated(subset=['姓名', '学科', '学期']))
可以看到最后两行与前面的重复。
0 False
1 False
2 False
3 False
4 False
5 False
6 False
7 False
8 True
9 True
dtype: bool
获取所有重复行
duplicates = df[df.duplicated(subset=['姓名', '学科', '学期'])]
姓名 成绩 学科 学期
8 Alice 90.0 Math 2023-1
9 Bob 75.0 English 2023-2
3.2 删除重复值
对于重复值,可以选择删除它们。
df_no_duplicates_subset = df.drop_duplicates(subset=['姓名', '学科', '学期'])
print(df_no_duplicates_subset)
姓名 成绩 学科 学期
0 Alice 85.0 Math 2023-1
1 Bob NaN English 2023-2
2 Charlie 70.0 Physics 2023-1
3 David 92.0 Chemistry 2023-2
4 Eva NaN Biology 2023-1
5 Frank 65.0 History 2023-2
6 Grace 78.0 Geography 2023-1
7 Henry 80.0 Physics 2023-1
4 数据格式转换
确保数据以正确的数据类型存储,如使用 astype()
方法设置数据类型,使用 to_datetime()
将字符串转换为日期时间类型。
4.1 数字类型
注意先将nan值给处理后再进行后续的试验。
df.loc[3, '成绩'] = '65.5'
df.loc[5, '成绩'] = '33'
print(df['成绩'])
# 将字符串列转换为浮点数
print(df['成绩'].astype(float))
0 85.0
2 70.0
3 65.5
5 33
6 78.0
7 80.0
8 90.0
9 75.0
Name: 成绩, dtype: object
0 85.0
2 70.0
3 65.5
5 33.0
6 78.0
7 80.0
8 90.0
9 75.0
Name: 成绩, dtype: float64
4.2 时间类型转换
将字符串的时间类型转换为datetime64类型
import pandas as pd
# 创建一个包含不同数据类型的 DataFrame
data = {'A': ['2023-01-01', '2023-01-02', '2023-01-03']}
df = pd.DataFrame(data)
# 将字符串列转换为日期时间类型
df['A'] = pd.to_datetime(df['A'])
print(df.dtypes)
A datetime64[ns]
dtype: object