如何确保Pandas时间序列区间具备均匀间隔?
问题根源
先明确你的时间范围总时长:2022-10-24到2022-11-03正好是10天,转换成纳秒是 10*24*3600*1e9 = 864000000000000 ns。
当你指定periods=44时,实际需要生成43个时间间隔(点数=间隔数+1)。用总时长除以43:864000000000000 / 43 ≈ 20093023255813.953 ns——这个结果不是整数纳秒。而纳秒是Python时间系统的最小精度单位,无法拆分,所以pandas只能把一部分间隔取整数部分(20093023255813 ns),另一部分取整数部分+1(20093023255814 ns),凑齐总时长,这就是你看到两种间隔的原因。
你之前尝试±1调整周期数,本质是调整间隔数(42或44),但42和44都不是864000000000000的因数,所以同样无法得到整数间隔。而当你把周期数+2(变成46),间隔数变成45,864000000000000 /45 = 19200000000000 ns,正好是整数,所以能生成完全均匀的间隔。
通用解决方案
核心思路是:找到一个接近目标周期数的点数,使得总时长能被(点数-1)整除;如果找不到,就生成近似均匀的序列,最后强制对齐终点。
方案1:找最接近目标周期数的均匀间隔序列
这个方法会在目标周期数附近搜索,找到能生成完全均匀间隔的点数:
import numpy as np import pandas as pd def get_uniform_date_range(date_min, date_max, target_periods): # 计算总时长(纳秒) delta = date_max - date_min delta_ns = delta.astype('timedelta64[ns]').astype(int) target_gaps = target_periods - 1 # 目标间隔数 # 在目标间隔数附近搜索(可调整搜索范围) best_gap = None min_gap_diff = float('inf') # 搜索±10范围内的间隔数,避免过度偏离目标 search_start = max(1, target_gaps - 10) search_end = target_gaps + 11 for gap in range(search_start, search_end): if delta_ns % gap == 0: current_diff = abs(gap - target_gaps) if current_diff < min_gap_diff: min_gap_diff = current_diff best_gap = gap if best_gap is not None: # 找到合适的间隔数,生成序列 return pd.date_range(date_min, date_max, periods=best_gap + 1) else: # 没找到完全整除的情况,生成近似均匀序列,最后对齐终点 ideal_interval = delta_ns / target_gaps dates = date_min + np.arange(target_periods) * np.timedelta64(int(ideal_interval), 'ns') dates[-1] = date_max # 强制最后一个点等于结束时间 return dates
测试你的场景:
date_min = np.datetime64('2022-10-24T00:00:00.000000000') date_max = np.datetime64('2022-11-03T00:00:00.000000000') target_periods = 44 result = get_uniform_date_range(date_min, date_max, target_periods) print(np.unique(np.diff(result))) # 输出:array([19200000000000], dtype='timedelta64[ns]')
方案2:允许微小调整起止时间
如果可以接受起止时间有极微小的偏差(纳秒级),直接用精确的间隔生成序列:
def get_approx_uniform_dates(date_min, date_max, target_periods): delta = date_max - date_min interval = delta / (target_periods - 1) return date_min + np.arange(target_periods) * interval
这个方法生成的序列间隔完全均匀,但最后一个点可能和date_max有几纳秒的差异,对多数插值场景来说可以忽略。
内容的提问来源于stack exchange,提问作者Tom McLean

