Python实现DataFrame时间序列筛选、重采样后横向拼接的方法咨询
实现方案
你可以按以下步骤实现,逻辑清晰且能覆盖所有需求:
第一步:数据预处理
先统一两个表的时间字段格式,同时给df1计算每个记录对应的时间窗口起止时间:
import pandas as pd # 转换时间字段格式 df1['Date'] = pd.to_datetime(df1['Date']) df2['Timestamp'] = pd.to_datetime(df2['Timestamp']) # 计算每个记录的时间窗口:前10天0点 ~ 当日23:59:59 df1['start_ts'] = df1['Date'] - pd.Timedelta(days=10) df1['end_ts'] = df1['Date'] + pd.Timedelta(days=1) - pd.Timedelta(seconds=1)
第二步:逐行处理生成时间序列特征
对于df1的每一条记录,筛选df2匹配数据后做重采样、填充,最终转成横向的14400列:
def generate_time_features(row): # 1. 筛选当前Id对应时间范围内的Value数据 filter_mask = ( (df2['Id'] == row['Id']) & (df2['Timestamp'] >= row['start_ts']) & (df2['Timestamp'] <= row['end_ts']) ) tmp = df2.loc[filter_mask, ['Timestamp', 'Value']].set_index('Timestamp').sort_index() # 2. 生成刚好14400个点的完整1min间隔时间序列 full_time_range = pd.date_range(start=row['start_ts'], end=row['end_ts'], freq='1min') # 3. 1min重采样 + 填充缺失值 # 若1分钟内有多个值,默认取均值,可替换为first()/max()等符合业务需求的聚合规则 resampled = tmp.resample('1min').mean() # 对齐完整时间序列后,先后执行后向填充、前向填充 filled = resampled.reindex(full_time_range).bfill().ffill()['Value'].values # 4. 返回成横向的value1~value14400序列 return pd.Series(filled, index=[f'value{i+1}' for i in range(14400)]) # 执行处理并拼接结果 final_result = pd.concat( [df1.drop(columns=['start_ts', 'end_ts']), df1.apply(generate_time_features, axis=1)], axis=1 )
大数据量优化方案
如果你的df1记录数过万、df2数据量超过百万级,逐行apply效率较低,可以用预关联+分组的方式提速:
# 先按Id关联两个表,再过滤符合时间范围的记录 merged_df = df2.merge(df1[['Id', 'Date', 'start_ts', 'end_ts']], on='Id', how='inner') merged_df = merged_df[ (merged_df['Timestamp'] >= merged_df['start_ts']) & (merged_df['Timestamp'] <= merged_df['end_ts']) ] # 按Id+Date分组处理每个组的时间序列 def process_group(group): # 取当前组对应的时间窗口 group_info = df1[(df1['Id'] == group.name[0]) & (df1['Date'] == group.name[1])].iloc[0] full_time_range = pd.date_range(start=group_info['start_ts'], end=group_info['end_ts'], freq='1min') resampled = group.set_index('Timestamp')['Value'].resample('1min').mean() filled = resampled.reindex(full_time_range).bfill().ffill().values return pd.Series(filled, index=[f'value{i+1}' for i in range(14400)]) # 生成时间特征列后和df1拼接 value_features = merged_df.groupby(['Id', 'Date']).apply(process_group).reset_index() final_result = df1.drop(columns=['start_ts', 'end_ts']).merge(value_features, on=['Id', 'Date'], how='left')
注意事项
- 若某条记录在对应时间范围内完全没有匹配的
Value数据,填充后所有value列会是NaN,可根据业务需求额外加fillna(默认值)处理 - 1分钟重采样的聚合规则可自行调整,比如需要取每分钟第一个值,把
mean()替换为first()即可 - 用左连接可保留
df1的所有原始记录,即使没有匹配到df2的数据
内容的提问来源于stack exchange,提问作者nilsinelabore
相关产品推荐
相关产品推荐

