pandas的DataFrame的apply函数可以实现对指定的轴进行遍历操作,这是个很方便也很常用的函数,但是问题在于,当我们的数据量较大,比如有50万行,这时要对50万行进行逐行遍历的话,如果对每行的操作用到了Series索引,那么这将是一个非常耗时的过程,因为对于pandas来说,索引操作是低效的,这种低效再经过50万行放大,那么性能就会显得很差。对此,我们可以通过numpy的apply_along_axis函数替代,可以实现一样的功能,但是由于numpy的ndarray的索引相对更加高效,所以性能上会有很大的提升。

import pandas as pd
import numpy as np

df=pd.DataFrame(np.arange(800000).reshape(200000,4),columns=list('abcd'))
t1=time.time()
s1=df.apply(lambda x:x['a']+x['d'],axis=1)
t2=time.time()
print(t2-t1)
arr=df.values
t3=time.time()
s=np.apply_along_axis(lambda x:x[0]+x[3],axis=1,arr=arr)
t4=time.time()
print(t4-t3)

# output:
# 9.685098886489868
# 1.3745567798614502

       可以看到,性能提升了7倍多,如果数据量更大,性能提升会更加的明显。

       对于apply_along_axis函数的使用,相比于DataFrame的apply函数,有以下几点需要特别注意:

1、apply_along_axis本质上还是一个for loop,只是其数据结构上性能会更佳,所以整体的速度会更快;

2、如果ndarray的数据类型是object,那么在使用apply_along_axis时,其会进一步的将object转为numpy的其他数据类型,因此这时就需要特别注意,特别注意第一个inner loop遇到的元素,之后将以此元素在numpy中的数据类型为准进行转换,这可能会引起数据类型不兼容的问题,会抛出异常或者产生数据误差,具体可看笔者的这篇文章

3、axis参数只能接受一个int值,因为默认func参数中关于arr的输入只能是一个一维的array。

4、ndarray在形式上区别于DataFrame的重要的一点是,前者只有数字索引,而后者有标签索引,很多时候,标签索引给了相应的列或者行以明确的含义,这是很重要的,在脚本逻辑上有时也是必要的;那么如何在ndarray中也实现标签索引呢?我们只需要额外的构建一个字典,即关于标签和整数之间的映射,这样我们可以通过这个字典作为标签到数字的中转站,从而实现在ndarray中也有标签索引。

5、如果需要对多条轴进行同一个函数的操作,可以利用numpy.apply_over_axis,其axis参数可以指定多轴,其运算过程为:现在第一个传入的轴上做运算,得到结果后再在第二个轴上对第一步得到的结果做相同的函数操作,以此类推,返回结果。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐