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

如何优化Pandas日期范围转换?寻求高效条件合并方案

问题描述

我有如下销售数据DataFrame,日期列的数据类型为pandas的datetime[64]:

Shop IDSpecial Offer StartSpecial Offer End
A'2022-01-01''2022-01-03'
B'2022-01-09''2022-01-11'

希望将数据转换为二进制格式,用单独列展示日期,促销信息用0和1标识,转换后表格如下:

Shop IDDateSpecial Offer?
A'2022-01-01'1
A'2022-01-02'1
A'2022-01-03'1
B'2022-01-09'1
B'2022-01-10'1
B'2022-01-11'1

我原本用逐行循环的方式实现,但运行速度极慢:

new_list = []
for i, row in sales_df.iterrows():
    df = pd.DataFrame(pd.date_range(start=row["Special Offer Start"],end=row["Special Offer End"]), columns=['Date'])
    df['Shop ID'] = row['Shop ID']
    df["Special Offer?"] = 1
    new_list.append(df)

result = pd.concat(new_list ).reset_index(drop=True)

我想过先给原DataFrame加Special Offer?列,再和包含所有日期的DataFrame按「Date在Special Offer Start和Special Offer End之间」的条件合并后填充NaN,但找不到Pandas里对应的条件合并方法,求这个日期范围转换的优化方案。


优化方案

方法1:用explode结合date_range生成日期序列

避免逐行循环,直接对每行生成日期范围的列表,再用explode展开,这是Pandas原生的高效操作:

# 为每行生成日期范围的列表
sales_df['Date'] = sales_df.apply(
    lambda x: pd.date_range(start=x['Special Offer Start'], end=x['Special Offer End']).tolist(),
    axis=1
)
# 展开列表为多行并整理列
result = sales_df.explode('Date')[['Shop ID', 'Date']]
result['Special Offer?'] = 1
result = result.reset_index(drop=True)

方法2:生成全量店铺-日期组合,匹配促销区间(支持非促销日期标记0)

如果需要包含非促销日期并标记为0,可以用笛卡尔积生成全量组合,再判断日期是否在促销区间内:

# 生成所有需要覆盖的日期范围(取原数据中最早和最晚的日期)
all_dates = pd.date_range(
    start=sales_df['Special Offer Start'].min(),
    end=sales_df['Special Offer End'].max()
)
# 生成店铺和日期的笛卡尔积
all_shop_dates = pd.MultiIndex.from_product(
    [sales_df['Shop ID'].unique(), all_dates],
    names=['Shop ID', 'Date']
).to_frame(index=False)

# 合并原促销数据,判断每个日期是否属于促销区间
result = all_shop_dates.merge(
    sales_df,
    on='Shop ID',
    how='left'
)
# 标记促销状态:日期在区间内为1,否则为0
result['Special Offer?'] = result.apply(
    lambda x: 1 if (x['Date'] >= x['Special Offer Start']) & (x['Date'] <= x['Special Offer End']) else 0,
    axis=1
)
# 清理多余列
result = result[['Shop ID', 'Date', 'Special Offer?']].reset_index(drop=True)

方法3:用Numpy广播机制加速(超大数据量适用)

如果数据量极大,用Numpy的广播替代Pandas的行级操作,进一步提升速度:

import numpy as np

# 提取数组格式的店铺、起始、结束日期
shops = sales_df['Shop ID'].to_numpy()
starts = sales_df['Special Offer Start'].to_numpy().astype('datetime64[D]')
ends = sales_df['Special Offer End'].to_numpy().astype('datetime64[D]')

# 计算每个促销区间的日期数量,生成重复的店铺数组
date_counts = (ends - starts).astype(int) + 1
repeat_shops = np.repeat(shops, date_counts)

# 生成所有促销日期的数组
dates = np.concatenate([np.arange(s, e+np.timedelta64(1, 'D'), dtype='datetime64[D]') for s, e in zip(starts, ends)])

# 组合成结果DataFrame
result = pd.DataFrame({
    'Shop ID': repeat_shops,
    'Date': dates,
    'Special Offer?': 1
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 15:21:01