活用 shift,10 秒搞定 500 万
2020-06-12 本文已影响0人
呆鸟的简书
Pandas 百问百答第 011 篇。
呆鸟云:“因受疫情影响,断更了好久,不过大家不用担心,只要呆鸟有心得,就会继续与大家分享,这个号不会黄的。这次先来一篇优化 pandas 计算效率的文章,希望大家喜欢。”
话说,前几天凤哥找我说要对几百万条数据先分组,再根据条件为每组里的数据加上序号, 据他说用循环的速度太慢了,要跑上一两个小时,这不是潘大师该有的表现,于是呆鸟尝试了一下,把处理 500 万条数据的速度压缩到了 10 秒以内,现总结如下:
背景
- 原始数据分为两列,一列为 id,一列为 date,id 不唯一,每个 id 出现至少一次,并对应不同的 date;date 的排序为由远及近,即日期近的在上面,日期远的在下面,类似一个客户 id 在不同日期进行多次消费
目标
- 要求添加一列新 id,依据是按原 id 分组,查看相邻记录的日期是否超过 4 天,没超过 4 天,则序号不增加,超过 4 天则 + 1
- 新 id 由原 id 作为前缀,新生成的序号为后缀,结果如 “1-1、1-2、1-3”
知识点
-
shift()
:支持对 groupby 结果按每组内的数据进行 shift。periods
参数的值为正数时下移,负数时上移 -
两列日期相减后的结果为 timedelta,timedelta 数据相减时要用
pd.Timedelta()
,如pd.Timedelta('0 days')
,常用时间间隔参数(可组合)如下:- 年:1 Y
- 月:注意,不支持月,因为月的天数不定
- 周:2 W
- 日:3 days、3 day
- 时:4 hours、4 hour、4 hr、4 h
- 分:5 minutes、5 minute、5 min、5 m、5 T
- 秒:6 seconds、6 second、6 sec、6 s
-
np.where():np.where(条件,结果为真时的值,结果为假时的值),对 pandas 数据列执行 if-then-else 判断
思路
-
std = pd.Timedelta('4 days')
, 设定标准间隔天数为 4 天 -
df['date_shift'] = df.groupby(['id'])['date'].shift(periods=1)
,用 groupby 根据 id 分组,以便对每组数据重新排序
注意:每组的第 1 条数据对应序号肯定为 1
从第 2 条数据开始,判断与上一条数据间隔的日期是否为 4 天,怎么判断间隔日期呢?这里就用到了标题里提到的 shift(),将日期数据下移一行
-
df['date_diff'] = df['date_shift'] - df['date']
,两列 date 列的数据相减,计算上下两条记录相隔的天数,注意计算结果的类型为timedelta
-
df['date_diff'] = (df['date_diff']-std) \> pd.Timedelta('0 days')
,配合 pd.Timedelta() 计算间隔日期是否超过 4 天 -
df['diff'] = np.where(df['date_diff'] == True, 1,0)
,对 pandas 的列数据执行 if-then-else 判断,超过 4 天则为 1,没超过则为 0,新建 “diff” 列储存计算结果,注意:这里的 0 与 1 是为了用于下一步计算 -
df['diff_cumsum'] = df.groupby(['id'])['diff'].cumsum()
,用 cumsum() 为每组数据添加组内序号,注意:这里有一个分组后的计算技巧,这里的累加是针对 diff 列的,也就是上一步计算的 0 与 1,这样计算的目的是实现只有间隔日期超过 4 天序号才递增,没超过 4 天则不递增,计算结果存在diff_cumsum
这一步虽没什么技术含量,但思路非常重要,就是这种方式,使得计算速度大幅提升。
-
df['new_id_surfix'] = df['diff_cumsum'] + 1
,把diff_cumsum
列的数据 + 1,即可得到每组的序号,计算结果存入到新 id 的后缀列里 即new_id_surfix
-
df['new_id'] = df['id'].astype(str) + '-' + df['new_id_surfix'].astype(str)
,用astype(str)
把类型转为字符串,用+
合并两个,则可生成新的 id
生成 500 万条模拟数据
生成模拟数据与解决方案好了,今天的分享就到这里。
- 第 010 篇:惊了!大牛换了个思路,就让 Pandas 快了 1000x!
- 第 009 篇:不会爬,没数据?没关系!3分钟搞定1w+数据,超实用!
- 第 008 篇:Pandas 还能这么玩儿?这样排序才叫真功夫!
- 第 007 篇:如何把多个 df 保存至一个 Excel?
- 第 006 篇:三分钟告诉你 1575119387982 是什么?
- 第 005 篇:如何选择适合小白的 Python 数据分析书?
- 第 004 篇:如何安装 Python 数据分析编程环境
- 第 003 篇:如何用 Anaconda 安装、升级、删除支持库?
- 第 002 篇:如何配置 Jupyter Notebook?
- 第 001 篇:你不一定知道这个用 Python 快速设置 Excel 表格边框的技巧
- 第 000 篇: 1 分钟修改 Jupyter 启动文件夹