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

如何基于另一DataFrame的日期区间对DataFrame数据求和?

高效计算Pandas DataFrame区间总和的方法

给定以下两个Pandas DataFrame:

import pandas as pd

df1 = pd.DataFrame({'Name': ['A', 'B', 'C'], 
                    'Date1':['2023-01-01', '2023-01-02', '2023-01-03'], 
                    'Date2':['2023-01-03', '2023-01-04', '2023-01-05']})
df1.loc[:, ['Date1', 'Date2']] = df1.loc[:, ['Date1', 'Date2']].apply(pd.to_datetime, errors='coerce')

df2 = pd.DataFrame({'Date': ['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04', '2023-01-05'],
                    'A': [1, 2, 3, 4, 5], 'B': [6, 7, 8, 9, 10], 'C': [11,12,13,14,15]})
df2['Date'] = pd.to_datetime(df2['Date'])

需要为df1添加Sum列,计算df2中对应Name的数据在Date1(不含)至Date2(含)区间内的总和,期望结果如下:

df_result = pd.DataFrame({'Name': ['A', 'B', 'C'], 
                          'Date1':['2023-01-01', '2023-01-02', '2023-01-03'], 
                          'Date2':['2023-01-03', '2023-01-04', '2023-01-05'],
                          'Sum': [5, 17, 29]})

高效矢量化实现方案

这种方法避免逐行循环,通过长格式转换+累积和+区间匹配实现,适合大数据量场景:

  1. 将df2转换为长格式,统一Name和Value字段:
df2_long = df2.melt(id_vars='Date', var_name='Name', value_name='Value')
  1. 按Name和Date排序,计算每个分组的累积和:
df2_long = df2_long.sort_values(['Name', 'Date'])
df2_long['CumSum'] = df2_long.groupby('Name')['Value'].cumsum()
  1. 用merge_asof匹配df1中Date1和Date2对应的累积和,进而计算区间差:
# 匹配Date1对应的累积和(Date <= Date1的总和)
df1_sorted = df1.sort_values(['Name', 'Date1'])
df1_sorted = pd.merge_asof(df1_sorted, df2_long[['Name', 'Date', 'CumSum']],
                           left_on='Date1', right_on='Date', by='Name', direction='backward')
df1_sorted.rename(columns={'CumSum': 'Sum_Date1'}, inplace=True)

# 匹配Date2对应的累积和(Date <= Date2的总和)
df1_sorted = pd.merge_asof(df1_sorted, df2_long[['Name', 'Date', 'CumSum']],
                           left_on='Date2', right_on='Date', by='Name', direction='backward')
df1_sorted.rename(columns={'CumSum': 'Sum_Date2'}, inplace=True)

# 计算区间总和:Sum_Date2 - Sum_Date1
df1_sorted['Sum'] = df1_sorted['Sum_Date2'] - df1_sorted['Sum_Date1']

# 恢复原索引和列顺序
df1 = df1_sorted.sort_index()[['Name', 'Date1', 'Date2', 'Sum']]

执行后df1的结果与期望一致,该方案的时间复杂度主要来自排序(O(n log n)),远高于逐行循环的效率。

简易实现方案(小数据量适用)

如果数据量较小,可直接用apply逐行计算,代码更简洁但效率较低:

def get_interval_sum(row):
    # 筛选Date在(Date1, Date2]区间内的行
    date_mask = (df2['Date'] > row['Date1']) & (df2['Date'] <= row['Date2'])
    return df2.loc[date_mask, row['Name']].sum()

df1['Sum'] = df1.apply(get_interval_sum, axis=1)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 19:03:30