稳扎稳打的基础循环

for是所有编程语言的基础语法,初学者为了快速实现功能,依懒性较强。但如果从运算时间性能上考虑可能不是特别好的选择。

本次东哥介绍几个常见的提速方法,一个比一个快,了解pandas本质,才能知道如何提速。

下面是一个例子,数据获取方式见文末。


  1. >>> import pandas as pd  
  2. # 导入数据集  
  3. >>> df = pd.read_csv('demand_profile.csv')  
  4. >>> df.head()  
  5.      date_time  energy_kwh  
  6. 0  1/1/13 0:00       0.586  
  7. 1  1/1/13 1:00       0.580  
  8. 2  1/1/13 2:00       0.572  
  9. 3  1/1/13 3:00       0.596  
  10. 4  1/1/13 4:00       0.592 

基于上面的数据,我们现在要增加一个新的特征,但这个新的特征是基于一些时间条件生成的,根据时长(小时)而变化,如下:

因此,如果你不知道如何提速,那正常第一想法可能就是用apply方法写一个函数,函数里面写好时间条件的逻辑代码。


  1. def apply_tariff(kwh, hour):  
  2.     """计算每个小时的电费"""      
  3.     if 0 <= hour < 7:  
  4.         rate = 12  
  5.     elif 7 <= hour < 17:  
  6.         rate = 20  
  7.     elif 17 <= hour < 24:  
  8.         rate = 28  
  9.     else:  
  10.         raise ValueError(f'Invalid hour: {hour}')  
  11.     return rate * kwh 

然后使用for循环来遍历df,根据apply函数逻辑添加新的特征,如下:


  1. >>> # 不赞同这种操作  
  2. >>> @timeit(repeat=3number=100 
  3. … def apply_tariff_loop(df): 
  4. …     """用for循环计算enery cost,并添加到列表"""  
  5. …     energy_cost_list = []  
  6. …     for i in range(len(df)):  
  7. …         # 获取用电量和时间(小时)  
  8. …         energy_used = df.iloc[i]['energy_kwh']  
  9. …         hour = df.iloc[i]['date_time'].hour  
  10. …         energy_cost = apply_tariff(energy_used, hour)  
  11. …         energy_cost_list.append(energy_cost)  
  12. …     df['cost_cents'] = energy_cost_list  
  13. …   
  14. >>> apply_tariff_loop(df)  
  15. Best of 3 trials with 100 function calls per trial:  
  16. Function `apply_tariff_loop` ran in average of 3.152 seconds. 

对于那些写Pythonic风格的人来说,这个设计看起来很自然。然而,这个循环将会严重影响效率。原因有几个:

首先,它需要初始化一个将记录输出的列表。

其次,它使用不透明对象范围(0,len(df))循环,然后再应用apply_tariff()之后,它必须将结果附加到用于创建新DataFrame列的列表中。另外,还使用df.iloc [i]['date_time']执行所谓的链式索引,这通常会导致意外的结果。

这种方法的最大问题是计算的时间成本。对于8760行数据,此循环花费了3秒钟。

接下来,一起看下优化的提速方案。

【声明】:芜湖站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

相关文章