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

基于双条件的Pandas查找并获取首个匹配值的实现方案

Pandas按区间匹配取值并填充默认值

需求说明

为df2的每个day值,从df中匹配满足day1 <= day且day2 > day的记录:

  • 若存在多个匹配,取第一个匹配的value
  • 无匹配时填充0

给定数据

import pandas as pd

df = pd.DataFrame({'day1': [3, 7, 15], 'day2': [20, 15, 11], 'value': [10, 20, 30]})
df2 = pd.DataFrame({'day': [2, 8, 15, 22]})

预期结果:df2新增的value列值为[0, 10, 10, 0]

实现思路与代码

方法一:基于apply完成匹配(贴合你的现有思路)

你已经完成了筛选匹配行的逻辑,只需补充提取首个匹配值、无匹配返回0的逻辑即可:

def get_matching_value(x):
    # 筛选满足条件的行
    matched_rows = df[(df['day1'] <= x) & (df['day2'] > x)]
    # 存在匹配则取第一个value,否则返回0
    return matched_rows['value'].iloc[0] if not matched_rows.empty else 0

df2['value'] = df2['day'].apply(get_matching_value)

方法二:用idxmax标记首个匹配(符合你的猜测方向)

通过构造布尔匹配矩阵,用argmax()定位每行首个匹配的位置,再映射值并填充0:

# 构造df2每个day与df所有行的匹配布尔矩阵
match_matrix = (df['day1'].values <= df2['day'].values[:, None]) & (df['day2'].values > df2['day'].values[:, None])
# 找到每行第一个匹配的索引,无匹配的行标记为-1
first_match_idx = match_matrix.argmax(axis=1)
first_match_idx[~match_matrix.any(axis=1)] = -1
# 映射value值,无匹配时填充0
df2['value'] = df['value'].iloc[first_match_idx].fillna(0).values

方法三:高效批量匹配(适合大数据量场景)

如果数据量较大,apply效率偏低,可使用merge_asof结合预处理实现批量匹配:

# 先对两个数据集按关联字段排序
df_sorted = df.sort_values('day1').reset_index(drop=True)
df2_sorted = df2.sort_values('day').reset_index(drop=True)

# 用merge_asof找到每个day对应的最大day1不超过day的行
merged = pd.merge_asof(df2_sorted, df_sorted, left_on='day', right_on='day1', direction='backward')
# 筛选day2 > day的有效匹配,无效匹配填0
merged['value'] = merged.apply(lambda row: row['value'] if row['day2'] > row['day'] else 0, axis=1)
# 恢复df2原有的行顺序
df2['value'] = merged.set_index(df2_sorted.index)['value'].reindex(df2.index)

运行任意方法后,df2的结果均符合预期:

day  value
0    2      0
1    8     10
2   15     10
3   22      0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 09:10:34