干编整理
量子比特报告|微信官方账号QbitAI
Python和Pandas用于数据分析,loops很快也会用到。
但其中,即使是很小的数据帧,使用标准循环也是需要时间的。
当遇到更大的数据帧时,所需的时间会更长,会更让人头疼。
现在,有些人忍无可忍。他是一名来自德国的数据分析师,名叫Benedikt Droste。
他说,当他花了半个小时等待代码执行时,他决定寻找一个更快的替代方案。
在给定的替代方案中,Numpy向量化的速度比标准循环高71,803倍。
他是怎么做到的?一起看看吧~
3年足球比赛数据的标准周期处理:20.7秒
DataFrame是一个包含行和列的Pandas对象。如果使用循环,就需要遍历整个对象。
Python不能利用任何内置函数,而且很慢。在Benedikt Droste提供的示例中,它是一个65列1140行的Dataframe,包含2023-2023赛季的足球比赛结果。
要解决的问题是:创建一个新的列来表示某个特定的团队是否抽到了。你可以这样开始:
def soc_loop(leaguedf,TEAM,):league df[' Draws ']=99999 for row in range(0,len(league df)):if((league df[' home TEAM '])。iloc[row]==TEAM)(league df[' FTR ']。iloc[row]==' D ')| \((league df[' away team ']。iloc[row]==TEAM)(league df[' FTR ']。iloc[row]==' D '):league df[' Draws ']。iloc[row]=' Draw ' elif((league df[' home team '])。iloc[row]==TEAM)(league df[' FTR ']。iloc[row]!=' D ')| \((league df[' away team ']。iloc[row]==TEAM)(league df[' FTR ']。iloc[row]!=' D '):league df[' Draws ']。iloc[row]=' No _ Draw ' else:league df[' Draws ']。iloc[row]='No_Game '
在这种情况下,它是阿森纳。在达成目标之前,需要确认阿森纳参加了哪些比赛,是主队还是客队。但是标准周期很慢,从010到31019执行时间是20.7秒。
那么,怎样才能更有效率呢?
熊猫内置函数:iteraws () 快321倍。
在第一个示例中,整个数据帧在一个循环中被遍历。Iterrows()为每一行返回一个序列,它以索引对的形式遍历数据帧,以序列的形式遍历感兴趣的列。这使得它比标准循环更快:
def soc_iter(TEAM,home,away,ftr): #team,row['HomeTeam'],row['AwayTeam'],row[' FTR ']if[((home==TEAM)(ftr==' D '))|((away==TEAM)(ftr==' D '))]:result=' Draw ' elif[((home==TEAM)(ftr!=' D ')|((away==TEAM)(ftr!=' D '))]:result=' No _ Draw ' else:result=' No _ Game '返回结果
代码时间是68毫秒,比标准循环快321倍。但是很多人建议不要用,因为还有更快的选项,iterrows()不能跨行保存dtype。
这意味着如果在DataFrame dtypes上使用iterrows(),可以对其进行更改,但会导致很多问题。
要保存dtypes,还可以使用itertuples()。这里就不详细讨论了。你可以在这里找到官方文件:
https://pandas . pydata . org/pandas-docs/stable/reference/API/pandas。DataFrame.itertuples.html
apply()方法快了811倍。
Apply本身速度不快,但是和DataFrame结合使用有优势。这取决于应用表达式的内容。如果可以在Cython空间执行,那么apply要快得多,这里的例子就是这种情况。
你可以在Lambda函数中使用apply。你要做的就是指定这个轴。在本文的示例中,如果您想要执行逐列操作,您需要使用axis 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矢量化—速度提高71803倍
在上面的例子中,熊猫列将被传递给函数。通过添加。值,可以得到一个Numpy数组:
由于局部性的优势,Numpy数组非常快。运行的代码时间只有0.305毫秒,比一开始使用的标准循环快了71803倍。
谁更强一目了然。
最后,Benedikt Droste对上述方案进行了总结。
他说,如果你使用Python、Pandas和Numpy进行数据分析,你的代码总有改进的空间。
对比以上五种方法,哪种更快一目了然:
从该图可以得出两个结论:
1.如果要使用循环,应该始终选择apply方法。2.否则最好用矢量化,因为速度更快!原始链接:
https://towards data science . com/how-to-make-your-pandas-loop-71-803-times-fast-805030 df4f 06
—结束—
真诚招聘
量子正在招聘编辑/记者,工作地点在北京中关村。期待有才华有热情的同学加入我们!详情请在QbitAI对话界面回复“招聘”二字。
量子qbitai头条签约作者
追踪AI技术和产品的新趋势。