当前位置: 首页 > news >正文

Pandas 高效数据处理:apply、向量化与分组

Pandas 高效数据处理:apply、向量化与分组进阶实战(附代码示例)

  • 适用人群: 想系统掌握 Pandas 自定义计算、性能优化、分组聚合与转换的同学
  • 核心要点: apply 的行列处理、真正向量化 vs 伪向量化、GroupBy 的聚合/转换/apply 全景案例

一、为什么需要这些技术

  • apply: 用自定义函数批量处理 Series/DataFrame/GroupBy,替代显式 for 循环。
  • 向量化: 利用底层 C/NumPy 实现的批处理(极快);np.vectorize 提供向量化接口但本质仍是循环(伪向量化)。
  • 分组进阶: 统计、对齐转换(transform 类似 SQL 窗口函数)、组级过滤、自定义 apply。

二、apply 入门与典型用法

1)对 Series:逐元素

“”"
apply函数是pandas中自由度(自定义)最高的函数之一,用来对series、dataframe或者分组对象应用自定义函数,他的核心行为是:
1:对series,逐个元素进行处理(输入单个值,输出单个值)
“”"

import pandas as pdprint("----------对series中使用apply--------------")
def my_fun1(x):return x ** 2s = pd.Series([1,2,3,4])
r1 = s.apply(my_fun1)
  • 也可传参:
def my_fun2(x, e):return x ** er2 = s.apply(my_fun2, e=3)

2)对 DataFrame:按行或按列传入 Series

print("----------对dataframe中使用apply--------------")
df = pd.DataFrame({'a':[10,20,30], 'b': [20,30,40]})
def my_fun3(x):print(f"x的内容:\n{x}")print(f"x的类型:{type(x)}")df.apply(my_fun3, axis=1)   # axis=1 按“行”传入 Series
  • 误区提示:函数签名需与传入对象匹配(行/列 Series),否则会报参不匹配错误。
df = pd.read_csv("data/titanic_train.csv")
def count_missing(vec):return pd.isnull(vec).sum()
def prop_missing(vec):return pd.isnull(vec).sum() / vec.size
def prop_complete(vec):return 1-prop_missing(vec)print(df.apply(count_missing))             # 按列
print(df.apply(prop_missing))
print(df.apply(prop_complete))
print(df.apply(count_missing, axis=1))     # 按行

要点:

  • axis=0(默认)按列;axis=1 按行。
  • 行列粒度输出分别用于字段健康度与行级质量检查。

三、真正向量化 vs 伪向量化(np.vectorize)

教程总结要点如下:
“”"
真正的向量化:底层C/NumPy实现,性能极高,语法简洁,广泛覆盖数学/统计/字符串/日期等。
np.vectorize:伪向量化,内部仍是python循环,接口友好但性能远逊真·向量化。
apply:最灵活,但性能最低。
性能:向量化函数>伪向量化函数>apply(自定义函数)
“”"

- 真·向量化示例(列运算、标量运算、NumPy 通用函数):- `df['C'] = df['A'] + df['B']`- `df['D'] = df['A'] * 10`- `df['E'] = np.log(df['A'])`- `np.vectorize` 适用场景:- 自定义标量函数、多分支复杂逻辑,或多参数且需固定部分参数时。- 注意:它不是性能优化的“银弹”,只是让写法像向量化。实践建议:
- 能用真·向量化就不要用 apply/np.vectorize。
- 需要强自定义且无等价向量化方案时,再考虑 `np.vectorize` 或 `apply`。---## 四、GroupBy 分组进阶:聚合、转换、应用### 1)概念全景
"""
分组:groupby();按列/函数/索引分组
聚合:agg()/aggregate()
转换:transform() 返回与原始数据同大小(组内对齐)
过滤:filter() 基于组属性筛组
应用:apply() 对组DataFrame做任意处理
"""

2)使用 Gapminder 数据做统计实践

df = pd.read_csv("data/gapminder.tsv", sep="\t")
df.groupby("year")
df.groupby(["year", "continent"])
print(df.groupby("year").lifeExp.mean())
print(df.groupby("year")['lifeExp'].mean())
  • 常用描述统计:
print(df.groupby("continent").lifeExp.count())
print(df.groupby("continent").lifeExp.describe())
print(df.groupby("continent").lifeExp.agg(lambda x: np.mean(x)))
  • 结合全局值做组内“差值”分析(传参 + 自定义聚合):
global_lifeExp_mean = df.lifeExp.mean()
def my_mean_diff(col, lifeExp_mean):return col.mean() - lifeExp_mean
print(df.groupby("continent").lifeExp.agg(my_mean_diff, lifeExp_mean=global_lifeExp_mean))
  • 一次性对不同列做不同聚合并改列名:
print(df.groupby("year").agg({'lifeExp':'mean','pop':'max','gdpPercap':'min'
}).rename(columns={'lifeExp':'平均寿命', 'pop':'最大人口', 'gdpPercap':'人均最小GDP'}).reset_index())

3)转换 transform:组内对齐输出(窗口函数思维)

计算 Z-Score(标准分数)并按年分组,结果与原数据等长、可直接对齐赋值:

def my_zscore(x):return (x - x.mean()) / x.std()
print(df.groupby('year').lifeExp.transform(my_zscore))

4)小案例:按性别组均值填充消费总额缺失值

tops_10_df = pd.read_csv("data/tips.csv").sample(n=10, random_state=20)
tops_10_df.loc[np.random.permutation(tops_10_df.index)[:4], 'total_bill'] = np.NaNdef my_fillna(x):return x.fillna(x.mean())r1 = tops_10_df.groupby('sex').total_bill.transform(my_fillna)
  • 思路:按 sex 分组 → 对每组 total_bill 用组均值填充 → transform 保持原长度,直接对齐回写到原列,避免 merge。

五、选型建议与最佳实践

  • 优先顺序(速度):真正向量化 > np.vectorize(伪) > apply
  • apply 何时用
    • 需要高度灵活的自定义逻辑,且难以映射为向量化表达式
    • 分组后的整组 DataFrame 级复杂处理
  • transform 常用场景
    • 需要与原表逐行对齐输出(标准化、组均值填充、组排名、比值偏差等)
  • 性能注意
    • 尽量减少 Python 层循环;多利用 Pandas/NumPy 内建函数与表达式
    • 多列多指标聚合用 agg(dict) 一次完成,减少多次扫描
  • 可读性
    • 分组链式写法建议 .groupby(...).agg(...).rename(...).reset_index(),用于清晰输出

六、可直接复用的模板片段

  • 组内 Z-Score 并对齐:
df['lifeExp_z'] = df.groupby('year')['lifeExp'].transform(lambda x: (x - x.mean())/x.std())
  • 多列多指标聚合:
out = df.groupby('year').agg({'lifeExp':'mean','pop':'max','gdpPercap':'min'
}).rename(columns={'lifeExp':'平均寿命','pop':'最大人口','gdpPercap':'人均最小GDP'}).reset_index()
  • 组均值缺失值填充:
df['total_bill'] = df.groupby('sex')['total_bill'].transform(lambda x: x.fillna(x.mean()))

七、结语

本文系统梳理了 Pandas 的 apply、向量化与分组进阶技巧,并通过 gapminder 与 tips 两个数据集展示了典型统计与缺失值处理套路。建议在项目中优先考虑“真·向量化 + groupby/transform”,在必须强自定义时再回退到 np.vectorizeapply

更新日期:2025年8月25日,后续会持续更新

http://www.dtcms.com/a/350128.html

相关文章:

  • Qt——多媒体(音频、视频播放)
  • 艾利特石油管道巡检机器人:工业安全的智能守护者
  • 系统数据库
  • WRC2025 | 澳鹏亮相2025世界机器人大会,以数据之力赋能具身智能新纪元
  • 2025年9月计算机二级C++语言程序设计——选择题打卡Day6
  • 神经网络模型搭建及手写数字识别案例
  • 关于“程序=数据结构+算法”的深层认识
  • Java图形图像处理【双缓冲技术与游戏】【九】
  • Java全栈开发面试实战:从基础到微服务的深度解析
  • IDEA2022开启新版UI
  • 系统架构设计师备考第4天——计算机软件概述操作系统
  • Aligning Effective Tokens with Video Anomaly in Large Language Models
  • 储能防逆流:智能守护电网稳定的核心技术
  • 大数据毕业设计选题推荐-基于大数据的餐饮服务许可证数据可视化分析系统-Spark-Hadoop-Bigdata
  • 阿里云OSS文件上传_对象存储服务全流程
  • Android横竖屏切换的“数据保卫战”:如何优雅地保存和恢复表单数据
  • 用 python 开发一个可调用工具的 AI Agent,实现电脑配置专业评价_python ai agent
  • 常见前端性能优化讲解
  • 在分布式计算区域中通过VPC搭建私有网络
  • Ansible 任务控制与事实管理指南:从事实收集到任务流程掌控
  • Hadoop(四)
  • 【GPT入门】第59课 大模型内存计算指南:7B/8B/70B 模型在 32/16/8/4bit 精度下的内存需求测算
  • 【GPT5的多个子模型和动态路由分别是什么?】
  • 深度学习分类网络初篇
  • AI与自动化工具对比与选择
  • Coze用户账号设置修改用户密码-前端源码
  • 用一根“数据中枢神经”串起业务从事件流到 Apache Kafka
  • Flume中常见的易错的问题
  • Linux应用软件编程---网络编程(TCP:[ 其他机制、头部标志位、应用示例 ]、 HTTP:[ 万维网、概念、格式、报文、应用示例 ]
  • LoRA 微调后幻觉排查 Checklist