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

如何高效统计pandas DataFrame中日期落在Start、End列间的不同Category数量

最高效实现方案

你原来的循环写法时间复杂度为O(M*N)(M为日期总数,N为原始df行数),数据量增大后性能会非常差,推荐使用事件扫描法,时间复杂度仅为O(N log N),完全不需要逐天遍历过滤:

import pandas as pd
import datetime

# 1. 准备原始数据
d = pd.date_range(start='2015-01-01', end='2015-12-31', freq='D')
df = pd.DataFrame({
    'Category': ['a', 'a', 'b', 'b', 'c'],
    'Start': [datetime.date(2014,12,1), datetime.date(2015,10,2), datetime.date(2015,10,1), datetime.date(2015,10,1), datetime.date(2015,6,1)],
    'End': [datetime.date(2015,6,1), datetime.date(2015,10,16), datetime.date(2016,4,1), datetime.date(2015,12,1), datetime.date(2015,8,1)]
})
# 统一转成pandas datetime类型避免类型匹配错误
df[['Start', 'End']] = df[['Start', 'End']].apply(pd.to_datetime)

# 2. 每个Category先合并重叠/相邻区间,避免重复计数
def merge_intervals(group):
    group = group.sort_values('Start')
    merged = []
    for _, row in group.iterrows():
        if not merged:
            merged.append([row['Start'], row['End']])
        else:
            last_start, last_end = merged[-1]
            if row['Start'] <= last_end:
                merged[-1][1] = max(last_end, row['End'])
            else:
                merged.append([row['Start'], row['End']])
    return pd.DataFrame(merged, columns=['Start', 'End'])

merged_df = df.groupby('Category', group_keys=False).apply(merge_intervals).reset_index(drop=True)

# 3. 生成事件列表:区间开始日期计数+1,区间结束后一天计数-1
events = []
for _, row in merged_df.iterrows():
    events.append({'date': row['Start'], 'delta': 1})
    events.append({'date': row['End'] + pd.Timedelta(days=1), 'delta': -1})
event_df = pd.DataFrame(events)

# 4. 按日期聚合事件,计算累计活跃分类数
event_df = event_df.groupby('date')['delta'].sum().reset_index()
event_df = event_df.sort_values('date')
event_df['count'] = event_df['delta'].cumsum()

# 5. 对齐到目标日期范围,填充缺失值
df_count = pd.DataFrame({'date': d}).merge(event_df[['date', 'count']], on='date', how='left')
df_count['count'] = df_count['count'].ffill().fillna(0).astype(int)
df_count = df_count.set_index('date')

输出的df_count和你预期的格式完全一致,当原始数据有十万行、日期范围跨度长达数年时,性能比原循环写法高出数百倍。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 15:00:03