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

为DataFrame按条件赋值:无精确匹配时取更大u_g对应的target值

解决方案:DF2匹配DF1的精确+近似匹配需求

首先咱们先把示例数据构建出来,方便测试验证:

import pandas as pd

# 构建DF1
df1 = pd.DataFrame({
    'spec': ['G1', 'G2', 'WG2', 'WG2', 'WG2', 'WG3', 'WG3', 'SWG3'],
    'u_g': [4.8, 2.1, 1.4, 1.2, 1.0, 0.8, 0.7, 0.7],
    'target': [0.88, 0.76, 0.71, 0.68, 0.52, 0.65, 0.53, 0.31]
})

# 构建DF2
df2 = pd.DataFrame({
    'id': range(1, 12),
    'type': ['WG2', 'WG2', 'WG2', 'G1', 'G1', 'G2', 'SWG3', 'WG3', 'WG3', 'WG2', pd.NA],
    'u_g_1': [1.4, 1.4, 1.0, 4.8, 4.9, 2.1, 0.7, 0.8, 0.7, 1.1, 0]
})

方法一:逐行处理(适合小数据集)

这种方法逻辑直观,容易理解,适合数据量不大的场景:

步骤1:先完成精确匹配

用你之前尝试的merge方法,先拿到所有精确匹配的target,同时保留DF2的所有行:

# 精确匹配,得到初始target列并命名区分
df2_modified = df2.merge(
    df1,
    left_on=['type', 'u_g_1'],
    right_on=['spec', 'u_g'],
    how='left'
).rename(columns={'target': 'target_exact'})

步骤2:预处理DF1分组排序

把DF1按spec分组,每组按u_g升序排序,这样后续找大于u_g_1的最小值会更高效:

df1_grouped = df1.groupby('spec').apply(
    lambda x: x.sort_values('u_g').reset_index(drop=True)
).reset_index(drop=True)

步骤3:编写函数处理非精确匹配行

定义一个函数,给每个没有精确匹配的行找到符合要求的target:

def find_closest_target(row):
    # type为NaN直接返回空值
    if pd.isna(row['type']):
        return pd.NA
    # 获取当前type对应的分组数据
    group = df1_grouped[df1_grouped['spec'] == row['type']]
    if group.empty:
        return pd.NA
    # 筛选出u_g大于当前u_g_1的条目
    candidates = group[group['u_g'] > row['u_g_1']]
    if candidates.empty:
        return pd.NA  # 没有符合条件的,返回空
    # 取u_g最小的那个对应的target
    return candidates.loc[candidates['u_g'].idxmin(), 'target']

步骤4:合并最终结果

把精确匹配的target和补全的target合并,得到最终的结果列:

df2_modified['target'] = df2_modified.apply(
    lambda row: row['target_exact'] if not pd.isna(row['target_exact']) else find_closest_target(row),
    axis=1
)

# 保留需要的列
df2_modified = df2_modified[['id', 'type', 'u_g_1', 'target']]

运行后你会得到符合要求的df2_modified:

id   type  u_g_1 target
0    1    WG2    1.4   0.71
1    2    WG2    1.4   0.71
2    3    WG2    1.0   0.52
3    4     G1    4.8   0.88
4    5     G1    4.9    NaN
5    6     G2    2.1   0.76
6    7   SWG3    0.7   0.31
7    8    WG3    0.8   0.65
8    9    WG3    0.7   0.53
9   10    WG2    1.1   0.68
10  11   <NA>    0.0    NaN

方法二:用merge_asof高效处理(适合大数据集)

如果你的数据量很大,逐行apply会很慢,这时候可以用merge_asof做向量级别的匹配,速度会快很多:

步骤1:拆分精确匹配和剩余行

先把精确匹配的行单独提取出来,剩下的行用近似匹配处理:

# 精确匹配的行
df_exact = df2.merge(df1, left_on=['type', 'u_g_1'], right_on=['spec', 'u_g'], how='inner')
# 剩余需要近似匹配的行
df_remaining = df2[~df2.index.isin(df_exact.index)].copy()

步骤2:排序数据

merge_asof要求左右两边的数据都按匹配键排序,所以先对两个数据集排序:

# 按type和u_g_1排序剩余行
df_remaining_sorted = df_remaining.sort_values(['type', 'u_g_1'])
# 按spec和u_g排序DF1
df1_sorted = df1.sort_values(['spec', 'u_g'])

步骤3:用merge_asof做近似匹配

direction='forward'会找第一个大于等于u_g_1的u_g,之后我们再过滤掉等于的情况,只保留大于的:

df_approx = pd.merge_asof(
    df_remaining_sorted,
    df1_sorted,
    left_on='u_g_1',
    right_on='u_g',
    left_by='type',
    right_by='spec',
    direction='forward'
)

# 过滤掉u_g <= u_g_1的情况(确保是大于的最小值)
df_approx = df_approx[df_approx['u_g'] > df_approx['u_g_1']]

步骤4:合并结果并排序

把精确匹配和近似匹配的结果合并,再按id排序:

df2_modified = pd.concat([df_exact, df_approx], ignore_index=True)
df2_modified = df2_modified.sort_values('id').reset_index(drop=True)
df2_modified = df2_modified[['id', 'type', 'u_g_1', 'target']]

这个方法得到的结果和方法一完全一致,但处理速度会快很多,适合十万级以上的数据量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 08:42:41