如何将Pandas DataFrame行对齐到最近的6分钟时间步长并设置索引频率
背景
我有一个包含数十万条数值的大型DataFrame,其头部数据如下所示:
df = pd.DataFrame([np.nan, 1100, 1400, np.nan, 14000], index=pd.to_datetime(["2011-05-25 10:00:00", "2011-05-25 16:40:00", "2011-05-25 17:06:00", "2011-05-25 17:10:00", "2011-05-25 17:24:00"])) # 输出预览 0 2011-05-25 10:00:00 NaN 2011-05-25 16:40:00 1100.0 2011-05-25 17:06:00 1400.0 2011-05-25 17:10:00 NaN 2011-05-25 17:24:00 14000.0
需求
数据的记录时间不都是6分钟步长,我需要将未在6分钟时间步长上记录的值移动到最近的6分钟步长,得到的新DataFrame示例如下:
n_df = pd.DataFrame([np.nan, 1100, 1400, np.nan, 14000], index=pd.to_datetime(["2011-05-25 10:00:00", "2011-05-25 16:42:00", "2011-05-25 17:06:00", "2011-05-25 17:12:00", "2011-05-25 17:24:00"]) ) # 输出预览 0 2011-05-25 10:00:00 NaN 2011-05-25 16:42:00 1100.0 2011-05-25 17:06:00 1400.0 2011-05-25 17:12:00 NaN 2011-05-25 17:24:00 14000.0
核心要求是n_df中所有值都对应6分钟时间步长,且n_df.index.freq属性不能为None。目前通过for循环遍历df查找最近6分钟步长并迁移值,当df数据量超过1000条时运行速度极慢,需要更高效的实现方法。
已尝试的实现方案
index = pd.date_range(df.index[0], end=df.index[-1], freq="6min") pydatetime_index = index.to_pydatetime() n_df = pd.DataFrame(columns=df.columns, index=index) for _idx, i in enumerate(df.index): nearest_neighbor = np.abs(pydatetime_index - i.to_pydatetime()) idx = np.argmin(nearest_neighbor) val = df.loc[i] n_df.iloc[idx] = val
高效解决方案
直接使用pandas内置的向量化时间处理能力即可实现需求,几十万条数据可在毫秒级完成处理,代码如下:
import pandas as pd import numpy as np # 1. 将原数据的时间索引对齐到最近的6分钟步长 df_aligned = df.copy() df_aligned.index = df_aligned.index.round(freq='6T') # 6T代表6分钟,也可写为'6min' # 2. 生成覆盖原时间范围的完整6分钟步长索引 full_time_index = pd.date_range( start=df.index.min(), end=df.index.max(), freq='6T' ) # 3. 先聚合落入同一时间步长的重复值(默认取第一个值,可按需改为sum/mean等),再补全所有时间步长 n_df = df_aligned.groupby(level=0).first().reindex(full_time_index)
方案说明
- 完全匹配需求:最终输出的
n_df索引为严格的6分钟步长,n_df.index.freq值为6T,不会为None - 效率提升显著:原循环方案时间复杂度为O(n*m)(n为原数据长度,m为目标索引长度),本方案为纯向量化操作,时间复杂度为O(n),处理数十万条数据无压力
- 对齐规则可灵活调整:如果需要向下取整到前一个6分钟步长,将
round改为floor;如果需要向上取整到后一个6分钟步长,改为ceil即可
内容的提问来源于stack exchange,提问作者Ather Cheema
相关产品推荐
相关产品推荐

