如何高效为Pandas DataFrame生成自定义滞后变量(多门店场景)
高效生成自定义滞后销售变量的方案需求(支持单/多门店)
数据构造
生成门店小时级销售数据的代码如下:
import pandas as pd import numpy as np # Create a list of hourly timestamps from May 14, 2023, 00:00 to May 17, 2023, 23:00 timestamps = pd.date_range(start='2023-05-14', end='2023-05-17 23:00', freq='H') # Create a DataFrame with the timestamps as the index df = pd.DataFrame(index=timestamps) # Generate random sales data for each hourly timestamp df['sales'] = np.random.randint(low=100, high=1000, size=len(timestamps)) df = df.reset_index() df.columns = ['t', 'sales']
数据结构示例
sales 2023-05-14 00:00:00 2023-05-14 01:00:00 2023-05-14 02:00:00
需求说明
针对每个小时h(当前记录时间的小时数),以及i∈[0,47],需要创建新列sales_i,取值规则如下:
- 若
(48+i) ≤ (72+h),则取当前时间往前(48+i)小时的销售数据; - 否则取当前时间往前
[48 - (48+i)%(71+h)]小时的销售数据。
示例如下:
sales_0 sales_1 ... sales_35 sales_36 2023-05-17 11:00:00 2023-05-15 11:00:00 2023-05-15 10:00:00 2023-05-14 00:00:00 2023-05-15 12:00:00
这类需求通常可用shift实现,但因不同小时对应不同偏移量,无法直接使用shift。
当前低效实现
单门店场景
当前使用apply方法实现,但效率极低:
def convert(row, i): h = row['t'].hour if row['t'].hour + 72 >= 48 + i and df.loc[df.t == row['t'] - pd.DateOffset(hours=48 + i), 'sales'].size > 0: return df.loc[df.t == row['t'] - pd.DateOffset(hours=48 + i), 'sales'].values.item() elif row['t'].hour + 72 < 48 + i and df.loc[df.t == row['t'] - pd.DateOffset(hours=48 - (48 + i) % (71 + h)), 'sales'].size > 0: return df.loc[df.t == row['t'] - pd.DateOffset(hours=48 - (48 + i) % (71 + h)), 'sales'].values.item() else: return None list = [i for i in range(48)] for i in list: df['sales' + str(i)] = df.apply(lambda row: convert(row, i), axis=1)
多门店场景
当数据新增store维度后,修改后的apply方法效率同样极差:
def convert(row, i): h = row['t'].hour if row['t'].hour + 72 >= 48 + i and df.loc[(df.t == row['t'] - pd.DateOffset(hours=48 + i)) & (df.store == row.store), 'sales'].size > 0: return df.loc[(df.t == row['t'] - pd.DateOffset(hours=48 + i)) & (df.store == row.store), 'sales'].values.item() elif row['t'].hour + 72 < 48 + i and df.loc[(df.t == row['t'] - pd.DateOffset(hours=48 - (48 + i) % (71 + h))) & (df.store == row.store), 'sales'].size > 0: return df.loc[(df.t == row['t'] - pd.DateOffset(hours=48 - (48 + i) % (71 + h))) & (df.store == row.store), 'sales'].values.item() else: return None
现寻求高效实现该自定义滞后变量生成的方案,要求支持单门店及多门店场景。
内容的提问来源于stack exchange,提问作者koch
相关产品推荐
相关产品推荐

