之前在项目中遇到一个需求,提取出每天多笔数据中的最新一笔数据作为当天的数据呈现出来。例如有如下数据:
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
那么应该选出如下两行,作为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
可是这个筛选怎么实现呢?插入一列只有日期信息的“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"))
这样做确实可以达到目标,但是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)
运行时间不到两秒,实现了超过100倍的加速。类似的需求,譬如选择每天最早一笔数据的话,设置keep=“last”就好。
利用简单排序后去重的方法变相实现nlargest的功能,达到了我们想要的performance。很多时候,如果对performance不满意,就可以思考下瓶颈在哪里,如何避开这些瓶颈?换个方式实现,也许会有意想不到的效果。