德安新闻门户网

首页 > 正文

Pandas循环提速7万多倍!Python数据分析攻略

www.lshappy.com2019-09-15

编译并编译和组织

量子报告|公共号码QbitAI

使用Python和Pandas进行数据分析很快就会使用循环。

但在这种情况下,即使是较小的DataFrame,使用标准循环也很耗时。

当您遇到大型DataFrame时,它需要更长时间,这将导致更多的麻烦。

现在,有些人再也受不了了。他是来自德国的数据分析师Benedikt Droste。

他说,当他花了半个多小时等待代码执行时,他决定寻找更快的替代方案。

在给定的替代方案中,使用Numpy矢量化,与使用标准环相比,速度提高了71,803倍。

他是如何实现的?我们来看看

标准循环处理3年足球比赛数据:20.7秒

DataFrame是具有行和列的Pandas对象。如果使用循环,则需要遍历整个对象。

Python无法利用任何内置函数,而且速度非常慢。在Benedikt Droste提供的示例中,有一个包含65列和1140行的Dataframe,包括2016-2019足球比赛的结果。

要解决的问题是创建一个新列,指示特定团队是否已达到平局。你可以这样开始:

Def soc_loop(leaguedf,TEAM,):

Leaguedf ['Draws']=

对于范围内的行(0,len(leaguedf)):

如果((leaguedf ['Home Team']。iloc [row]=TEAM)&(leaguedf ['FTR']。iloc [row]='D')| \

(leaguedf ['Away Team']。iloc [row]=TEAM)& (leaguedf ['FTR']。iloc [row]='D'):

Leaguedf ['Draws']。 iloc [row]='画'

Elif((leaguedf ['Home Team']。iloc [row]=TEAM)&(leaguedf ['FTR']。iloc [row]!='D')| \

(leaguedf ['Away Team']。iloc [row]==TEAM)& (leaguedf ['FTR']。iloc [row]!='D'):

Leaguedf ['Draws']。 iloc [row]='No_Draw'。

否则为:

Leaguedf ['Draws']。 iloc [row]='No_Game'。

在这种情况下,它是阿森纳。在实现目标之前,我们需要确认阿森纳队的比赛,主队或客场球队。但是使用标准循环非常慢,执行时间是20.7秒。

那么我们怎样才能更有效率呢?

Pandas内置函数: iterrows()快321倍

在第一个示例中,循环遍历整个DataFrame。 Iterrows()为每一行返回一个Series,它以索引对的形式遍历DataFrame,以Series的形式遍历感兴趣的列。这使得它比标准周期更快:

Def soc_iter(TEAM,home,away,ftr):

#Team,row ['Home Team'],row ['Away Team'],row ['FTR']

如果[(home=TEAM)& (ftr=D')| ((离开=TEAM)&(ftr=D')]:

结果='绘制'

Elif [(home=TEAM)& (ftr!='D')| ((离开=TEAM)&(ftr!='D')]:

结果=No_Draw'

否则为:

结果=No_Game'

返回结果

代码运行68毫秒,比标准循环快321倍。但是,许多人不建议使用它,因为仍有更快的选项,iterrows()无法跨行保存dtypes。

这意味着如果在DataFrame dtypes上使用iterrows(),则可以更改它,但这会导致很多问题。

如果必须保存dtypes,还可以使用itertuples()。我们不会在这里详细讨论,你可以在这里找到官方文件:

Apply()方法`快811次

应用本身并不快,但与DataFrame结合使用时具有优势。这取决于apply表达式的内容。如果你可以在Cython空间中执行,那么应用会更快,就像这里的例子一样。

您可以在Lambda函数中使用apply。您所要做的就是指定此轴。在本文的示例中,要执行逐列操作,请使用轴1:

此代码甚至比前一种方法更快,完成时间为27毫秒。

熊猫矢量化 - 快9280倍

此外,您可以利用矢量化来创建非常快速的代码。

重点是避免像前面的例子那样的Python级循环,并使用优化的C代码,它将更有效地使用内存。只需修改一下这个功能:

Def soc_iter(TEAM,home,away,ftr):

DF ['Draws']='No_Game'

Df.loc [((home=TEAM)&(ftr=D')|((away=TEAM)&(ftr=D'),'Draws']='Draw')

Df.loc [((home=TEAM)&(ftr!='D')|((away=TEAM)&(ftr!='D'),'Draws']='No_Draw')

现在,您可以使用Pandas列作为输入来创建新列:

在这种情况下,您甚至不需要循环。您所要做的就是调整功能的内容。现在可以将Pandas列直接传递给函数以实现巨大的速度增益。

Numpy矢量化 - 快了71 803次

在上面的示例中,Pandas列传递给函数。通过增加。值,你可以得到一个Numpy数组:

由于局部性的好处,Numpy阵列非常快,代码只运行0.305毫秒,比首次使用的标准循环快71,803倍。

谁更强大一目了然

最后,Benedikt Droste总结了上述方案。

他说如果你使用Python,Pandas和Numpy进行数据分析,总会有改进代码的空间。

通过比较上述五种方法,哪种方法更快更清晰:

从这张图片中,可以得出两个结论:

1.如果要使用循环,则应始终选择apply方法。

2.否则,使用矢量化是最好的,因为它更快!

原始链接:

本文首次出现在微信公众号:qubit上。本文内容属于作者个人观点,不代表和讯网的立场。投资者应采取相应行动,风险自负。

(编辑:吉利亚HN003)

http://www.whgcjx.com/bds02K

热门浏览
热门排行榜
热门标签
日期归档