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

Pandas按id匹配正负金额后筛选name字符串相似度最高行对的方法

实现思路

  1. 对筛选后的DataFrame按id分组,每组内拆分出正金额、负金额两个子集
  2. 遍历每组内的所有正金额行,针对每个正金额,筛选出组内金额为其相反数的所有负金额候选行
  3. 计算当前正金额行的name与所有候选负金额行name的字符串相似度,保留相似度最高的负金额行
  4. 收集所有保留的正负行对的索引,去重后取出对应行即为最终结果

完整可运行代码

import pandas as pd
from difflib import SequenceMatcher

# 字符串相似度计算函数,可按需替换为Jaccard等其他指标
def calc_str_similarity(a, b):
    return SequenceMatcher(None, a, b).ratio()

def filter_best_match(df_group):
    # 拆分当前组正负金额行
    pos_df = df_group[df_group['amount'] > 0].reset_index()
    neg_df = df_group[df_group['amount'] < 0].reset_index()
    keep_indices = set()
    
    for _, pos_row in pos_df.iterrows():
        target_neg_amount = -pos_row['amount']
        # 筛选金额匹配的负金额候选行
        candidates = neg_df[neg_df['amount'] == target_neg_amount]
        if candidates.empty:
            continue
        # 计算所有候选的相似度,取最高的配对
        candidates['sim'] = candidates['name'].apply(lambda x: calc_str_similarity(pos_row['name'], x))
        best_neg = candidates.sort_values('sim', ascending=False).iloc[0]
        # 记录配对行的原始索引
        keep_indices.add(pos_row['index'])
        keep_indices.add(best_neg['index'])
    # 返回当前组保留的行
    return df_group.loc[list(keep_indices)]

# 对已经筛选过互为正负的df1按id分组处理
result = df1.groupby('id', group_keys=False).apply(filter_best_match).sort_index()
print(result)

说明

如果需要替换为Jaccard相似度,仅需修改calc_str_similarity函数即可,参考实现:

def calc_str_similarity(a, b):
    set_a, set_b = set(a), set(b)
    return len(set_a & set_b) / len(set_a | set_b)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 22:45:01