Pandas:如何让你的代码性能飙升
在数据分析相关的工作中,Pandas无疑是一个强大的工具,它的易用性和灵活性广受青睐。
然而,随着数据量的不断增长和计算需求的日益复杂,Pandas代码的性能问题也逐渐浮出水面。
如何让Pandas代码运行得更快、更高效,成为了每一个人使用者都需要面对的挑战。
今天,本文就一个简化版的实际分析案例,来一起探讨Pandas代码如何写才能性能更好,让你的数据处理流程更加顺滑,不再为漫长的等待运行而烦恼。
1. 案例介绍
假设有个股票分析的场景,我们需要给所有的股票每天的交易情况做一个评估,评估的结果有3个级别:优,中,差。
其中,“优”的条件是当天成交额大于10亿且收盘价大于开盘价,也就是股票上涨;
“差”的条件是当天成交额小于1亿且收盘价小于开盘价,也就是股票下跌;
除此之外的情况就是“中”。
再次强调一下,这是一个简化的评估方法,主要是为了下面演示Pandas的代码性能,真实的评估不会如此粗糙。
股票交易的数据来自A股2024年1,2月份的日交易数据,大约20多万条。
数据可从地址 https://databook.top/stock/2024 下载。
导入数据:
import pandas as pd
# 这个路径根据实际情况修改
fp = r'D:\data\2024\历史行情数据-东财-不复权-2024.csv'
df = pd.read_csv(fp)
df = df.loc[:, ["股票代码", "日期", "开盘", "收盘", "最高", "最低", "成交量"]]
df

2. 不同写法的性能比较
下面是3种代码的写法都是基于pandas的,完成的功能也是一样的。
2.1. 循环遍历
给每条数据加一个评估的指标,最直接想到的方法就是遍历所有的数据,然后根据每条数据的情况,
给予一个评估指标(优,中,差)。
首先,封装一个评估一条数据的函数:
def eval_stock(row):
"""
评估一条的数据
"""
# 成交额
volumn = row["收盘"] * row["成交量"]
if volumn > 1_000_000_000 and row["收盘"] > row["开盘"]:
return "优"
if volumn < 100_000_000 and row["收盘"] < row["开盘"]:
return "差"
return "中"
然后用遍历的方式评估我们准备的数据(A股2024年1,2月份的日交易数据)。
for idx, row in df.iterrows():
df.loc[idx, "评估"] = eval_stock(row)
df

虽然只有20多万条数据,但是执行时间还挺长的,在jupyter notebook 中用 %%timeit 魔法函数测试性能如下。
%%timeit
for idx, row in df.iterrows():
df.loc[idx, "评估"] = eval_stock(row)
运行结果:
36.4 s ± 367 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
执行一次要36秒多,效率很低。
2.2. apply方法
apply方法是pandas提供的一种灵活处理数据的接口,它允许我们传入一个自定义函数来处理数据。
下面我们看看这种方式的性能如何。
%%timeit
df["评估"] = df.apply(eval_stock, axis=1)
运行结果:
4.9 s ± 86.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
性能提升非常明显(36.4秒->4.9秒),代码也变得更加简洁。
2.3. 向量化方法
最后,我们看看终极的写法,这种写法把pandas的数据结构DataFrame看成是一个一维的向量数组(每列一个向量),而不是一个二维的数值数组。
这样,我们操作数据是以列为单位来操作,看看这样写的性能如何:
%%timeit
df["评估"] = "中"
df.loc[
(df["收盘"] * df["成交量"] > 1_000_000_000) & (df["收盘"] > df["开盘"]),
"评估",
] = "优"
df.loc[
(df["收盘"] * df["成交量"] < 100_000_000) & (df["收盘"] < df["开盘"]), "评估"
] = "差"
运行结果:
8.22 ms ± 434 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
运行时间几乎可以忽略不计。
3. 总结
同样使用pandas写数据分析的代码,性能差距居然会如此天差地别。
可见,学习pandas,不仅仅是学习它的各种接口和函数,
更重要的是了解从pandas执行的角度应该如何看待数据,是把数据看成一个一个独立的值,还是一行一行或一列一列的向量。
只有这样,才能用pandas高效的处理数据,这在数据量膨胀之后,会大大提高我们分析的效率。
Pandas:如何让你的代码性能飙升的更多相关文章
- Visual Studio Entity Framework (EF) 生成SQL 代码 性能查询
Visual Studio Entity Framework (EF) 生成SQL 代码 性能查询 SQL 中,有SQL Server Profiler可以用来查询性能以及查看外部调用的SQL ...
- 10条建议提高PHP代码性能
这篇文章中的建议涵盖了大部分PHP代码性能方面的问题.如果你是做一些小网站或者小项目,那么有理由忽略这些建议,但是当你为大量用户提供长期稳定的服务的时候,就必须关注了.开发人员必须从项目一开始就考虑这 ...
- 11个Visual Studio代码性能分析工具
软件开发中的性能优化对程序员来说是一个非常重要的问题.一个小问题可能成为一个大的系统的瓶颈.但是对于程序员来说,通过自身去优化代码是十分困难的.幸运的是,有一些非常棒的工具可以帮助程序员进行代码分析和 ...
- Python 代码性能优化技巧(转)
原文:Python 代码性能优化技巧 Python 代码优化常见技巧 代码优化能够让程序运行更快,它是在不改变程序运行结果的情况下使得程序的运行效率更高,根据 80/20 原则,实现程序的重构.优化. ...
- JavaScript代码性能优化总结
JavaScript 代码性能优化总结 尽量使用源生方法 javaScript是解释性语言,相比编译性语言执行速度要慢.浏览器已经实现的方法,就不要再去实现一遍了.另外,浏览器已经实现的方法在算法方面 ...
- .NET : 使用代码性能分析工具
NET : CLR Profiler的使用 经常讲课的时候会提到值类型和引用类型,也会提到如何查看它们的大小.多次被朋友问到,如何真的想要知道到底每个方法分配了多少内存之类的问题,其实这可以通过CLR ...
- 干货 | 云智慧透视宝Java代码性能监控实现原理
这篇图文并茂,高端大气上档次,思维缜密的文章,一看就和我平时的风格不同.对了.这不是我写的,是我家高大英俊,写一手好代码,做一手好菜的男神老公的大作,曾发表于技术公号,经本人授权转载~~ 一.Java ...
- js代码性能优化的几个方法
相信写代码对于大部分人都不难,但想写出高性能的代码就需要一定的技术积累啦,下面是一些优化JavaScript代码性能的常见方法. 一.注意作用域 1.避免全局查找 使用全局变量和函数肯定要比局部的开销 ...
- .NET 11 个 Visual Studio 代码性能分析工具
原文地址 软件开发中的性能优化对程序员来说是一个非常重要的问题.一个小问题可能成为一个大的系统的瓶颈.但是对于程序员来说,通过自身去优化代码是十分困难的.幸运的是,有一些非常棒的工具可以帮助程序员进行 ...
- vs2013查看代码性能后删除保存的性能查看文件导致再打开提示未找到与约束匹配的导出
1.关闭VS: 2.删除C:/Users//AppData/Local/Microsoft/VisualStudio/12.0/ComponentModelCache文件夹下所有文件及文件夹: 3.重 ...
随机推荐
- java的char类型,只有两个字节,为什么可以存储汉字?java中 char详解
我自己出了一道面试题,如下: public static void main(String[] args) { char a = '9'; char b = 9; char c = '我'; Syst ...
- MySQL 将执行结果保存到文件
1. 使用mysql的tee命令记录对mysql的操作过程 (1)第一种情况是在连接数据库的时候使用tee >mysql -u root -p --tee=C:/log.txt ...
- CentOS7环境下编译FFmpeg
操作系统:CentOS 7.6.1810_x64 ffmpeg版本:4.2.1 ffmpeg是一个功能非常强大的音视频处理工具,很多软件依赖它,这里记录下编译过程,以便后续查阅. ffmpeg官方网址 ...
- 机器学习基础01DAY
数据的特征抽取 现实世界中多数特征都不是连续变量,比如分类.文字.图像等,为了对非连续变量做特征表述,需要对这些特征做数学化表述,因此就用到了特征提取. sklearn.feature_extract ...
- Series基础
目录 创建Series对象 1) 创建一个空Series对象 2) ndarray创建Series对象 3) dict创建Series对象 4) 标量创建Series对象 访问Series数据 1) ...
- NVME(学习笔记一)—概述
NVMe概述 NVMe是一个针对基于PCIe的固态硬盘的高性能的.可扩展的主机控制器接口. NVMe的显著特征是提供多个队列来处理I/O命令.单个NVMe设备支持多达64K个I/O 队列,每个I/O队 ...
- 如何从零实现属于自己的 API 网关?
序言 上一篇文章:你连对外接口签名都不会知道?有时间还是要学习学习. 有很多小伙伴反应,对外的 API 中相关的加签,验签这些工作可以统一使用网关去处理. 说到网关,大家肯定比较熟悉.市面上使用比较广 ...
- 【Unity3D】Unity与Android交互
1 前言 本文主要介绍 Unity 打包发布 Android apk 流程.基于 AndroidJavaObject(或 AndroidJavaClass)实现 Unity 调用 Java 代码. ...
- Redis原理再学习03:数据结构-链表 list
链表list介绍 1. 链表list简介 链表(linked list)是一种基础数据结构,是一种线性表,但是不会按照线性表的顺序存储数据,而是在每一个节点里存到下一个节点的指针. 链表插入节点时是 ...
- ASP.NET Core MVC应用模型的构建[3]: Controller的收集
从编程的角度来看,一个MVC应用是由一系列Controller类型构建而成的,所以对于一个代表应用模型的ApplicationModel对象来说,它的核心就是Controllers属性返回的一组Con ...