目录

前言:

一、前置准备:环境搭建+数据集获取

1. 环境搭建

2. 数据集选择与加载

3. 数据集信息解读

3.1 看整体信息,摸清数据“基本盘”

3.2 重点分析缺失值,锁定清洗核心对象

3.3 逐字段拆解,确定具体清洗方案

3.3.1 缺失值处理分析

3.3.2 异常值处理分析

二、核心清洗操作实战(按优先级排序)

1. 缺失值处理(最高频场景)

2. 重复值处理

3. 异常值处理(数值型字段)

4. 数据类型转换

三、清洗后的数据导出(后续分析/建模用)

四、核心知识点总结(初学者必记)

附录


前言:

        数据清洗是数据分析/AI建模的基础步骤,直接影响后续结果的准确性。结合上篇文章对于Pandas基础操作的讲解,今天使用Hugging Face可获取的经典公开数据集Titanic,实战讲解最常用的清洗操作,适合初学者快速上手。

一、前置准备:环境搭建+数据集获取

1. 环境搭建

        确保已安装Python,执行以下命令安装Pandas依赖库:

pip install pandas

2. 数据集选择与加载

        选择Hugging Face上的Titanic数据集(经典入门级,含缺失值、异常值等典型清洗场景,Hugging Face需科学上网,如需Titanic数据集,我将在文末附下载链接)。

        读取数据集:

import pandas as pd

# 1. 加载本地titanic.csv数据集(使用指定的CSV读取方式)
df = pd.read_csv("code/Pandas/data/titanic.csv")  #实际使用请替换成自己的本地地址或采用Hugging Face推荐的导入方法
print("数据集加载成功!")

# 2. 查看数据基本信息(清洗前必做,了解数据全貌)
print("\n=== 清洗前数据基本信息 ===")
print("数据形状(行×列):", df.shape)
print("\n前5行数据:")
print(df.head())
print("\n数据类型+缺失值统计:")
print(df.info())
print("\n数值型字段统计描述:")
print(df.describe())

运行结果:

数据集加载成功!

=== 清洗前数据基本信息 ===
数据形状(行×列): (891, 12)

前5行数据:
   PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
0            1         0       3  ...   7.2500   NaN         S
1            2         1       1  ...  71.2833   C85         C
2            3         1       3  ...   7.9250   NaN         S
3            4         1       1  ...  53.1000  C123         S
4            5         0       3  ...   8.0500   NaN         S

[5 rows x 12 columns]

数据类型+缺失值统计:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype
---  ------       --------------  -----
 0   PassengerId  891 non-null    int64
 1   Survived     891 non-null    int64
 2   Pclass       891 non-null    int64
 3   Name         891 non-null    object
 4   Sex          891 non-null    object
 5   Age          714 non-null    float64
 6   SibSp        891 non-null    int64
 7   Parch        891 non-null    int64
 8   Ticket       891 non-null    object
 9   Fare         891 non-null    float64
 10  Cabin        204 non-null    object
 11  Embarked     889 non-null    object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
None

数值型字段统计描述:
       PassengerId    Survived      Pclass         Age       SibSp       Parch        Fare
count   891.000000  891.000000  891.000000  714.000000  891.000000  891.000000  891.000000
mean    446.000000    0.383838    2.308642   29.699118    0.523008    0.381594   32.204208
std     257.353842    0.486592    0.836071   14.526497    1.102743    0.806057   49.693429
min       1.000000    0.000000    1.000000    0.420000    0.000000    0.000000    0.000000
25%     223.500000    0.000000    2.000000   20.125000    0.000000    0.000000    7.910400
50%     446.000000    0.000000    3.000000   28.000000    0.000000    0.000000   14.454200
75%     668.500000    1.000000    3.000000   38.000000    1.000000    0.000000   31.000000
max     891.000000    1.000000    3.000000   80.000000    8.000000    6.000000  512.329200

3. 数据集信息解读

3.1 看整体信息,摸清数据“基本盘”
数据形状(行×列): (891, 12)

前5行数据:
   PassengerId  Survived  Pclass  ...     Fare Cabin  Embarked
0            1         0       3  ...   7.2500   NaN         S
1            2         1       1  ...  71.2833   C85         C
2            3         1       3  ...   7.9250   NaN         S
3            4         1       1  ...  53.1000  C123         S
4            5         0       3  ...   8.0500   NaN         S

        根据数据形状直观了解数据集共891条乘客数据,12个描述字段,属于小数据集,清洗难度低。

        根据前5行数据预览能直观看到字段的实际格式,比如:- Cabin字段有NaN(表示缺失值),说明该字段存在缺失;- Survived字段是0/1(0=死亡,1=存活),属于标签字段;- Pclass字段是1/3(代表舱位等级),属于分类字段;

3.2 重点分析缺失值,锁定清洗核心对象

        数据类型+缺失值统计是清洗的“核心依据”,重点看「Non-Null Count」(非空值数量),通过“总行数-非空值数量”计算缺失值数量,再按缺失量定处理方案:

表格列名

含义

结合数据解读

Column(字段名)

数据的属性名称

比如PassengerId(乘客ID)、Survived(存活状态)等

Non-Null Count(非空值数量)

该字段有效数据的数量(非NaN)

用891减去该数值,得到缺失值数量(比如Age:891-714=177个缺失值)

Dtype(数据类型)

字段的数据类型,决定处理方式

int64=整数(如Survived)、float64=小数(如Age)、object=字符串(如Name)

3.3 逐字段拆解,确定具体清洗方案

        结合缺失值情况、数据类型、数值描述,分“缺失值处理”“异常值处理”两类确定方案:

Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype
---  ------       --------------  -----
 0   PassengerId  891 non-null    int64
 1   Survived     891 non-null    int64
 2   Pclass       891 non-null    int64
 3   Name         891 non-null    object
 4   Sex          891 non-null    object
 5   Age          714 non-null    float64
 6   SibSp        891 non-null    int64
 7   Parch        891 non-null    int64
 8   Ticket       891 non-null    object
 9   Fare         891 non-null    float64
 10  Cabin        204 non-null    object
 11  Embarked     889 non-null    object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
None

数值型字段统计描述:
       PassengerId    Survived      Pclass         Age       SibSp       Parch        Fare
count   891.000000  891.000000  891.000000  714.000000  891.000000  891.000000  891.000000
mean    446.000000    0.383838    2.308642   29.699118    0.523008    0.381594   32.204208
std     257.353842    0.486592    0.836071   14.526497    1.102743    0.806057   49.693429
min       1.000000    0.000000    1.000000    0.420000    0.000000    0.000000    0.000000
25%     223.500000    0.000000    2.000000   20.125000    0.000000    0.000000    7.910400
50%     446.000000    0.000000    3.000000   28.000000    0.000000    0.000000   14.454200
75%     668.500000    1.000000    3.000000   38.000000    1.000000    0.000000   31.000000
max     891.000000    1.000000    3.000000   80.000000    8.000000    6.000000  512.329200
3.3.1 缺失值处理分析
  • 缺失量极少(<1%):Embarked(登船港口) - 数据情况:非空889,缺失2个(缺失占比0.2%) - 处理方案:直接删除缺失行(缺失量太小,对整体数据影响可忽略)

  • 缺失量中等(10%-30%):Age(年龄) - 数据情况:非空714,缺失177个(缺失占比19.8%) - 数据类型:float64(数值型) - 处理方案:用中位数填充(参考数值型字段统计,Age中位数是28.0,比平均值更抗极端值干扰)

  • 缺失量极大(>50%):Cabin(船舱) - 数据情况:非空204,缺失687个(缺失占比77.1%) - 数据类型:object(字符串型) - 处理方案:用“Unknown”标注缺失值(缺失量太大,删除或填充都会失真,标注为“未知”最合理)

  • 无缺失值字段(9个):PassengerId、Survived、Pclass、Name、Sex、SibSp、Parch、Ticket、Fare - 处理方案:无需做缺失值处理,重点关注数据类型和异常值

3.3.2 异常值处理分析

        数值型字段统计描述(count/mean/std/min/25%/50%/75%/max)的核心作用是找“异常值”(偏离正常范围的值),重点看「min(最小值)」「max(最大值)」「std(标准差)」:

  • Age(年龄):无明显异常 - 统计结果:min=0.42(婴儿),max=80(老人),符合正常年龄范围; - 处理方案:无需额外删除异常值(若后续建模需严格筛选,可用品位法IQR进一步验证)。

  • Fare(票价):存在潜在异常 - 统计结果:mean=32.2,max=512.33,标准差=49.69(标准差远大于平均值,说明存在极端高票价); - 处理方案:若用于一般分析,可暂时保留;若用于建模,需用IQR法(Q1-1.5*IQR到Q3+1.5*IQR)筛选正常范围(Q1=7.91,Q3=31.0,IQR=23.09,异常值边界:-26.73到65.64,需删除>65.64的高票价数据)。

  • 其他数值字段(PassengerId、Survived、Pclass、SibSp、Parch):无异常 - PassengerId是唯一标识,min=1、max=891,无重复或缺失; - Survived是0/1标签,无异常; - Pclass是1/2/3(舱位等级),无异常; - SibSp(兄弟姐妹/配偶数量)max=8,Parch(父母/子女数量)max=6,属于合理范围。

核心总结:分析清洗前数据的核心逻辑是先找“必须处理的问题”(缺失值),再找“可优化的问题”(异常值、数据类型)。

二、核心清洗操作实战(按优先级排序)

        核心原则:先处理缺失值→再处理重复值→最后处理异常值,避免步骤混乱。

1. 缺失值处理(最高频场景)

先明确缺失情况(基于上面的df.info()结果):

  • age(年龄):缺失177个→数值型字段

  • cabin(船舱):缺失687个→字符串字段

  • embarked(登船港口):缺失2个→分类字段

常用处理方法(按需选择,示例代码如下)

# 方法1:删除缺失值(仅适用于缺失量极少的情况,如Embarked)
df_clean = df.dropna(subset=["Embarked"])               # 仅删除embarked字段缺失的行

# 方法2:填充缺失值(适用于缺失量中等的数值型字段,如Age)
# 用中位数填充(避免受极端值影响,比平均值更稳健)
df_clean["Age"] = df_clean["Age"].fillna(df_clean["Age"].median())

# 方法3:用特殊值填充(适用于缺失量极大的字符串字段,如Cabin)
df_clean["Cabin"] = df_clean["Cabin"].fillna("Unknown") # 缺失船舱标记为"未知"

# 验证:确认无缺失值
print("\n清洗后缺失值统计:")
print(df_clean.isnull().sum())  # 所有字段缺失值均为0

2. 重复值处理

        步骤:先检测重复行→再删除重复行(保留第一次出现的行)

# 检测重复行
duplicate_count = df_clean.duplicated().sum()
print("重复行数量:", duplicate_count)                   # titanic数据集默认无重复行,此处仅演示方法
# 删除重复行
df_clean = df_clean.drop_duplicates(keep="first")       # keep="first"表示保留第一行,删除后续重复行

3. 异常值处理(数值型字段)

        异常值:偏离正常范围的值,常用“四分位法”检测(IQR)。

以Age(年龄)字段为例,实战处理:

# 步骤1:计算四分位(Q1=25%分位数,Q3=75%分位数)
Q1 = df_clean["Age"].quantile(0.25)
Q3 = df_clean["Age"].quantile(0.75)
IQR = Q3 - Q1

# 步骤2:定义异常值边界(小于Q1-1.5*IQR 或 大于Q3+1.5*IQR 即为异常值)
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

# 步骤3:筛选正常数据(删除异常值)
df_clean = df_clean[(df_clean["Age"] >= lower_bound) & (df_clean["Age"] <= upper_bound)]
print(f"Age字段异常值边界:[{lower_bound:.2f}, {upper_bound:.2f}]")
print("处理异常值后数据形状:", df_clean.shape)

4. 数据类型转换

部分字段可能存在类型不合理(如本数据集无此问题,演示通用方法):

# 将字符串类型的"性别"转换为分类类型
df_clean["sex"] = df_clean["sex"].astype("category")

# 将数值型的"存活状态"(0=死亡,1=存活)转换为布尔类型
df_clean["survived"] = df_clean["survived"].astype(bool)

# 验证转换后的数据类型
print(f"\n=== 数据类型优化后 ===")
print(df_clean.dtypes)

三、清洗后的数据导出(后续分析/建模用)

将清洗完成的数据保存为CSV文件,方便后续使用:

df_clean.to_csv("code/Pandas/data/titanic_cleaned.csv", index=False)
print("\n清洗完成!数据已导出为titanic_cleaned.csv文件")

四、核心知识点总结(初学者必记)

  1. DataFrame是Pandas的核心数据结构,可理解为“带标签的表格”;

  2. 缺失值处理优先选“填充”(按字段类型选中位数/均值/特殊值),仅缺失极少时选“删除”;

  3. 重复值处理用 duplicated() 检测,drop_duplicates() 删除;

  4. 数值型异常值常用“四分位法(IQR)”检测,避免极端值干扰;

  5. Hugging Face的datasets库可快速获取各类公开数据集,适合实战练习。

结语:本文覆盖了Pandas数据清洗的90%实战场景,核心是“先了解数据→再针对性处理”。建议初学者复制代码逐行运行,观察每步输出结果,快速掌握逻辑。后续可尝试用此方法清洗Hugging Face上的其他数据集(如iriswine)强化练习。

附录

本文所使用数据集:ankislyakov/titanic at main
若无法科学上网,相关链接:https://pan.quark.cn/s/4a9bfda2ed18

完整代码:

import pandas as pd

# 1. 加载本地titanic.csv数据集(使用指定的CSV读取方式)
df = pd.read_csv("code/Pandas/data/titanic.csv")        #实际使用请替换成自己的本地地址或采用Hugging Face推荐的导入方法
print("数据集加载成功!")

# 2. 查看数据基本信息(清洗前必做,了解数据全貌)
print("\n=== 清洗前数据基本信息 ===")
print("数据形状(行×列):", df.shape)
print("\n前5行数据:")
print(df.head())
print("\n数据类型+缺失值统计:")
print(df.info())
print("\n数值型字段统计描述:")
print(df.describe())

# 3. 核心清洗操作
## 3.1 缺失值处理
print(f"\n=== 缺失值处理 ===")
# 方法1:删除缺失值(仅适用于缺失量极少的情况,如Embarked)
df_clean = df.dropna(subset=["Embarked"])               # 仅删除embarked字段缺失的行

# 方法2:填充缺失值(适用于缺失量中等的数值型字段,如Age)
# 用中位数填充(避免受极端值影响,比平均值更稳健)
df_clean["Age"] = df_clean["Age"].fillna(df_clean["Age"].median())

# 方法3:用特殊值填充(适用于缺失量极大的字符串字段,如Cabin)
df_clean["Cabin"] = df_clean["Cabin"].fillna("Unknown") # 缺失船舱标记为"未知"

## 3.2 重复值处理
# 检测重复行
duplicate_count = df_clean.duplicated().sum()
print(f"\n=== 重复值处理 ===")
print("重复行数量:", duplicate_count)                   # titanic数据集默认无重复行,此处仅演示方法
# 删除重复行
df_clean = df_clean.drop_duplicates(keep="first")       # keep="first"表示保留第一行,删除后续重复行

## 3.3 异常值处理(以Age字段为例,采用四分位法IQR)
# 步骤1:计算四分位(Q1=25%分位数,Q3=75%分位数)
Q1 = df_clean["Age"].quantile(0.25)                     
Q3 = df_clean["Age"].quantile(0.75)
IQR = Q3 - Q1                                           # 四分位距

# 步骤2:定义异常值边界(小于Q1-1.5*IQR 或 大于Q3+1.5*IQR 即为异常值)
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

# 步骤3:筛选正常数据(删除异常值)
df_clean = df_clean[(df_clean["Age"] >= lower_bound) & (df_clean["Age"] <= upper_bound)]
print(f"\n=== 异常值处理 ===")
print(f"Age字段异常值边界:[{lower_bound:.2f}, {upper_bound:.2f}]")
print("处理异常值后数据形状:", df_clean.shape)

## 3.4 数据类型优化(可以节省内存,提升后续处理效率)
# 将字符串类型的"性别"转换为分类类型
df_clean["Sex"] = df_clean["Sex"].astype("category")

# 将数值型的"存活状态"(0=死亡,1=存活)转换为布尔类型
df_clean["Survived"] = df_clean["Survived"].astype(bool)

print(f"\n=== 数据类型优化后 ===")
print(df_clean.dtypes)

# 4. 验证清洗结果
print(f"\n=== 清洗结果验证 ===")
print("清洗后各字段缺失值统计:")
print(df_clean.isnull().sum())

# 5. 导出清洗后的数据(用于后续分析/建模)
df_clean.to_csv("code/Pandas/data/titanic_cleaned.csv", index=False)
print("\n清洗完成!数据已导出为titanic_cleaned.csv文件")

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐