当前位置:   article > 正文

【pandas】如何百倍加速实现nlargest同样功能_pandas pandas 没有 nlargest属性

pandas pandas 没有 nlargest属性

之前在项目中遇到一个需求,提取出每天多笔数据中的最新一笔数据作为当天的数据呈现出来。例如有如下数据:

     date           tile clus   type  col_type   level  value
2019-05-13 10:39:49	 t2	  ME	ALL	  total      csim   1296
2019-05-13 11:21:41	 t2	  ME	ALL	  total	     csim	1051
2019-05-13 13:19:33	 t2   ME	ALL   total      csim	1051
2019-05-13 17:41:30	 t2   CC	ALL   total	     csim	655
2019-05-13 13:49:11	 t2   CC	ALL	  total      csim   415
2019-05-13 21:55:22	 t2   CC	ALL	  total	     csim   955
2019-05-13 08:43:30	 t2   CC	ALL	  total      csim   304
2019-05-13 01:21:12	 t2   CC 	ALL	  total      csim	415
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

那么应该选出如下两行,作为2019-05-13的最新数据输出给可视化平台。

     date                clus   type  col_type   level  value
2019-05-13 13:19:33	 t2   ME	ALL   total      csim	1051
2019-05-13 21:55:22	 t2   CC	ALL	  total	     csim   955
  • 1
  • 2
  • 3

可是这个筛选怎么实现呢?插入一列只有日期信息的“date_new”,再用上pandas的nlargest方法即可。代码如下:

     date            date_new     tile clus   type   col_type   level  value    
2019-05-13 21:55:22	 2019-05-13   t2   CC	  ALL	  total	     csim   955     
2019-05-13 17:41:30	 2019-05-13   t2   CC	  ALL     total	     csim	655     
2019-05-13 13:49:11	 2019-05-13   t2   CC	  ALL	  total      csim   415     
2019-05-13 13:19:33	 2019-05-13   t2   ME	  ALL     total      csim	1051    
2019-05-13 11:21:41	 2019-05-13   t2   ME	  ALL	  total	     csim	1051    
2019-05-13 10:39:49	 2019-05-13   t2   ME	  ALL	  total      csim   1296    
2019-05-13 08:43:30	 2019-05-13   t2   CC	  ALL	  total      csim   304     
2019-05-13 01:21:12	 2019-05-13   t2   CC 	  ALL	  total      csim	415     

df = df.groupby(["tile", "clus", "type", "col_type", "level""date_new"], as_index=False).apply(lambda x: x.nlargest(1, "date"))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

这样做确实可以达到目标,但是performance会比较差。测试了一下,在不到30W的数据集上需要两分钟多一些。经过深入思考做了第一次的优化,pandas操作的慢在很大程度上是因为太多的group组合,所以就尝试把原先的dataframe按“level”的字段拆分开,每一部分的df操作完再append在一起。为什么选择level字段,是因为level栏的种类一共只有三种,而其他的种类多。
经过这一改进,速度可以提升20%,runtime降到一分半钟左右,这个结果似乎并不能令人十分满意。如果有两百万行的数据估计还得需要十几分钟,无法忍受。

因此我们能不能换个角度,绕开group分组,哪怕不再用nlargest了?答案是肯定的。我们的目标是要取每一天最新更新的数据,那么就可以先按date进行排序,然后直接忽略“date”一栏,是不是就变成了只需要保留[“date_new”, “tile”, “clus”, “type”, “col_type”, “level”]最先出现的那一行?实现这一操作非常简单,去重即可:

df.sort_values(by="date", ascending=False, inplace=True)
df.drop_duplicates(subset=["date_new", "tile", "clus", "type", "col_type", "level"], keep="first", inplace=True)
  • 1
  • 2

运行时间不到两秒,实现了超过100倍的加速。类似的需求,譬如选择每天最早一笔数据的话,设置keep=“last”就好。

利用简单排序后去重的方法变相实现nlargest的功能,达到了我们想要的performance。很多时候,如果对performance不满意,就可以思考下瓶颈在哪里,如何避开这些瓶颈?换个方式实现,也许会有意想不到的效果。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/161889
推荐阅读
相关标签
  

闽ICP备14008679号