Pandas:数据处理与分析
AI 项目 80% 的时间花在数据处理上。Pandas 是处理表格数据的利器,从数据清洗到特征工程,它是 AI 数据管道的核心工具。
DataFrame —— 表格数据的核心
Pandas 最重要的结构是 DataFrame,本质上是一张带有行索引和列标签的二维表格,就像 Excel 表格,但能处理百万级数据且可编程。每一列是一个 Series。
DataFrame vs NumPy 数组
NumPy 数组的列是匿名的数字索引,所有数据必须同类型。DataFrame 的列有名字,不同列可以有不同类型(年龄是 int,姓名是 str,分数是 float)。这让它非常适合处理真实的 AI 训练数据集。
import pandas as pd
import numpy as np
# 从字典创建(最常用)
df = pd.DataFrame({
"样本ID": ["s001", "s002", "s003", "s004"],
"年龄": [25, 30, None, 22], # None = 缺失值
"收入": [5000, 8000, 6000, 4500],
"标签": [1, 0, 1, 0],
})
# 查看基本信息
print(df) # 打印整张表
print(df.shape) # (4, 4) → 4行4列
print(df.dtypes) # 各列的数据类型
print(df.info()) # 完整信息,含非空值数量
print(df.describe()) # 数值列的统计摘要(均值、标准差等)
# 从 CSV 读取(实际项目最常见)
df = pd.read_csv("train_data.csv")
df.to_csv("output.csv", index=False) # 保存,不写行号
# 前/后几行预览
print(df.head(5)) # 前5行
print(df.tail(3)) # 后3行
print(df.sample(3)) # 随机3行
选取数据:loc 和 iloc
Pandas 有两种主要的数据选取方式:loc 按标签选取,iloc 按整数位置选取。分清这两者,是使用 Pandas 的关键。
df = pd.DataFrame({
"feature1": [0.1, 0.5, 0.3, 0.8],
"feature2": [1.2, 2.3, 0.9, 3.1],
"label": [0, 1, 0, 1]
})
# 选取列(单列返回 Series,多列返回 DataFrame)
labels = df["label"] # Series
features = df[["feature1", "feature2"]] # DataFrame
# loc:按标签选取行列
print(df.loc[0]) # 第0行(行索引是整数时)
print(df.loc[0:2]) # 第0-2行(包含第2行!)
print(df.loc[0, "feature1"]) # 第0行 feature1 列
# iloc:按整数位置选取
print(df.iloc[0]) # 第0行
print(df.iloc[:2, :2]) # 前2行前2列
print(df.iloc[-1]) # 最后一行
# 条件筛选(最常用!)
positive = df[df["label"] == 1] # 所有正样本
high_feat = df[df["feature2"] > 2.0] # feature2 > 2 的行
multi = df[(df["label"]==1) & (df["feature1"]>0.4)]
print(positive)
数据清洗
真实数据总是"脏的"——有缺失值、重复行、异常值。在送入模型前必须清洗,否则会严重影响训练效果。"垃圾进,垃圾出(Garbage In, Garbage Out)"是 AI 领域的著名定律。
# 检查缺失值
print(df.isnull().sum()) # 每列缺失值数量
print(df.isnull().sum() / len(df)) # 缺失比例
# 处理缺失值
df_drop = df.dropna() # 删除含缺失值的行
df_fill = df.fillna(0) # 用0填充所有缺失值
# 按列填充(更好的做法)
df["年龄"] = df["年龄"].fillna(df["年龄"].mean()) # 用均值填充
df["类别"] = df["类别"].fillna(df["类别"].mode()[0]) # 用众数填充
df["值"] = df["值"].fillna(method="ffill") # 前向填充
# 删除重复行
df = df.drop_duplicates()
df = df.drop_duplicates(subset=["样本ID"]) # 按指定列去重
# 处理异常值(基于 3σ 原则)
col = "收入"
mean, std = df[col].mean(), df[col].std()
df = df[(df[col] >= mean - 3 * std) &
(df[col] <= mean + 3 * std)]
# 重置行索引
df = df.reset_index(drop=True)
特征工程
特征工程是将原始数据转换为模型能更好学习的格式。好的特征工程常常比换一个更复杂的模型效果更显著。
# 1. 数值归一化(Min-Max Scaling)
for col in ["年龄", "收入"]:
min_v = df[col].min()
max_v = df[col].max()
df[col] = (df[col] - min_v) / (max_v - min_v)
# 2. 类别编码(One-Hot Encoding)
df = pd.get_dummies(df, columns=["城市"], prefix="city")
# "北京", "上海", "广州" → city_北京, city_上海, city_广州(0或1)
# 3. 标签编码(Label Encoding)
df["性别_num"] = df["性别"].map({"男": 0, "女": 1})
# 4. 创建新特征(组合特征)
df["收入/年龄"] = df["收入"] / df["年龄"]
df["高收入"] = (df["收入"] > 0.7).astype(int)
# 5. 时间特征提取
df["日期"] = pd.to_datetime(df["日期"])
df["月份"] = df["日期"].dt.month
df["星期"] = df["日期"].dt.dayofweek
df["是否周末"] = (df["星期"] >= 5).astype(int)
特征工程的黄金法则
神经网络理论上能自动学习特征,但提供好的特征仍然有帮助。对于结构化数据(表格),特征工程是关键。对于图像和文本,通常让模型自己学。pd.get_dummies() 是处理类别变量最常用的方法,面试必考。
groupby —— 分组聚合
groupby 是 Pandas 最强大的功能之一,类似 SQL 的 GROUP BY:按某列分组,再对每组做统计。在 AI 中用于按类别分析数据分布是否均衡。
df = pd.DataFrame({
"类别": ["猫", "狗", "猫", "狗", "鸟", "鸟"],
"得分": [0.8, 0.6, 0.9, 0.7, 0.5, 0.55],
"置信度": [0.9, 0.7, 0.85, 0.75, 0.6, 0.65],
})
# 按类别分组,计算各列均值
print(df.groupby("类别").mean())
# 多种聚合函数同时计算
summary = df.groupby("类别")["得分"].agg(["mean", "std", "count"])
print(summary)
# 查看类别分布(AI 中用于检查数据是否均衡)
print(df["类别"].value_counts())
print(df["类别"].value_counts(normalize=True)) # 百分比
# 相关性分析(特征选择)
print(df.corr()) # 各数值列之间的相关系数矩阵
综合示例:完整数据预处理流程
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
# 1. 加载数据
df = pd.read_csv("titanic.csv")
print(f"原始数据: {df.shape}")
# 2. 查看缺失情况
print(df.isnull().sum())
# 3. 清洗
df["Age"] = df["Age"].fillna(df["Age"].median())
df["Embarked"] = df["Embarked"].fillna(df["Embarked"].mode()[0])
df = df.drop(columns=["Cabin", "Ticket", "Name", "PassengerId"])
# 4. 特征工程
df["Sex"] = df["Sex"].map({"male": 0, "female": 1})
df = pd.get_dummies(df, columns=["Embarked"])
df["FamilySize"] = df["SibSp"] + df["Parch"] + 1
# 5. 分离特征和标签
X = df.drop(columns=["Survived"])
y = df["Survived"]
# 6. 切分训练集测试集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
print(f"训练集: {X_train.shape}, 测试集: {X_test.shape}")
print(f"正负样本比: {y_train.mean():.2%}")
这是 Kaggle 竞赛的标准流程
上面的泰坦尼克号数据集是机器学习入门的"Hello World"。这个预处理流程——读取→清洗→特征工程→切分——在几乎所有结构化数据的 AI 项目中都适用。