《Python AI 入门》第2章 数据的力量——用Pandas与NumPy清洗“脏”数据
本章我们将掌握两把处理数据的瑞士军刀:NumPy 和 Pandas。它们是Python AI生态的基石。学会它们,你就不再是单纯的“写代码的”,而是能让数据乖乖听话的“数据工程师”
章节导语
“数据科学家80%的时间花在清洗和整理数据上,只有20%的时间在真正训练模型。剩下的时间呢?他们在抱怨数据太脏了。”
这是一个在AI行业流传已久的笑话,但它无比真实。
很多初学者以为AI开发就是不断地调用高大上的算法,但现实是:没有经过清洗的数据就是垃圾,而垃圾进,只能垃圾出(Garbage In, Garbage Out)。现实世界的数据充满了缺失值、拼写错误、异常值和莫名其妙的格式。如果直接把这些扔给神经网络,模型会立刻报错或者给出一个荒谬的结果。
本章我们将掌握两把处理数据的瑞士军刀:NumPy 和 Pandas。它们是Python AI生态的基石。学会它们,你就不再是单纯的“写代码的”,而是能让数据乖乖听话的“数据工程师”。
2.1 学习目标
在学完本章后,你将能够:
-
理解AI的数学基石:掌握NumPy数组及其核心的“广播机制”。
-
驾驭表格数据:熟练使用Pandas进行数据的读取、筛选、切片。
-
清洗脏数据:学会处理缺失值(NaN)、重复数据和格式错误。
-
工程思维进阶:理解为什么向量化运算比
for循环快100倍,并养成不写循环处理数据的习惯。 -
实战落地:完成一个电商销售数据的清洗与统计项目,从杂乱的日志中提取商业价值。
2.2 NumPy:让Python变身数学天才
Python原本处理数字列表的速度并不快,但AI(尤其是深度学习)需要进行海量的矩阵运算。NumPy(Numerical Python)通过在底层使用C语言优化,解决了这个问题。
2.2.1 数组(Array)与维度(Shape)
在AI里,你会反复听到一个词:Tensor(张量)。在NumPy里,它叫ndarray。别被名词吓到,它其实就是“多层列表”。
请在Jupyter Notebook或Python脚本中运行:
import numpy as np # 国际惯例,大家都叫它 np
# 1. 创建一个一维数组(向量)
vector = np.array([1, 2, 3])
print(f"向量: {vector}, 维度: {vector.shape}")
# 2. 创建一个二维数组(矩阵)—— 想象成 Excel 表格
matrix = np.array([
[1, 2, 3],
[4, 5, 6]
])
print(f"矩阵:\n{matrix}")
print(f"矩阵维度: {matrix.shape}") # 输出 (2, 3) 表示 2行 3列
【小白避坑】Shape的重要性 在后续学习PyTorch时,90%的报错都是“Shape Mismatch”(维度不匹配)。现在就开始养成习惯,拿到数据先打印
.shape看看它长什么样。
2.2.2 广播机制(Broadcasting):以少胜多的魔法
这是NumPy最天才的设计。当你让一个矩阵和一个数字相加时,NumPy会自动把这个数字“广播”到矩阵的每一个元素上。
# 假设这是 3 个学生的成绩
scores = np.array([60, 70, 80])
# 老师决定全员加 5 分
# 传统 Python 写法需要写循环,但在 NumPy 里:
new_scores = scores + 5
print(new_scores) # 输出: [65 75 85]
工程意义:这不仅写起来简单,而且底层并行计算,速度极快。在神经网络中,成千上万个神经元的偏置(Bias)相加,靠的就是这个机制。
2.3 Pandas:Python版的超级Excel
如果说NumPy是数学家,那Pandas就是数据分析师。它基于NumPy构建,专门用来处理表格数据。
2.3.1 DataFrame:你的核心工作台
Pandas的核心对象叫 DataFrame,你可以把它直接看作一张Excel表:有行索引(Index),有列名(Columns)。
import pandas as pd
# 手动创建一个 DataFrame
data = {
"姓名": ["张三", "李四", "王五"],
"年龄": [25, 30, 22],
"城市": ["北京", "上海", "深圳"]
}
df = pd.DataFrame(data)
print(df)
2.3.2 数据的“查户口”:读取与概览
在实际工作中,数据通常存储在CSV或Excel文件中。
# 伪代码,稍后我们在实战中生成真实文件
# df = pd.read_csv("data.csv")
# 拿到数据的第一件事:体检
# 1. 看前5行,确认数据长啥样
print(df.head())
# 2. 看宏观信息:有多少行?有哪些列?每一列是什么类型?是否存在空值?
print(df.info())
# 3. 看统计摘要:平均值、最大值、最小值(只对数值列有效)
print(df.describe())
【专业提示】
df.info()是排查“脏数据”的神器。如果你看到某列有 1000 行数据,但Non-Null Count只有 800,说明有 200 个缺失值;如果你看到“价格”这一列的类型是object(字符串)而不是float,说明里面可能混入了非数字字符。
2.4 工程思维:向量化 vs 循环
这是从“写脚本”进阶到“工程化”的分水岭。
假设你要计算两列数据的和:C列 = A列 + B列。
-
初学者做法(For循环): 逐行读取,逐个相加,再存回去。如果数据有100万行,这可能需要跑几分钟。
-
工程师做法(向量化): 直接操作整列。
# 向量化操作
df["总分"] = df["数学"] + df["英语"]
为什么? Pandas和NumPy底层使用了CPU的SIMD(单指令多数据)指令集。简单说,循环是一次搬一块砖,向量化是一次开一辆卡车搬砖。永远优先使用Pandas内置函数,尽量避免遍历DataFrame。
2.5 实战案例:电商销售数据清洗与分析
我们来模拟一个真实的业务场景。你是某电商公司的AI工程师,运营部门发给你一份销售日志,希望你统计上个月的GMV(商品交易总额)。
2.5.1 场景模拟:生成“脏”数据
为了让代码可运行,我们先编写一段脚本来生成一份包含“脏数据”的CSV文件。请直接运行以下代码:
import pandas as pd
import numpy as np
# 构造一份脏数据
raw_data = {
'order_id': ['1001', '1002', '1003', '1004', '1005', '1002'], # 注意 1002 是重复的
'product_name': ['Laptop', 'Mouse', 'Keyboard', np.nan, 'Monitor', 'Mouse'], # 有缺失值
'price': ['5000', '150', '300', '800', 'Not Available', '150'], # 混入了脏字符串
'quantity': [1, 2, 1, 1, 2, 2],
'date': ['2023-10-01', '2023-10-01', '2023-10-02', '2023-10-02', '2023-10-03', '2023-10-01']
}
df_raw = pd.DataFrame(raw_data)
# 保存为本地文件,模拟真实读取过程
df_raw.to_csv('sales_dirty.csv', index=False)
print("模拟数据已生成:sales_dirty.csv")
2.5.2 第一步:加载与初诊
# 1. 读取数据
df = pd.read_csv('sales_dirty.csv')
# 2. 查看问题
print("--- 原始数据预览 ---")
print(df)
print("\n--- 数据信息概览 ---")
print(df.info())
通过观察,我们发现三个严重问题:
-
order_id有重复(1002号订单出现了两次)。 -
product_name有空值(NaN)。 -
price列的类型是object,因为里面混入了一个 "Not Available" 字符串,导致无法进行数学计算。
2.5.3 第二步:清洗手术
# 1. 去除重复行
# keep='first' 表示保留第一次出现的,删掉后面重复的
df_clean = df.drop_duplicates(subset=['order_id'], keep='first')
# 2. 处理缺失值
# 对于商品名缺失,我们无法恢复,只能丢弃该行(或者标记为'Unknown')
# 这里选择丢弃任何包含空值的行
df_clean = df_clean.dropna(subset=['product_name'])
# 3. 清洗价格列
# 我们的目标是把 "Not Available" 变成数字,或者把这一行删掉
# 这是一个典型的逻辑:先强制转数字,无法转的变成 NaN,再处理 NaN
# errors='coerce' 意思是:遇到转不了的字符,强行把它变成 NaN (Not a Number)
df_clean['price'] = pd.to_numeric(df_clean['price'], errors='coerce')
# 现在我们可以看到 'Not Available' 变成了 NaN,再次把这些无效行删掉
df_clean = df_clean.dropna(subset=['price'])
print("\n--- 清洗后的数据 ---")
print(df_clean)
2.5.4 第三步:数据分析与计算
现在数据干净了,可以开始挖掘价值了。
# 1. 计算每单的总价
# 直接列与列相乘(向量化运算)
df_clean['total_amount'] = df_clean['price'] * df_clean['quantity']
# 2. 计算总 GMV
total_gmv = df_clean['total_amount'].sum()
# 3. 看看哪种商品卖得最好
top_product = df_clean.groupby('product_name')['quantity'].sum().idxmax()
print(f"\n清洗后的总GMV: {total_gmv}")
print(f"最畅销的商品是: {top_product}")
输出结果应类似:
清洗后的总GMV: 5600.0 最畅销的商品是: Mouse
【小白避坑】 注意 Pandas 的很多操作(如
dropna,drop_duplicates)默认是返回一个新的 DataFrame,而不会修改原始数据。 如果你想修改原始数据,需要加上参数inplace=True,或者像上面代码那样赋值给变量:df = df.dropna()。初学者常犯的错误是写了df.dropna()却发现df一点没变。
2.6 章节小结
本章我们跨越了AI入门的第一道坎:数据处理。
-
我们用 NumPy 了解了数组和维度,这是计算机视觉处理图片的基础。
-
我们用 Pandas 完成了从“读取”到“清洗”再到“分析”的全流程。
-
我们学会了用向量化的思维去处理数据,而不是写慢吞吞的
for循环。
现在的你,已经具备了处理 Excel 无法胜任的大规模数据集的能力。下一章,我们将引入视觉元素,用 Matplotlib 和 Seaborn 把这些枯燥的数据画成漂亮的图表,让数据自己“说话”。
2.7 思考与扩展练习
-
实战挑战: 在电商数据中,日期列
提示:转换后可以使用date目前还是字符串类型。请查阅 Pandas 文档,使用pd.to_datetime()将其转换为日期对象,并提取出每个订单是“星期几”生成的。df['date'].dt.day_name()。 -
筛选练习: 尝试筛选出所有单价(price)大于 1000 且数量(quantity)大于 1 的订单。
-
思考题: 在清洗价格时,我们直接删除了 "Not Available" 的行。在实际业务中,除了直接删除,还有什么办法处理缺失的数据?(例如:用平均价填充?)请思考这种做法在什么场景下是合理的,什么场景下是危险的。
更多推荐




所有评论(0)