是否需要使用NumPy代替Pandas处理数据以提高性能?
Pandas和NumPy是Python数据科学领域中最基础的两个库,他们都可以读取大量的数据并对数据做计算等处理。有很多的操作他们都能做。只不过一般来说,Pandas的DataFrame是一种“表格”,处理的数据可以是非常复杂的结构,一个DataFrame对象可以包括数值、字符等内容。而NumPy处理的基本对象一般是数值型的数组。

那么,这两个Python库在数据处理的性能上有什么差别呢?在工程项目中,是否需要考虑优先选择哪种?今天在Reddit上看到一个有意思的讨论和大家分享一下。
一、问题的由来
有位网友是做ETL工具的,目前他们使用pandas来处理数据。他们目前会在亚马逊云上的EC2做一笑部分的Python脚本工作。不过,目前项目中的数据都是比较小的数据。但是有的人建议他如果想更有效率地处理更大规模的数据,最好使用numpy代替pandas。他就问,是不是numpy替代pandas会更好?有没有必要?这个问题引起了很多的争论,各有观点,我选择了一些比较有价值的讨论供大家参考。
二、具体的讨论
某些pandas的方法非常“笨拙”,只要避免使用也是可以的。这种情况下不需要用NumPy替换。比如iterrows按行循环Pandas的DataFrame数据,这是非常慢的。可以考虑使用lambda或者tolist代替。而像apply这种方法表现不稳定,不同方法性能差异较大,谨慎使用。其它操作性能基本都是差不多,不需要替换。
有个以前搞MATLAB的童鞋,现在转成用Python,所以他的处理最常见的就是向量操作。他觉得观点1非常正确。只是有一种情况,有一些多个dataframe组成的dict操作性能一般,无法解决(这哥们还顺带diss了一下MATLAB,说除非是simulink不得已,否则肯定不会再回去使用MATLAB)。不过,这个观点有人不赞同,说使用多索引的DataFrame和dict保存多个DataFrame处理是很复杂的语法,但是性能提升一般。实际中可以考虑使用Pandas on Spark。就用最基本的存储对象操作,性能几乎没有影响。
第三种观点是当某些处理已经由处理引擎优化的时候(如SQL、Spark甚至是GPU的并行计算)那就不需要多考虑了,但是如果是一些操作没有现成的优化引擎,最好的方式是使用native C重写。
慎用DataFrame的迭代与apply方法,多采用lambda、frequent encapsulation代替。
Pandas是里面也有NumPy。它可能总是比编写好的Numpy有一些计算上的开销,但它可以节省你写代码的时间,而且更容易调试和维护。如果你的流水线的性能造成了实际问题,用NumPy重写部分可能是值得的。如果不是,过早的优化是万恶之源。
不要纠结这方面。最好是剖析你的代码,找出瓶颈所在。比如你的ETL代码跑1个小时,用NumPy把Pandas耗时3秒的操作降低成100毫秒没有任何意义。
使用Pandas代替NumPy几乎不会由速度的提升甚至可能会变慢。不过NumPy的好处是内存方面占用更低。不过这也不会有很大的内存节省空间。如果生产环境对内存要求敏感,那么可以考虑Spark而不是换成NumPy。
大部分情况下,NumPy的操作不会比Pandas快很多。但有时候Pandas会比较慢。所以最重要的是不要完全依赖Pandas。
考虑使用pyspark代替pandas吧。最新版本的pyspark中提供了一个类似pandas的接口,几乎兼容所有的pandas操作,可以很好地提升性能(这个有人反对:Spark有一些陷阱,这意味着你真的需要摸清基本原理,以获得它的最大价值。这对事业有好处,但对压力水平不利。这哥们真是幽默,哈哈哈哈)
10.1. 这两个工具之间有很多不同。如果你需要处理数字数据,特别是大于2维的数据,你应该学习numpy,因为pandas不会有帮助。pandas对你的数据所做的一切都将以某种方式依赖于numpy数组,因此不可能更快,但它会增加numpy中缺少或笨重的功能,如grouping, lagging, rolling windows、数据时间类型的东西和字符串操作。
10.2. Numpy是纯粹的线性代数之王,它可以做一些惊人的事情,如einsum符号和快速傅里叶变换,但它在文本数据方面没有特别的优势。
10.3. 尽量避免在生产中使用pandas,因为它很耗费内存,而且在将dtypes转换为其他dtypes时也有点不稳定。当你处理文本数据时,主要的加速来自于放弃pandas而使用一些工具,如数据库,或redshift或spark,你的主要问题应该是:我可以并行化这个吗?
- 最后,有个哥们建议的,人生不是只有代码性能。如果你在乎性能,那就不要第一时间考虑Python。人生苦短,真要在乎,还可以考虑ASIC。哈哈哈哈。
三、总结及个人经验
总的来说,基本结论是Pandas的数值列也是基于NumPy的,同样的操作,NumPy的内存开销和性能应该是有一点优势,但不太值得大家花很大的力气去优化。尤其是过早优化(premature optimization)很不值得。除了个别的操作外,性能的影响很大程度是由于代码逻辑和其它瓶颈导致的。所以需要大家剖析代码来提升性能。在我个人实际项目经验中,也有一些优化经验供大家参考。
原则是如果数据是纯数值型的输入,且计算量大,可以优先一开始考虑NumPy,可能会有惊喜。Pandas某些操作性能真的不好预估。其它时候不用太在乎二者的区别。
实际的处理中,尽量早的考虑数据索引和排序,很多group/merge类型的计算操作,对于排序的数据很敏感。
在数值计算非常密集和耗时的情况下,考虑将pandas的非数值型内容用数值做转换再计算。然后将结果转换回来也是一种好的思路。
很多时候,代码逻辑影响更大。先处理什么后处理什么很重要,同时,如果可以的话,尽量采用pandas和numpy自带的函数以及lambda函数优化逻辑。
在项目的启动的时候,系统设计的过程中需要考虑项目的目标,如果对可扩展性要求很高,尽早考虑采用分布式框架的方案,包括dask、pyspark等。
讨论原文:https://www.reddit.com/r/datascience/comments/rdao7c/is_numpy_always_more_efficient_than_pandas_and/
欢迎大家关注DataLearner官方微信,接受最新的AI技术推送
