数据处理必看:如何让你的Pandas循环加快71803倍

大数据
如果你使用 python 和 pandas 进行数据分析,那么不久你就会第一次使用循环了。然而,即使是对小型数据集,使用标准循环也很费时,你很快就会意识到大型数据帧可能需要很长的时间。当我第一次等了半个多小时来执行代码时,我找到了接下来想与你共享的替代方案。

数据处理必看:如何让你的Pandas循环加快71803倍

雷锋网 AI 开发者按,如果你使用 python 和 pandas 进行数据分析,那么不久你就会第一次使用循环了。然而,即使是对小型数据集,使用标准循环也很费时,你很快就会意识到大型数据帧可能需要很长的时间。当我第一次等了半个多小时来执行代码时,我找到了接下来想与你共享的替代方案。

标准循环

数据帧是具有行和列的 pandas 对象。如果使用循环,则将遍历整个对象。python 不能用任何内置函数,而且速度非常慢。在我们的示例中,我们得到了一个具有 65 列和 1140 行的数据帧,它包含 2016-2019 赛季的足球比赛结果。我们要创建一个新的列来指示某个特定的队是否打过平局。我们可以这样开始:

 

  1. leaguedf['Draws'] = 99999    
  2.  
  3. for row in range(0, len(leaguedf)):     
  4.  
  5. if ((leaguedf['HomeTeam'].iloc[row] == TEAM) & (leaguedf['FTR'].iloc[row] == 'D')) | \ 
  6. ((leaguedf['AwayTeam'].iloc[row] == TEAM) & (leaguedf['FTR'].iloc[row] == 'D')):     
  7.  
  8. leaguedf['Draws'].iloc[row] = 'Draw'      
  9. elif ((leaguedf['HomeTeam'].iloc[row] == TEAM) & (leaguedf['FTR'].iloc[row] != 'D')) | \
  10.  
  11. ((leaguedf['AwayTeam'].iloc[row] == TEAM) & (leaguedf['FTR'].iloc[row] != 'D')):   
  12. leaguedf['Draws'].iloc[row] = 'No_Draw'  
  13.  
  14. else:      
  15.  
  16. leaguedf['Draws'].iloc[row] = 'No_Game'  
  17. def soc_loop(leaguedf,TEAM,):    

 

数据处理必看:如何让你的Pandas循环加快71803倍

因为我们的数据框架中包含了英超的每一场比赛,所以我们必须检查我们感兴趣的球队(阿森纳)是否参加过比赛,是否适用,他们是主队还是客队。如你所见,这个循环非常慢,需要 207 秒才能执行。让我们看看如何提高效率。

pandas 内置函数:iterrow()——快 321 倍

在第一个示例中,我们循环访问了整个数据帧。iterrows()为每行返回一个序列,因此它以一对索引的形式在数据帧上迭代,而感兴趣的列以序列的形式迭代。这使得它比标准循环更快:

 

  1. def soc_iter(TEAM,home,away,ftr):  
  2.         #team, row['HomeTeam'], row['AwayTeam'], row['FTR']    
  3.         if [((home == TEAM) & (ftr == 'D')) | ((away == TEAM) & (ftr == 'D'))]:     
  4.                 result = 'Draw'     
  5.        elif [((home == TEAM) & (ftr != 'D')) | ((away == TEAM) & (ftr != 'D'))]:     
  6.               result = 'No_Draw'  
  7.  
  8.        else:     
  9.               result = 'No_Game'    
  10.        return result 

 

数据处理必看:如何让你的Pandas循环加快71803倍

代码运行需要 68 毫秒,比标准循环快 321 倍。但是,许多人建议不要使用它,因为仍然有更快的方法,并且 iterrows() 不保留跨行的数据类型。这意味着,如果在数据帧上使用 iterrow(),则可以更改数据类型,这会导致很多问题。要保留数据类型,还可以使用 itertuples()。我们不会在这里详细讨论,因为我们要关注效率。你可以在这里找到官方文件:

数据处理必看:如何让你的Pandas循环加快71803倍

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.itertuples.html?source=post_page-----805030df4f06----------------------

apply()方法——快 811 倍

apply 本身并不快,但与数据帧结合使用时具有优势。这取决于应用表达式的内容。如果可以在 Cython 空间中执行,则速度会更快(在这里就是这种情况)。

我们可以将 apply 与 Lambda 函数一起使用。我们要做的就是指定轴。在这种情况下,我们必须使用 axis=1,因为我们要执行一个列操作:

数据处理必看:如何让你的Pandas循环加快71803倍

此代码甚至比以前的方法更快,只需要 27 毫秒就能完成。

pandas 矢量化——快 9280 倍

现在我们可以讨论一个新话题了。我们利用矢量化的优点来创建真正快速的代码。重点是避免像前面的例子 [1] 中那样的 Python 级循环,并使用优化的 C 代码,这个代码使用内存的效率更高。我们只需要稍微修改函数:

 

  1. df['Draws'] = 'No_Game'     
  2.         df.loc[((home == TEAM) & (ftr == 'D')) | ((away == TEAM) & (ftr == 'D')), 'Draws'] = 'Draw'
  3.        df.loc[((home == TEAM) & (ftr != 'D')) | ((away == TEAM) & (ftr != 'D')), 'Draws'] = 'No_Draw'  
  4.        def soc_iter(TEAM,home,away,ftr):     

现在我们可以用 pandas series 作为输入创建新列:

数据处理必看:如何让你的Pandas循环加快71803倍

在这种情况下,我们甚至不需要循环。我们要做的就是调整函数的内容。现在我们可以直接将 pandas series 传递给我们的函数,这会导致巨大的速度增益。

Numpy 矢量化——速度快 71.803 倍

在前面的示例中,我们将 pandas series 传递给了函数。通过添加.values,我们收到一个 Numpy 数组:

数据处理必看:如何让你的Pandas循环加快71803倍

Numpy 数组非常快,我们的代码运行时间为 0305 毫秒,比开始使用的标准循环快 71803 倍。

结论

如果您使用 python、pandas 和 Numpy 进行数据分析,那么代码总会有一些改进空间。我们比较了五种不同的方法,在计算的基础上增加了一个新的列到我们的数据框架中。我们注意到在速度方面存在巨大差异:

数据处理必看:如何让你的Pandas循环加快71803倍

如果你从这篇文章中选择两条规则,我会很高兴:

  • 如果确定需要使用循环,则应始终选择 apply 方法
  • 否则,矢量化总是更好的,因为它更快

本文转自雷锋网,如需转载请至雷锋网官网申请授权。

责任编辑:未丽燕 来源: 雷锋网
相关推荐

2020-06-24 11:59:31

PythonPandas数据处理

2023-08-30 09:16:38

PandasPython

2019-06-26 08:37:23

Python数据处理编程语言

2020-02-28 09:26:54

PythonGo语言C语言

2023-12-12 11:06:37

PythonPandas数据

2021-02-17 13:20:51

forpandas语言

2022-11-17 11:52:35

pandasPySpark大数据

2023-12-18 10:36:46

数据处理PandasPython

2023-03-24 16:41:36

Pandas技巧数据处理

2019-06-12 16:21:52

时间序列PythonPandas

2023-09-25 13:19:41

pandasPython

2021-08-12 08:00:00

Pandas数据分析SQL

2018-07-27 09:32:18

Python代码数据

2020-07-21 15:40:55

NginxJava服务器

2021-09-08 08:00:00

PyPolars数据开源

2011-07-13 08:56:52

服务器大数据

2022-07-07 10:46:51

数据处理

2015-05-05 11:18:18

大数据Hadoop技术处理

2023-12-05 08:47:30

Pandas数据处理

2023-11-21 09:11:31

点赞
收藏

51CTO技术栈公众号