【简介】虽然dask、cudf等包的出现大大加速了我们的数据处理,但并不是每个人都有更好的GPU,还有很多朋友还是使用pandastoolkit,但有时候真的很无奈。实验对比1.Apply(Baseline)我们以Apply为例。原来的Apply函数需要18.4s来处理下面的问题。importpandasaspdimportnumpyasnpdf=pd.DataFrame(np.random.randint(0,11,size=(1000000,5)),columns=('a','b','c','d','e'))deffunc(a,b,c,d,e):如果e==10:返回c*delif(e<10)并且(e>=5):返回c+delife<5:returna+b%%timedf['new']=df.apply(lambdax:func(x['a'],x['b'],x['c'],x['d'],x['e']),axis=1)CPUtimes:user17.9s,sys:301ms,total:18.2sWalltime:18.4s2.Swift加速因为处理是并行的,所以我们可以使用Swift进行加速,使用Swift之后,同样的操作在我的机器上可以提升到7.67s。%%time#!pipinstallswifterimportswifterdf['new']=df.swifter.apply(lambdax:func(x['a'],x['b'],x['c'],x['d'],x['e']),axis=1)HBox(children=(HTML(value='DaskApply'),FloatProgress(value=0.0,max=16.0),HTML(value='')))CPU时间:用户329毫秒,系统:240毫秒,总计:569毫秒墙时间:7.67s3。向量化使用Pandas和Numpy的最快方法是对函数进行向量化。如果我们的操作可以直接向量化,那么我们应该尽量避免使用:for循环;列表处理;apply等操作。将上面的问题转化成下面的处理后,我们的时间缩短为:421ms。%%timedf['new']=df['c']*df['d']#defaultcasee==10mask=df['e']<10df.loc[mask,'new']=df['c']+df['d']mask=df['e']<5df.loc[mask,'new']=df['a']+df['b']CPU时间:用户134毫秒,系统:149毫秒,总计:283毫秒墙时间:421毫秒4。类别转换+向量化我们先将上面的类别转换成int16类型,然后进行同样的向量化操作,发现时间缩短为:116ms。对于colin('a','b','c','d'):df[col]=df[col].astype(np.int16)%%timedf['new']=df['c']*df['d']#defaultcasee==10mask=df['e']<10df.loc[mask,'new']=df['c']+df['d']mask=df['e']<5df.loc[mask,'new']=df['a']+df['b']CPU时间:用户71.3毫秒,系统:42.5毫秒,总计:114毫秒墙时间:116ms5。Converttovaluesprocessing在能转成.values的地方尽量转成.values,再进行操作。这里转为.values相当于转为numpy,这样我们的向量化操作会更快。因此,上述运算时间缩短为:74.9ms。%%timedf['new']=df['c'].values*df['d'].values#defaultcasee==10mask=df['e'].values<10df.loc[mask,'new']=df['c']+df['d']mask=df['e'].values<5df.loc[mask,'new']=df['a']+df['b']CPUtimes:user64.5ms,sys:12.5ms,total:77msWalltime:74.9ms实验总结通过上面的一些小技巧,我们把简单的Apply函数加速了几百次,具体来说:Apply:18.4sApply+Swifter:7.67sPandasvectorization:421msPandasvectorization+datatypes:116msPandasvectorization+values+datatypes:74.9ms
