详解Python中的Pandas和Numpy库

pandas、numpy是python数据科学中非常常用的库,numpy是python的数值计算扩展,专门用来处理矩阵,它的运算效率比列表更高效。  pandas是基于numpy的数据处理工具,能更方便的操作大型表格类型的数据集。但是,随着数据量的剧增,有时numpy和pandas的速度就成瓶颈。如下我们会介绍一些优化秘籍:里面包含了 代码层面的优化,以及可以无脑使用的性能优化扩展包。 1、numexpr numexpr 是一个对numpy计算式进行的性能优化。numexpr的使用及其简单,只需要将原来的numpy语句使用双引号框起来,并使用numexpr中的evaluate方法调用即可。
经验上看,数据有上万条+ 使用numexpr才比较优效果,对于简单运算使用numexpr可能会更慢。如下较复杂计算,速度差不多快了5倍。
import numexpr as neimport numpy as npa = np.linspace(0,1000,1000) print('# numpy十次幂计算')%timeit a**10print('# numexpr十次幂计算')%timeit ne.evaluate('a**10') 2、numba numba 使用行业标准的llvm编译器库在运行时将 python 函数转换为优化的机器代码。python 中 numba 编译的数值算法可以接近 c 或 fortran 的速度。  
如果在你的数据处理过程涉及到了大量的数值计算,那么使用numba可以大大加快代码的运行效率(一般来说,numba 引擎在处理大量数据点 如 1 百万+ 时表现出色)。numba使用起来也很简单,因为numba内置的函数本身是个装饰器,所以只要在自己定义好的函数前面加个@nb.方法就行,简单快捷!# pip install numbaimport numba as nb# 用numba加速的求和函数@nb.jit()def nb_sum(a):    sum = 0    for i in range(len(a)):        sum += a[i]    return sum# 没用numba加速的求和函数def py_sum(a):    sum = 0    for i in range(len(a)):        sum += a[i]    return sumimport numpy as npa = np.linspace(0,1000,1000) # 创建一个长度为1000的数组print('# python求和函数')%timeit sum(a) print('# 没加速的for循环求和函数')%timeit py_sum(a)print('# numba加速的for循环求和函数')%timeit nb_sum(a) print('# numpy求和函数')%timeit np.sum(a) 
当前示例可以看出,numba甚至比号称最接近c语言速度运行的numpy还要快5倍+,对于python求和速度快了几百倍。。此外,numba还支持gpu加速、矢量化加速方法,可以进一步达到更高的性能。from numba import cudacuda.select_device(1)@cuda.jitdef cudasquare(x):    i, j = cuda.grid(2)    x[i][j] *= x[i][j]#numba的矢量化加速from math import sin@nb.vectorize()def nb_vec_sin(a):    return sin(a) 3、cupy cupy 是一个借助 cuda gpu 库在英伟达 gpu 上实现 numpy 数组的库。基于 numpy 数组的实现,gpu 自身具有的多个 cuda 核心可以促成更好的并行加速。
# pip install cupyimport numpy as npimport cupy as cpimport time### numpys = time.time()x_cpu = np.ones((1000,1000,1000))e = time.time()print(e - s)### cupy s = time.time()x_gpu = cp.ones((1000,1000,1000))e = time.time()print(e - s) 上述代码,numpy 创建(1000, 1000, 1000)的数组用了 1.68 秒,而 cupy 仅用了 0.16 秒,实现了 10.5 倍的加速。随着数据量的猛增,cupy的性能提升会更为明显。 4、pandas使用技巧 更多pandas性能提升技巧请戳官方文档:https://pandas.pydata.org/pandas-docs/stable/user_guide/enhancingperf.html 4.1 按行迭代优化 我们按行对dataframe进行迭代,一般我们会用iterrows这个函数。在新版的pandas中,提供了一个更快的itertuples函数,如下可以看到速度快了几十倍。
import pandas as pdimport numpy as npimport timedf = pd.dataframe({'a': np.random.randn(100000),                     'b': np.random.randn(100000),                    'n': np.random.randint(100, 1000, (100000)),                   'x':  np.random.randint(1, 10, (100000))})%%timeita2=[]for row in df.itertuples():    temp=getattr(row, 'a')    a2.append(temp*temp)df['a2']=a2%%timeita2=[]for index,row in df.iterrows():    temp=row['a']    a2.append(temp*temp)df['a2']=a2     4.2 apply、applymap优化 当对于每行执行类似的操作时,用循环逐行处理效率很低。这时可以用apply或applymap搭配函数操作,其中apply是可用于逐行计算,而applymap可以做更细粒度的逐个元素的计算。
# 列a、列b逐行进行某一函数计算df['a3']=df.apply( lambda row: row['a']*row['b'],axis=1)# 逐个元素保留两位小数df.applymap(lambda x: %.2f % x) 4.3 聚合函数agg优化 对于某列将进行聚合后,使用内置的函数比自定义函数效率更高,如下示例速度加速3倍
%timeit  df.groupby(x)['a'].agg(lambda x:x.sum())%timeit  df.groupby(x)['a'].agg(sum)%timeit  df.groupby(x)['a'].agg(np.sum) 4.4 文件操作 pandas读取文件,pkl格式的数据的读取速度最快,其次是hdf格式的数据,再者是读取csv格式数据,而xlsx的读取是比较慢的。但是存取csv有个好处是,这个数据格式通用性更好,占用内存硬盘资源也比较少。此外,对于大文件,csv还可以对文件分块、选定某几列、指定数据类型做读取。
4.5 pandas.eval pandas.eval 是基于第一节提到的numexpr,pandas也是基于numpy开发的,numexpr同样可以被用来对pandas加速)。使用eval表达式的一个经验是数据超过 10,000 行的情况下使用会有明显优化效果。import pandas as pd nrows, ncols = 20000, 100df1, df2, df3, df4 = [pd.dataframe(np.random.randn(nrows, ncols)) for _ in range(4)]print('pd')%timeit df1 + df2 + df3 + df4print('pd.eval')%timeit pd.eval(df1 + df2 + df3 + df4) 5、cython优化 cython是一个基于c语言的python 编译器,在一些计算量大的程序中,可以cython来实现相当大的加速。考虑大部分人可能都不太了解复杂的cython语句,下面介绍下cython的简易版使用技巧。
通过在ipython加入 cython 魔术函数%load_ext cython,如下示例就可以加速了一倍。进一步再借助更高级的cython语句,还是可以比python快个几十上百倍。
%%cythondef f_plain(x):    return x * (x - 1)def integrate_f_plain(a, b, n):    s = 0    dx = (b - a) / n    for i in range(n):        s += f_plain(a + i * dx)    return s * dx 6、swifter swifter是pandas的插件,可以直接在pandas的数据上操作。swifter的优化方法检验计算是否可以矢量化或者并行化处理,以提高性能。如常见的apply就可以通过swifter并行处理。
import pandas as pdimport swifterdf.swifter.apply(lambda x: x.sum() - x.min()) 7、modin modin后端使用dask或者ray(dask是类似pandas库的功能,可以实现并行读取运行),是个支持分布式运行的类pandas库,简单通过更改一行代码import modin.pandas as pd就可以优化 pandas,常用的内置的read_csv、concat、apply都有不错的加速。注:并行处理的开销会使小数据集的处理速度变慢。
!pip install modinimport pandasimport modin.pandas as pdimport time## pandaspandas_df = pandas.dataframe({'a': np.random.randn(10000000),                     'b': np.random.randn(10000000),                    'n': np.random.randint(100, 10000, (10000000)),                   'x':  np.random.randint(1, 1000, (10000000))})start = time.time()big_pandas_df = pandas.concat([pandas_df for _ in range(25)])end = time.time()pandas_duration = end - startprint(time to concat with pandas: {} seconds.format(round(pandas_duration, 3)))#### modin.pandasmodin_df = pd.dataframe({'a': np.random.randn(10000000),                     'b': np.random.randn(10000000),                    'n': np.random.randint(100, 10000, (10000000)),                   'x':  np.random.randint(1, 1000, (10000000))})start = time.time()big_modin_df = pd.concat([modin_df for _ in range(25)])end = time.time()modin_duration = end - startprint(time to concat with modin: {} seconds.format(round(modin_duration, 3)))print(modin is {}x faster than pandas at `concat`!.format(round(pandas_duration / modin_duration, 2)))
原文标题:pandas、numpy 性能优化秘籍
文章出处:【微信公众号:数据分析与开发】欢迎添加关注!文章转载请注明出处。


京东将发行10亿美元的债券
虫情测报灯大大提高了林间虫情测报工作的准确性
新能源汽车领域深度布局的车企在营收、净利润等方面实现负增长
增加工厂正常运行时间的简单方法
Littelfuse推出新款TSV阵列SP1005-01ETG
详解Python中的Pandas和Numpy库
为什么选择美国服务器?美国服务器有什么优势?
Facebook游戏现已向美国所有Android用户开放
小米max2什么时候上市?小米max2最新消息:小米max2意外曝光,骁龙660+128G定价或再次上涨
博世表彰最佳初创企业合作项目,推动开放式创新
打造最适合你的零碳阳光房
智能驾驶芯片算力越大就越好吗
汽车供应链恢复?5月新能源车交付触底反弹,汽车市场利好不断
SMARTCAR软件平台实现汽车电子系统软件的整体设计
夏普SDP争夺战升级 三星来了要郭台铭出局?
霍尔效应传感器集成电路的关键设计特征
台湾考虑开放中国大陆12英寸硅晶圆进口,遭台厂强烈反对
议程抢鲜看|OpenHarmony技术峰会——生态与互联分论坛
智能安防之后,汽车或会成为AI芯片的下一个大战场
MCU如何选型?合宙LuatOS真「芯」实「易」助力行业发展