You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对Pandas DataFrame按时间间隔重采样并按比例分配数值?

按小时间隔拆分带起止时间的Pandas数据并按比例分配数值

原始数据

我有如下Pandas DataFrame:

indexstart_timeend_timeamount
foo2023-03-11 09:45:272023-03-11 09:58:3948
bar2023-03-11 09:59:002023-03-11 10:09:0020

需求与逻辑

希望按小时间隔拆分数据,得到如下结果:

intervalamount
2023-03-11 09:00-10:0050
2023-03-11 10:00-11:0018

逻辑说明:

  • bar的1分钟(占自身总时长的10%)落在09:00-10:00区间,因此将bar的amount的10%加入该区间,即48 + 20*0.1 = 50
  • bar剩余的amount(18)分配至10:00-11:00区间

现有方法的局限

我了解到resample方法适合按间隔拆分,但存在局限:

  • resample针对单个时间点,而非起止时间范围
  • 无法自动基于时间间隔的重叠比例分配数值

解决方案

Pandas没有直接内置的一键方法,但可以通过以下高效步骤实现,无需复杂自定义逻辑:

步骤1:转换时间列为datetime类型

首先确保时间列是datetime格式,方便后续计算:

import pandas as pd

# 构造原始数据
df = pd.DataFrame({
    'index': ['foo', 'bar'],
    'start_time': ['2023-03-11 09:45:27', '2023-03-11 09:59:00'],
    'end_time': ['2023-03-11 09:58:39', '2023-03-11 10:09:00'],
    'amount': [48, 20]
}).set_index('index')

# 转换为datetime类型
df['start_time'] = pd.to_datetime(df['start_time'])
df['end_time'] = pd.to_datetime(df['end_time'])

步骤2:生成所有涉及的小时区间

提取数据覆盖的所有小时起始点,生成对应的小时区间:

# 获取覆盖的所有小时起始点
all_hours = pd.date_range(
    start=df['start_time'].min().floor('H'),
    end=df['end_time'].max().ceil('H'),
    freq='H'
)

# 构造小时区间的起止时间
hour_intervals = pd.DataFrame({
    'interval_start': all_hours[:-1],
    'interval_end': all_hours[1:]
})

步骤3:计算每条记录与小时区间的重叠时长

通过交叉合并,匹配每条记录和所有小时区间,计算重叠时间:

# 交叉合并原始数据与小时区间
cross = df.assign(key=1).merge(hour_intervals.assign(key=1), on='key').drop('key', axis=1)

# 计算重叠时段的起止时间
cross['overlap_start'] = cross[['start_time', 'interval_start']].max(axis=1)
cross['overlap_end'] = cross[['end_time', 'interval_end']].min(axis=1)

# 计算重叠时长(秒),过滤无重叠的记录
cross['overlap_seconds'] = (cross['overlap_end'] - cross['overlap_start']).dt.total_seconds()
cross = cross[cross['overlap_seconds'] > 0]

步骤4:按比例分配amount并汇总

根据重叠时长占比分配amount,最后按区间汇总结果:

# 计算每条记录的总时长
cross['total_seconds'] = (cross['end_time'] - cross['start_time']).dt.total_seconds()

# 计算当前区间应分配的amount
cross['allocated_amount'] = cross['amount'] * (cross['overlap_seconds'] / cross['total_seconds'])

# 格式化区间名称并汇总求和
result = cross.groupby(
    cross['interval_start'].dt.strftime('%Y-%m-%d %H:00') + '-' + cross['interval_end'].dt.strftime('%H:00')
)['allocated_amount'].sum().round().reset_index(name='amount')

执行后得到的result即为目标结果:

interval  amount
0  2023-03-11 09:00-10:00      50
1  2023-03-11 10:00-11:00      18

补充说明

这个方法的核心是交叉匹配时间区间+计算重叠比例,可扩展到任意时间间隔(如15分钟、日度等),只需修改date_range的freq参数即可。利用Pandas向量运算,效率高于自定义循环逻辑,也更易维护。

内容的提问来源于stack exchange,提问作者PlankTon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 21:13:25