摘要

本文介绍了使用 Pandas 进行数据挖掘时常用的加速技巧。

实验环境

import numpy as np
import pandas as pd
print(np.__version__)
print(pd.__version__)
1.16.5
0.25.2

性能分析工具

本文使用到的性能分析工具,参考:Python 性能评估 学习笔记

数据准备

tsdf = pd.DataFrame(np.random.randint(1, 1000, (1000, 3)), columns=['A', 'B', 'C'],
index=pd.date_range('1/1/1900', periods=1000))
tsdf['D'] = np.random.randint(1, 3, (1000, ))
tsdf.head(3)
			A	B	C
1900-01-01 820 827 884 1
1900-01-02 943 196 513 1
1900-01-03 693 194 6 2

使用 numpy 数组加速运算

map, applymap, apply 之间的区别,参考:Difference between map, applymap and apply methods in Pandas

apply(func, raw=True)

Finally, apply() takes an argument raw which is False by default, which converts each row or column into a Series before applying the function. When set to True, the passed function will instead receive an ndarray object, which has positive performance implications if you do not need the indexing functionality.

Pandas 官方文档

DataFrame.apply() 支持参数 raw,为 True 时,直接将 ndarray 输入函数,利用 numpy 并行化加速。

有多快?

%%timeit
tsdf.apply(np.mean) # raw=False (default)
# 740 µs ± 28.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%%timeit
tsdf.apply(np.mean, raw=True)
# 115 µs ± 2.76 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

由 740 微秒降低到 115 微秒。

什么条件下可以使用?

  1. 只有 DataFrame.apply() 支持,Series.apply() 和 Series.map() 均不支持;
  2. func 不使用 Series 索引时。
tsdf.apply(np.argmax)  # raw=False, 保留索引
A   2019-12-08
B 2021-03-14
C 2020-04-09
D 2019-11-30
dtype: datetime64[ns]
tsdf.apply(np.argmax, raw=True)  # 索引丢失
A      8
B 470
C 131
D 0
dtype: int64

.values

多个 Series 计算时,可以使用 .values 将 Series 转换为 ndarray 再计算。

%%timeit
tsdf.A * tsdf.B
# 123 µs ± 2.86 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%%timeit
tsdf.A.values * tsdf.B.values
# 11.1 µs ± 1.09 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)

由 123 微秒降低到 11 微秒。

补充说明

注意到 Pandas 0.24.0 引入了 .array 和 .to_numpy(),参考。但这两种方法的速度不如 values,建议在数据为数值的情况下继续使用 values。

%%timeit
tsdf.A.array * tsdf.B.array
# 37.9 µs ± 938 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%%timeit
tsdf.A.to_numpy() * tsdf.B.to_numpy()
# 15.6 µs ± 110 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

可见两种方法均慢于 values 的 11 微秒。

字符串操作优化

数据准备

tsdf['S'] = tsdf.D.map({1: '123_abc', 2: 'abc_123'})
%%timeit
tsdf.S.str.split('_', expand=True)[0] # 得到'_'之前的字符串
# 1.44 ms ± 97.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

一种优化思路是:针对特定场景,不需要使用 split,可以改用 partition:

%%timeit
tsdf.S.str.partition('_', expand=True)[0]
# 1.39 ms ± 44.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

速度略有提升。试试 apply :

%%timeit
tsdf.S.apply(lambda a: a.partition('_')[0])
# 372 µs ± 8.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

可见使用 apply 速度反而比 Pandas 自带的字符串处理方法要快,这可能是因为 Pandas 支持的数据类型多,处理过程中存在一些冗余的判断。

注意到原有数据只有2种,理论上对每一种数据取值只需要计算一次,其它值直接 map 就行。因此考虑转换为 Categorical 类型:

tsdf['S_category'] = tsdf.S.astype('category')
%%timeit
tsdf.S_category.apply(lambda a: a.partition('_')[0])
# 246 µs ± 3.36 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

耗时降低至 246 微秒。

IO 优化

Pandas 性能优化 学习笔记的更多相关文章

  1. KVM性能优化学习笔记

    本学习笔记系列都是采用CentOS6.x操作系统,KVM虚拟机的管理也是采用virsh方式,网上的很多的文章都基于ubuntu高版本内核下,KVM的一些新的特性支持更好,本文只是记录了CentOS6. ...

  2. 深挖计算机基础:Linux性能优化学习笔记

    参考极客时间专栏<Linux性能优化实战>学习笔记 一.CPU性能:13讲 Linux性能优化实战学习笔记:第二讲 Linux性能优化实战学习笔记:第三讲 Linux性能优化实战学习笔记: ...

  3. mysql性能优化学习笔记-参数介绍及优化建议

    MySQL服务器参数介绍 mysql参数介绍(客户端中执行),尽量只修改session级别的参数. 全局参数(新连接的session才会生效,原有已经连接的session不生效) set global ...

  4. mysql性能优化学习笔记

    mysql性能优化 硬件对数据库的影响 CPU资源和可用内存大小 服务器硬件对mysql性能的影响 我们的应用是CPU密集型? 我们的应用的并发量如何? 数量比频率更好 64位使用32位的服务器版本 ...

  5. js性能优化--学习笔记

    <高性能网站建设进阶指南>: 1.使用局部变量,避免深入作用域查找,局部变量是读写速度最快的:把函数中使用次数超过一次的对象属性和数组存储为局部变量是一个好方法:比如for循环中的.len ...

  6. mysql性能优化学习笔记(1)优化目的、方向及数据库准备

    前言: 最近参加面试,问到了很多关于mysql的优化方面的问题,回答的不是很好,也是因为原先做的项目流量不是很大,所以对mysql优化不是太了解,所以趁着周末,恶补一下. 本文来源于慕课网sqlerc ...

  7. php性能优化学习笔记

    编写代码 1.尽可能多的使用内置函数2.比对内置函数的时间复杂度,选择复杂度低的 比如 循环20万次-测试isset 和 array_key_exists 耗时 对比isset.php , array ...

  8. Java性能优化学习笔记

    1. 尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面: 第一,控制资源的使用,通过线程同步来控 ...

  9. PHP性能优化学习笔记--PHP周边性能优化--来自慕课网Pangee http://www.imooc.com/learn/205

    PHP一般运行于Linux服务器中,周边主要包括:Linux运行环境.文件存储.数据库.缓存.网络 常见PHP场景的开销次序: 读写内存<<读写数据库(使用内存作为缓存.异步处理)< ...

随机推荐

  1. 微信小程序传code 拿token 后台报40029 状态吗,是为什么?

    看看是不是code用了两次,还有种可能,检查一下后台的appid

  2. git相关项目迁移

    1). 从原地址克隆一份裸版本库,比如原本托管于 GitHub. git clone --bare git://github.com/username/project_old.git --bare 创 ...

  3. JS中的解构

    先看看数组解构: function fn(){ return [1,2,3]; } var [a,b,c] = fn(); console.log(a,b,c); // 1 2 3 var [d,,f ...

  4. 使用Spring框架整合Java Mail

    我的博客名为黑客之谜,今天演示的案例中会出现我的邮箱,还不赶紧收藏!我现在是小白,但是随着时间的流逝,我会逐渐向大神走进,所以,喜欢我的,或者喜欢大神的,点一波关注吧!顺便说一下,双十二快到了,有什么 ...

  5. [Linux kali] linux kali [KDE]一些软件切换输入法无效

    #开始 今天最终是在实体机安装了Kali Kali的默认桌面是GNOME桌面 但是用久了windows桌面用这个实在是不习惯 然后看到了kali有自带KDE版本的 然后就下载了一个尝尝鲜 之前在Deb ...

  6. django的静态文件配置和路由控制

    上一篇写到刚建完django项目,此时我登录页面中调用了js文件,执行后发现报错了找不到js这个文件 目录结构如图所示: <!DOCTYPE html> <html lang=&qu ...

  7. VMware虚拟磁盘修复

    最近VMware虚拟机老是断掉提示无法完成同步,后来提示虚拟磁盘需要修复,经过一番查询,找到了相关检查与修复口令,先记录如下. vmware-vdiskmanager -R “PATH” 说明: PA ...

  8. LeetCode练题——70. Climbing Stairs

    1.题目 70. Climbing Stairs——Easy You are climbing a stair case. It takes n steps to reach to the top. ...

  9. 为什么阿里Java手册推荐慎用 Object 的 clone 方法来拷贝对象

    图片若无法显示,可至掘金查看https://juejin.im/post/5d425230f265da039519d248 前言 在阿里Java开发手册中,有这么一条建议:慎用 Object 的 cl ...

  10. ubuntu 18 python3.6更换国内源和pip3源

    1.更换国内源 查看Ubuntu18版本和codename(一定要注意codename对应) lsb_release -a No LSB modules are available. Distribu ...