如何计算DataFrame每行datetime往前1天内的移动行数?
统计DataFrame每行Datetime往前1天内的行数
我有一个包含datetime列的大型DataFrame,想要统计每行datetime值往前1天范围内的行数。尝试过df.rolling,但它不支持动态窗口大小。
示例输入数据
datetime_col 01-01-2022 01:00:00 01-01-2022 02:00:00 01-01-2022 03:00:00 01-01-2022 03:30:00 01-02-2022 02:30:00 01-03-2022 01:00:00 01-04-2022 01:00:00 01-04-2022 12:00:00 01-05-2022 11:00:00
期望输出
datetime_col moving_count 01-01-2022 01:00:00 1 01-01-2022 02:00:00 2 01-01-2022 03:00:00 3 01-01-2022 03:30:00 4 01-02-2022 02:30:00 3 01-03-2022 01:00:00 2 01-04-2022 01:00:00 2 01-04-2022 12:00:00 2 01-05-2022 11:00:00 2
注意:moving_count统计的是该行日期往前1天内的行数(包含当前行)。
方法1:使用searchsorted(高效适合大数据)
searchsorted通过二分查找快速定位窗口起始索引,时间复杂度O(n log n),是处理大型数据集的最优方案之一。
步骤:
- 将datetime列转换为
datetime64类型,确保DataFrame按该列排序(未排序则执行df = df.sort_values('datetime_col')) - 计算每个时间点往前推1天的时间戳
- 用
searchsorted找到每个时间戳在原datetime列中的插入位置,即为窗口起始索引 - 用当前行索引减去起始索引再加1,得到窗口内的行数
代码示例:
import pandas as pd # 构造示例数据 data = { 'datetime_col': [ '01-01-2022 01:00:00', '01-01-2022 02:00:00', '01-01-2022 03:00:00', '01-01-2022 03:30:00', '01-02-2022 02:30:00', '01-03-2022 01:00:00', '01-04-2022 01:00:00', '01-04-2022 12:00:00', '01-05-2022 11:00:00' ] } df = pd.DataFrame(data) # 转换datetime类型并排序 df['datetime_col'] = pd.to_datetime(df['datetime_col'], format='%d-%m-%Y %H:%M:%S') df = df.sort_values('datetime_col').reset_index(drop=True) # 计算每行对应的1天前时间 df['one_day_ago'] = df['datetime_col'] - pd.Timedelta(days=1) # 定位窗口起始索引 start_indices = df['datetime_col'].searchsorted(df['one_day_ago'], side='left') # 计算移动计数 df['moving_count'] = df.index - start_indices + 1 # 输出结果 print(df[['datetime_col', 'moving_count']])
方法2:使用merge_asof(适合有序时间序列)
merge_asof专门用于按时间范围匹配数据,适合处理有序的时间序列场景,效率同样出色。
步骤:
- 复制原DataFrame生成临时表,用于时间范围匹配
- 用
merge_asof按"当前时间-1天到当前时间"的范围连接原表和临时表 - 按原表的datetime分组,统计每组的行数
代码示例:
import pandas as pd # 构造示例数据 data = { 'datetime_col': [ '01-01-2022 01:00:00', '01-01-2022 02:00:00', '01-01-2022 03:00:00', '01-01-2022 03:30:00', '01-02-2022 02:30:00', '01-03-2022 01:00:00', '01-04-2022 01:00:00', '01-04-2022 12:00:00', '01-05-2022 11:00:00' ] } df = pd.DataFrame(data) # 转换datetime类型并排序 df['datetime_col'] = pd.to_datetime(df['datetime_col'], format='%d-%m-%Y %H:%M:%S') df = df.sort_values('datetime_col').reset_index(drop=True) # 创建匹配用临时表 temp_df = df.rename(columns={'datetime_col': 'match_datetime'}) # 按时间范围连接数据 merged = pd.merge_asof( df, temp_df, left_on='datetime_col', right_on='match_datetime', direction='backward', tolerance=pd.Timedelta(days=1) ) # 分组统计行数 df['moving_count'] = merged.groupby('datetime_col')['match_datetime'].transform('count') # 输出结果 print(df[['datetime_col', 'moving_count']])
内容的提问来源于stack exchange,提问作者Daniel Wyatt
相关产品推荐
相关产品推荐

