基于时间戳与数值范围合并两个DataFrame的技术问询
嘿,这个需求我之前处理过类似的,你选merge_asof方向是对的,但因为还要结合数值区间匹配,得稍微调整下步骤,我给你拆解清楚:
核心思路
先把DataFrame B的生效时间区间明确出来(毕竟规则是从某个时间点开始生效,直到下一个规则生效前一刻),再用merge_asof匹配A的时间落在哪个规则生效区间里,最后筛选出符合value_A数值范围的记录。
完整代码实现
先构造示例数据(你可以替换成自己的真实数据):
import pandas as pd # 示例DataFrame A:带时间戳和数值 df_a = pd.DataFrame({ 'creation_time': pd.to_datetime(['2023-01-01 10:00', '2023-01-02 14:00', '2023-01-03 09:00', '2023-01-04 16:00']), 'value_A': [15, 35, 25, 45] }) # 示例DataFrame B:带数值区间、生效时间和对应value_B df_b = pd.DataFrame({ 'value_A_range': ['0-20', '21-40', '41-60', '0-30', '31-60'], 'creation_time': pd.to_datetime(['2023-01-01 00:00', '2023-01-01 00:00', '2023-01-01 00:00', '2023-01-03 00:00', '2023-01-03 00:00']), 'value_B': ['low', 'medium', 'high', 'low_new', 'high_new'] })
步骤1:预处理DataFrame B
把数值区间拆成上下限,同时生成每个规则的生效结束时间:
# 拆分value_A_range为数值型的上下限 df_b[['range_low', 'range_high']] = df_b['value_A_range'].str.split('-', expand=True).astype(int) # 按生效时间排序,为每个规则计算结束时间(下一个规则生效的前1秒) df_b_sorted = df_b.sort_values('creation_time') df_b_sorted['end_time'] = df_b_sorted['creation_time'].shift(-1) - pd.Timedelta(seconds=1) # 最后一个规则的结束时间设为最大时间戳,确保覆盖后续所有记录 df_b_sorted['end_time'] = df_b_sorted['end_time'].fillna(pd.Timestamp.max)
步骤2:用merge_asof匹配时间区间
merge_asof要求左右DataFrame都按匹配的时间列排序,所以先给A排序:
df_a_sorted = df_a.sort_values('creation_time') # 匹配A的creation_time落在B的[creation_time, end_time]区间内的所有规则 merged = pd.merge_asof(df_a_sorted, df_b_sorted, on='creation_time', direction='backward')
这里direction='backward'的作用是:给A的每条记录匹配不晚于当前时间的最新生效规则,刚好符合你的需求。
步骤3:筛选符合数值区间的记录
此时merge后的结果会包含同一时间生效的所有数值区间,我们需要过滤出value_A落在对应区间的那条:
# 筛选value_A在[range_low, range_high]范围内的记录 result = merged[(merged['value_A'] >= merged['range_low']) & (merged['value_A'] <= merged['range_high'])] # 整理成最终需要的结果集 final_result = result[['creation_time', 'value_A', 'value_B']].sort_values('creation_time').reset_index(drop=True) print(final_result)
运行后你会得到这样的结果:
creation_time value_A value_B 0 2023-01-01 10:00:00 15 low 1 2023-01-02 14:00:00 35 medium 2 2023-01-03 09:00:00 25 low_new 3 2023-01-04 16:00:00 45 high_new
几个注意点
- 如果DataFrame B里存在同一生效时间+同一数值区间的重复记录,记得先通过
df_b.drop_duplicates(subset=['creation_time', 'value_A_range'], keep='last')去重 - 如果A的记录早于B中最早的生效时间,
merge_asof会返回NaN,你可以根据需求用fillna填充默认值,或者直接过滤掉这些记录 - 如果数值区间是左开或右开的,记得调整筛选条件(比如把
>=改成>)
内容的提问来源于stack exchange,提问作者dank
相关产品推荐
相关产品推荐

