【机器学习】7 个 Pandas 技巧,提升你的机器学习模型开发效率
【精选优质专栏推荐】
- 《AI 技术前沿》 —— 紧跟 AI 最新趋势与应用
- 《网络安全新手快速入门(附漏洞挖掘案例)》 —— 零基础安全入门必看
- 《BurpSuite 入门教程(附实战图文)》 —— 渗透测试必备工具详解
- 《网安渗透工具使用教程(全)》 —— 一站式工具手册
- 《CTF 新手入门实战教程》 —— 从题目讲解到实战技巧
- 《前后端项目开发(新手必知必会)》 —— 实战驱动快速上手
每个专栏均配有案例与图文讲解,循序渐进,适合新手与进阶学习者,欢迎订阅。
文章目录

引言
如果你正在阅读这篇文章,很可能你已经意识到,机器学习模型的性能不仅取决于所选算法,还高度依赖模型训练数据的质量和表现形式。
数据预处理和特征工程是机器学习工作流程中最关键的步骤之一。在 Python 生态中,Pandas 是进行这类数据操作的首选库。掌握几个实用的 Pandas 数据转换技巧,可以显著优化你的工作流程,使代码更清晰高效,并最终提升模型表现。
本教程将通过七个实际场景演示 Pandas 技巧,帮助你在数据准备和特征工程环节提高效率,为下一个机器学习项目打下良好基础。
准备数据
为了演示这些技巧,我们将使用经典的 Titanic 数据集。这个数据集包含数值型和类别型数据,同时存在缺失值,这些都是现实机器学习任务中常见的挑战。
我们可以直接从 URL 将数据集加载到 Pandas DataFrame 中:
import pandas as pd
import numpy as np
# 从 URL 加载 Titanic 数据集
url = "https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv"
df = pd.read_csv(url)
# 输出数据集形状及前 5 行
print("Dataset shape:", df.shape)
print(df.head())
输出示例:
Dataset shape: (891, 12)
PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
0 1 0 3 Braund, Mr. Owen Harris male 22.0 1 0 A/5 21171 7.2500 NaN S
1 2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Th... female 38.0 1 0 PC 17599 71.2833 C85 C
2 3 1 3 Heikkinen, Miss. Laina female 26.0 0 0 STON/O2. 3101282 7.9250 NaN S
3 4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35.0 1 0 113803 53.1000 C123 S
4 5 0 3 Allen, Mr. William Henry male 35.0 0 0 373450 8.0500 NaN S
我们得到一个包含列如 Survived(目标变量)、Pclass(乘客等级)、Sex、Age 等的 DataFrame。
下面将介绍使用 Pandas 的实用技巧。
1. 使用 query() 实现更清晰的数据过滤
数据过滤是一个永无止境的任务,无论是为了创建训练子集,还是探索特定数据片段。使用布尔索引进行标准过滤在条件较多时容易变得冗长且难以阅读。query() 方法提供了更直观、更易读的替代方案,可通过字符串表达式进行过滤。
标准过滤
# 过滤年龄大于 30 且属于一等舱且存活的乘客
filtered_df = df[(df['Pclass'] == 1) & (df['Age'] > 30) & (df['Survived'] == 1)]
print(filtered_df.head())
使用 query() 过滤
# 使用 query() 方法实现同样的过滤
query_df = df.query('Pclass == 1 and Age > 30 and Survived == 1')
print(query_df.head())
输出结果相同,但 query() 版本更清晰易读,尤其是条件增多时。
此外,query() 支持变量传入,使得过滤条件动态化更简单,例如:
age_threshold = 30
query_df = df.query('Pclass == 1 and Age > @age_threshold and Survived == 1')
这种方式可避免在多处修改代码时出现重复或错误。
2. 使用 cut() 对连续变量进行分箱
某些模型(如线性模型和决策树)在将连续变量离散化后可以更好地捕捉非线性关系。可以使用 pd.cut() 将数据分入自定义区间,例如将年龄分组:
bins = [0, 12, 18, 60, np.inf]
labels = ['Child', 'Teenager', 'Adult', 'Senior']
df['AgeGroup'] = pd.cut(df['Age'], bins=bins, labels=labels, right=False)
print(df['AgeGroup'].value_counts())
输出示例:
Adult 575
Child 68
Teenager 45
Senior 26
新的 AgeGroup 特征是一个强有力的类别变量,可供模型使用。
此外,pd.cut() 可以设置 right=False 或 right=True 来控制区间是否包含右端点,还可以通过 include_lowest=True 确保最小值包含在第一个区间。对连续变量的分箱还能生成哑变量,便于模型处理分类特征:
df = pd.get_dummies(df, columns=['AgeGroup'], prefix='AgeGroup')
3. 使用 .str 提取文本特征
文本列通常包含有价值的结构化信息。.str 访问器提供一系列适用于整个 Series 的字符串处理方法。比如,我们可以用正则表达式从 Name 列提取乘客称谓(如 ‘Mr.’、‘Miss.’、‘Dr.’):
df['Title'] = df['Name'].str.extract(' ([A-Za-z]+)\.', expand=False)
print(df['Title'].value_counts())
输出示例:
Mr 517
Miss 182
Mrs 125
Master 40
Dr 7
...
Title 特征在 Titanic 模型中常常是生存率的重要预测指标。
除此之外,.str 还能实现其他文本操作,如:
.str.lower()或.str.upper()转换大小写.str.strip()去除前后空格.str.contains('pattern')检查是否匹配模式.str.replace('old','new')替换文本
这些方法在处理姓名、票号、船舱号等文本字段时非常实用。
4. 使用 transform() 进行高级填充
直接删除缺失值会导致数据损失。更好的策略是分组填充。例如,按 Pclass 填充 Age 缺失值:
median_age_by_pclass = df.groupby('Pclass')['Age'].transform('median')
df['Age'].fillna(median_age_by_pclass, inplace=True)
print("Missing Age values after imputation:", df['Age'].isnull().sum())
输出:
Missing Age values after imputation: 0
这种基于分组的填充通常比全局平均值更准确。
另外,transform() 也可配合 lambda 函数 或自定义函数实现更灵活的填充策略,例如按性别和舱位组合计算中位数:
df['Age'] = df.groupby(['Pclass', 'Sex'])['Age'].transform(lambda x: x.fillna(x.median()))
此方法可保持分组内部的特征一致性,尤其在不同类别之间年龄差异明显时非常有效。
5. 使用方法链和 pipe() 简化流程
机器学习预处理通常涉及多步操作。链式调用可以提高代码可读性,并避免产生不必要的中间 DataFrame。pipe() 方法进一步允许将自定义函数集成到链中。
# 自定义函数删除列
def drop_cols(df, cols_to_drop):
return df.drop(columns=cols_to_drop)
# 自定义函数编码 Sex 列
def encode_sex(df):
df['Sex'] = df['Sex'].map({'male': 0, 'female': 1})
return df
# 创建链式管道
processed_df = (df.copy()
.pipe(drop_cols, cols_to_drop=['Ticket', 'Cabin', 'Name'])
.pipe(encode_sex)
)
print(processed_df.head())
输出示例:
PassengerId Survived Pclass Sex Age SibSp Parch Fare Embarked AgeGroup Title
0 1 0 3 0 22.0 1 0 7.2500 S Adult Mr
1 2 1 1 1 38.0 1 0 71.2833 C Adult Mrs
2 3 1 3 1 26.0 0 0 7.9250 S Adult Miss
3 4 1 1 1 35.0 1 0 53.1000 S Adult Mrs
4 5 0 3 0 35.0 0 0 8.0500 S Adult Mr
使用 pipe() 可以轻松将任意自定义处理函数加入链条中,使得整个数据处理流程更模块化、可读性更强,也便于团队协作与代码复用。
此外,方法链还可结合 assign()、dropna()、sort_values() 等 Pandas 方法,实现一步到位的数据清洗、特征生成和排序操作。
例如:
processed_df = (df.copy()
.assign(Fare_scaled = lambda x: x['Fare']/x['Fare'].max())
.pipe(drop_cols, cols_to_drop=['Ticket', 'Cabin', 'Name'])
.pipe(encode_sex)
.sort_values(by='Age', ascending=True)
)
这样就可以在一条链中完成标准化、删除列、编码和排序操作,保持代码整洁高效。
6. 使用 map() 高效映射有序类别
对于名义型类别,通常使用独热编码(one-hot encoding);但对于有序类别(ordinal data),更适合将其映射为整数。使用字典和 map() 方法是快速而明确的方式。比如,我们假设 Embarked 有顺序关系:S > C > Q。
# 假设 Embarked 顺序为 S > C > Q
embarked_mapping = {'S': 2, 'C': 1, 'Q': 0}
df['Embarked_mapped'] = df['Embarked'].map(embarked_mapping)
print(df[['Embarked', 'Embarked_mapped']].head())
输出示例:
Embarked Embarked_mapped
0 S 2.0
1 C 1.0
2 S 2.0
3 S 2.0
4 S 2.0
这种方法快速、明确,便于模型学习类别间的顺序关系。
此外,map() 也可结合 fillna() 实现对缺失值的补充:
df['Embarked_mapped'] = df['Embarked'].map(embarked_mapping).fillna(-1)
7. 使用 astype() 优化内存
在处理大型数据集时,内存占用可能成为瓶颈。Pandas 默认使用较大数据类型(如 int64 和 float64),但通常可以使用较小类型而不丢失信息。将 object 类型转换为 category 是一种常用方法。
# 查看原始内存占用
print("Original memory usage:")
print(df.info(memory_usage='deep'))
# 优化数据类型
df_optimized = df.copy()
df_optimized['Pclass'] = df_optimized['Pclass'].astype('int8')
df_optimized['Sex'] = df_optimized['Sex'].astype('category')
df_optimized['Age'] = df_optimized['Age'].astype('float32')
df_optimized['Embarked'] = df_optimized['Embarked'].astype('category')
# 查看优化后内存占用
print("\nOptimized memory usage:")
print(df_optimized.info(memory_usage='deep'))
优化效果显著,可以在大数据集上训练模型而不易崩溃。
另外,astype() 也可以用于批量优化类型,例如:
categorical_cols = ['Sex', 'Embarked', 'AgeGroup', 'Title']
for col in categorical_cols:
df_optimized[col] = df_optimized[col].astype('category')
这种批量处理在列较多时非常高效。
总结
机器学习的成功始于高质量、充分准备的数据。尽管算法复杂度、超参数调优以及模型构建常常成为关注焦点,但高效的数据处理才是发挥模型真正威力的关键。
本文介绍的七个 Pandas 技巧不仅是编程捷径,更是清洗数据、工程特征、构建稳健、可复现模型的强大策略。通过熟练掌握这些方法,你的机器学习工作流将更加高效、可维护,并有助于提升模型表现。
额外扩展建议:
- 将上述技巧与 scikit-learn 的 Pipeline 相结合,实现端到端自动化数据预处理。
- 对缺失值、异常值和类别分布进行可视化分析,提前发现数据问题。
- 在大数据环境下,可考虑 Dask 或 Modin 等库,实现分布式、高效的 Pandas 操作。
更多推荐



所有评论(0)