python - 在下一个事件开始时计算已完成的事件
问题描述
我有一个数据集,可以测量多个人(id)持续多天的事件(event_start 到 event_end)。我想在下一个事件的日期计算已完成事件的数量。我可以通过 iterrows 做到这一点,但这在规模上非常缓慢。你能帮我减少运行时间吗?
df = pd.DataFrame([{'id': 1, 'event_start': '2020-01-01', 'event_end': '2020-01-03'},
{'id': 1, 'event_start': '2020-01-02', 'event_end': '2020-01-04'},
{'id': 1, 'event_start': '2020-01-03', 'event_end': '2020-01-05'},
{'id': 1, 'event_start': '2020-01-07', 'event_end': '2020-01-10'},
{'id': 2, 'event_start': '2020-01-06', 'event_end': '2020-01-07'},
{'id': 2, 'event_start': '2020-01-08', 'event_end': '2020-01-10'},])
df['event_start'] = pd.to_datetime(df['event_start'])
df['event_end'] = pd.to_datetime(df['event_end'])
df = df.sort_values(['id', 'event_start', 'event_end'])
for index, row in df.iterrows():
df.at[index, 'Previous Count'] = df[(df['id'] == row['id']) & (df['event_end'] < row['event_start'])].count()[0]
df
解决方案
我比较了这两种策略
首先是你的
%time
df = pd.DataFrame([{'id': 1, 'event_start': '2020-01-01', 'event_end': '2020-01-03'},
{'id': 1, 'event_start': '2020-01-02', 'event_end': '2020-01-04'},
{'id': 1, 'event_start': '2020-01-03', 'event_end': '2020-01-05'},
{'id': 1, 'event_start': '2020-01-07', 'event_end': '2020-01-10'},
{'id': 2, 'event_start': '2020-01-06', 'event_end': '2020-01-07'},
{'id': 2, 'event_start': '2020-01-08', 'event_end': '2020-01-10'},])
df['event_start'] = pd.to_datetime(df['event_start'])
df['event_end'] = pd.to_datetime(df['event_end'])
df = df.sort_values(['id', 'event_start', 'event_end'])
for index, row in df.iterrows():
df.at[index, 'Previous Count'] = df[(df['id'] == row['id']) & (df['event_end'] < row['event_start'])].count()[0]
df
我得到了
CPU times: user 2 µs, sys: 0 ns, total: 2 µs
Wall time: 5.01 µs
然后我尝试使用 groupby 将 iterrows 减少到同一个 ID。我不确定这是否会更快,除非数据帧很大,因为设置时间会更长。
%time
df = pd.DataFrame([{'id': 1, 'event_start': '2020-01-01', 'event_end': '2020-01-03'},
{'id': 1, 'event_start': '2020-01-02', 'event_end': '2020-01-04'},
{'id': 1, 'event_start': '2020-01-03', 'event_end': '2020-01-05'},
{'id': 1, 'event_start': '2020-01-07', 'event_end': '2020-01-10'},
{'id': 2, 'event_start': '2020-01-06', 'event_end': '2020-01-07'},
{'id': 2, 'event_start': '2020-01-08', 'event_end': '2020-01-10'},])
df['event_start'] = pd.to_datetime(df['event_start'])
df['event_end'] = pd.to_datetime(df['event_end'])
df = df.sort_values(['id', 'event_start', 'event_end'])
outdf = pd.DataFrame(columns=df.columns)
for id, subdf in df.groupby('id'):
for index, row in subdf.iterrows():
subdf.at[index, 'Previous Count'] = subdf[(subdf['event_end'] < row['event_start'])].count()[0]
outdf = pd.concat([outdf,subdf])
outdf
我得到了
CPU times: user 2 µs, sys: 1 µs, total: 3 µs
Wall time: 5.96 µs
您的里程将根据您的大数据框的大小和组成而有所不同,但值得一试。
推荐阅读
- material-ui - 如何在 Material-ui 中使用或开始使用 ...theme.mixins.toolbar?
- node.js - “从哪里选择”翻译成猫鼬
- python - 随机选择字符串中元素的百分比并更改值
- android - 我的用于 arm64-v8a ABI 的应用 APK 的旧版本在 Play 商店中分发?
- c# - 在进入瀑布对话框之前禁用/重新启用 LUIS 识别器
- arrays - 如何将数组转换为对象并在角度5中迭代列表?
- ios - Codable 如何适应 iOS 恢复过程?
- sql - 在 BigQuery 标准 SQL 中按时间戳值的前 4 位进行过滤
- jquery - JQueryUI Dialog插入文本的方式
- sql-server - 报表生成器:如何同时设置多个文本框的高度