摘要

本文介绍了使用 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. Loading class `com.mysql.jdbc.Driver'. This is deprecated

    注意mysql的版本,pom.xml里面的版本.External Librarlies里面的mysql版本.application.properties版本都要检查 有时候还会报 Invalid bo ...

  2. bugku 你必须让他停下

    首先打开链接会发现一个不断刷新的网页 然后使用抓包工具burpsuit抓网页 然后右键点击跳转到repeater 然后点击go一直点击 注意黄色区域的变化然后在点击过程中会发现flag 然后拿到答案

  3. 基于selenium+Python3.7+yaml+Robot Framework的UI自动化测试框架

    前端自动化测试框架 项目说明 本框架是一套基于selenium+Python3.7+yaml+Robot Framework而设计的数据驱动UI自动化测试框架,Robot Framework 作为执行 ...

  4. C++子类虚函数表指针

    最近看剑指offer,记录一下 #include <iostream> #include <string> #include <cctype> #include&l ...

  5. css 把图片变成灰色

    3.14号刚下班,噩耗传来,伟大的物理学家斯蒂芬·威廉·霍金去世了. 同事正好叫我吃饭,几分钟内去看了一眼百度百科,一看也都变黑白了,可是查看图片还是彩色的,也是哪有这么快的时间来p图呢,回来搜了一下 ...

  6. linux查看端口占用程序

    netstat -apn  查看所有进程和端口的使用情况,看到9000端口和28080端口被java程序占用,PID分别为17607,1442 ps -aux|grep 17607 ps -aux|g ...

  7. Ubuntu 安装 uWSGI

    uWSGI官方网址: https://pypi.org/project/uWSGI/ 使用如下命令安装: pip install uWSGI 报如下错: Collecting uWSGI Using ...

  8. ASP.NET(C#) Json序列化反序列化帮助类Jsonhelper

    原文地址:https://ken.io/note/csharp-asp.net-jsonhelper using System; using System.Collections.Generic; u ...

  9. Python的 REPL 模式

    REPL Read Eval Print Loop读取,执行,输出,循环 在REPL环境中,你输入一句话,他就读取,执行,输出一个结果,所以也称为 交互式提示模式这是python代码最简单的方式,也揭 ...

  10. 用for循环写这段代码

    之前用while循环写了一段代码,现在改为用for循环来写,代码如下: hongtao_age = 38 for i in range(5): guess_age = int(input(" ...