加入收藏 | 设为首页 | 会员中心 | 我要投稿 宜春站长网 (https://www.0795zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 运营中心 > 网站设计 > 教程 > 正文

还在抱怨Pandas运行速度慢?这几个方法会颠覆你的看法

发布时间:2018-12-20 15:16:11 所属栏目:教程 来源:知乎
导读:前言 当大家谈到数据分析时,提及最多的语言就是Python和SQL。Python之所以适合数据分析,是因为它有很多第三方强大的库来协助,pandas就是其中之一。pandas的文档中是这样描述的: 快速,灵活,富有表现力的数据结构,旨在使关系或标记数据的使用既简单又

我们来看一下结果如何。

  1. >>> apply_tariff_isin(df) 
  2. Best of 3 trials with 100 function calls per trial: 
  3. Function `apply_tariff_isin` ran in average of 0.010 seconds. 

为了了解刚才代码中发生的情况,我们需要知道.isin()方法返回的是一个布尔值数组,如下所示:

  1. [False, False, False, ..., True, True, True] 

这些值标识哪些DataFrame索引(datetimes)落在指定的小时范围内。然后,当你将这些布尔数组传递给DataFrame的.loc索引器时,你将获得一个仅包含与这些小时匹配的行的DataFrame切片。在那之后,仅仅是将切片乘以适当的费率,这是一种快速的矢量化操作。

这与我们上面的循环操作相比如何?首先,你可能会注意到不再需要apply_tariff(),因为所有条件逻辑都应用于行的选择。因此,你必须编写的代码行和调用的Python代码会大大减少。

处理时间怎么样?比不是Pythonic的循环快315倍,比.iterrows快71倍,比.apply快27倍。

还可以做的更好吗?

在apply_tariff_isin中,我们仍然可以通过调用df.loc和df.index.hour.isin三次来进行一些“手动工作”。如果我们有更精细的时隙范围,你可能会争辩说这个解决方案是不可扩展的。幸运的是,在这种情况下,你可以使用Pandas的pd.cut() 函数以编程方式执行更多操作:

  1. @timeit(repeat=3, number=100) 
  2. def apply_tariff_cut(df): 
  3.     cents_per_kwh = pd.cut(x=df.index.hour, 
  4.                            bins=[0, 7, 17, 24], 
  5.                            include_lowest=True, 
  6.                            labels=[12, 20, 28]).astype(int) 
  7.     df['cost_cents'] = cents_per_kwh * df['energy_kwh'] 

让我们看看这里发生了什么。pd.cut() 根据每小时所属的bin应用一组标签(costs)。

  • 注意include_lowest参数表示第一个间隔是否应该是包含左边的(您希望在组中包含时间= 0)。

这是一种完全矢量化的方式来获得我们的预期结果,它在时间方面是最快的:

  1. >>> apply_tariff_cut(df) 
  2. Best of 3 trials with 100 function calls per trial: 
  3. Function `apply_tariff_cut` ran in average of 0.003 seconds. 

到目前为止,时间上基本快达到极限了,只需要花费不到一秒的时间来处理完整的10年的小时数据集。但是,最后一个选项是使用 NumPy 函数来操作每个DataFrame的底层NumPy数组,然后将结果集成回Pandas数据结构中。

使用Numpy继续加速

使用Pandas时不应忘记的一点是Pandas Series和DataFrames是在NumPy库之上设计的。这为你提供了更多的计算灵活性,因为Pandas可以与NumPy阵列和操作无缝衔接。

下面,我们将使用NumPy的 digitize() 函数。它类似于Pandas的cut(),因为数据将被分箱,但这次它将由一个索引数组表示,这些索引表示每小时所属的bin。然后将这些索引应用于价格数组:

  1. @timeit(repeat=3, number=100) 
  2. def apply_tariff_digitize(df): 
  3.     prices = np.array([12, 20, 28]) 
  4.     bins = np.digitize(df.index.hour.values, bins=[7, 17, 24]) 
  5.     df['cost_cents'] = prices[bins] * df['energy_kwh'].values 

与cut函数一样,这种语法非常简洁易读。但它在速度方面有何比较?让我们来看看:

  1. >>> apply_tariff_digitize(df) 
  2. Best of 3 trials with 100 function calls per trial: 
  3. Function `apply_tariff_digitize` ran in average of 0.002 seconds. 

(编辑:宜春站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读