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

如何识别DataFrame中合同间的关联关系

合同关联关系提取问题

原始数据

我有一个包含订单及合同编号的DataFrame:

OrdersContract
Order_1Contract_1
Order_1Contract_2
Order_2Contract_1
Order_2Contract_2

合同可关联多个订单,订单也可关联多个合同。

需求

希望获取所有合同间的关联关系,生成以所有合同为索引、其他列展示关联合同的DataFrame,期望输出为以下两种形式之一:

形式一:逗号分隔关联合同

Contract_sourceContract_link
Contract_1Contract_2, Contract_3
Contract_2Contract_1, Contract_3
Contract_3Contract_1, Contract_2
Contract_4Contract_8

形式二:多列展示关联合同

Contract_sourceContract_link_1Contract_link_2
Contract_1Contract_2Contract_3
Contract_2Contract_1Contract_3
Contract_3Contract_1Contract_2
Contract_4Contract_8

已尝试的操作

我已生成一个以订单为索引、合同为列的DataFrame:

df_po = pd.DataFrame(df.loc[:,['Contract Nbr', 'Order']].groupby(by='Order')\
    ['Contract Nbr'].apply(lambda x : list(x.unique()))).reset_index()

对应的表格:

Orders_sourceContract_link
Order_1Contract_1, Contract_2
Order_2Contract_3, Contract_4

还生成了一个以合同为索引、订单为列的DataFrame:

df_contract = pd.DataFrame(df.loc[:,['Contract Nbr', 'Order']].groupby(by='Contract Nbr')\
    ['Order'].apply(lambda x : x.unique())).reset_index()

对应的表格:

Contract_sourceorders_link
Contract_1Order_1, Order_2
Contract_2Order_3, Order_4

尝试创建订单转合同的字典,但写法有误:

dict_orders_to_contract = zip(df_po['Order'], df_po['Contrct Nbr'])

并尝试替换,但代码无法运行:

df_contract['count PO'] = pd.DataFrame(df.loc[:,['Contract Nbr', 'Order']].groupby(by='Contract Nbr')\
    ['Order'].apply(lambda x : x.unique().replace(dict_orders_to_contract ))).reset_index()['Order']

解决方案

步骤1:构建正确的订单-合同映射字典

先修正字典的创建逻辑,让每个订单对应其关联的所有合同列表:

# 构建订单到关联合同列表的字典
dict_order_to_contracts = df_po.set_index('Order')['Contract Nbr'].to_dict()

步骤2:获取每个合同的关联合同

对每个合同,先找到它绑定的所有订单,再通过字典找到这些订单对应的全部合同,最后去重并排除合同自身:

def get_linked_contracts(row):
    current_contract = row['Contract_source']
    linked_orders = row['orders_link']
    # 收集所有关联订单对应的合同
    all_related_contracts = []
    for order in linked_orders:
        all_related_contracts.extend(dict_order_to_contracts[order])
    # 去重并移除当前合同本身
    unique_links = list(set(all_related_contracts) - {current_contract})
    return unique_links

# 修正df_contract的列名
df_contract = df_contract.rename(columns={'Contract Nbr': 'Contract_source', 'Order': 'orders_link'})

# 应用函数生成关联合同列
df_contract['Contract_link'] = df_contract.apply(get_linked_contracts, axis=1)

步骤3:转换为期望的输出形式

形式一:逗号分隔字符串

df_form1 = df_contract[['Contract_source', 'Contract_link']].copy()
df_form1['Contract_link'] = df_form1['Contract_link'].apply(lambda x: ', '.join(x) if x else '')

形式二:多列展示

先找到最大的关联合同数量,再拆分列表为多列:

max_link_count = df_contract['Contract_link'].apply(len).max()
# 生成列名
link_col_names = [f'Contract_link_{i+1}' for i in range(max_link_count)]
# 将列表拆分为多列
link_columns = df_contract['Contract_link'].apply(pd.Series)
link_columns.columns = link_col_names
# 合并到原DataFrame
df_form2 = pd.concat([df_contract[['Contract_source']], link_columns], axis=1)

完整可运行代码

import pandas as pd

# 原始数据
df = pd.DataFrame({
    'Orders': ['Order_1', 'Order_1', 'Order_2', 'Order_2'],
    'Contract': ['Contract_1', 'Contract_2', 'Contract_1', 'Contract_2']
})
# 重命名列匹配代码中的命名
df = df.rename(columns={'Orders': 'Order', 'Contract': 'Contract Nbr'})

# 生成订单-合同映射表
df_po = df.groupby('Order')['Contract Nbr'].apply(lambda x: list(x.unique())).reset_index()

# 生成合同-订单映射表
df_contract = df.groupby('Contract Nbr')['Order'].apply(lambda x: list(x.unique())).reset_index()
df_contract = df_contract.rename(columns={'Contract Nbr': 'Contract_source', 'Order': 'orders_link'})

# 构建订单到合同的字典
dict_order_to_contracts = df_po.set_index('Order')['Contract Nbr'].to_dict()

# 定义获取关联合同的函数
def get_linked_contracts(row):
    current_contract = row['Contract_source']
    linked_orders = row['orders_link']
    all_related_contracts = []
    for order in linked_orders:
        all_related_contracts.extend(dict_order_to_contracts[order])
    unique_links = list(set(all_related_contracts) - {current_contract})
    return unique_links

# 生成关联合同列
df_contract['Contract_link'] = df_contract.apply(get_linked_contracts, axis=1)

# 生成形式一结果
df_form1 = df_contract[['Contract_source', 'Contract_link']].copy()
df_form1['Contract_link'] = df_form1['Contract_link'].apply(lambda x: ', '.join(x) if x else '')

# 生成形式二结果
max_link_count = df_contract['Contract_link'].apply(len).max()
link_col_names = [f'Contract_link_{i+1}' for i in range(max_link_count)]
link_columns = df_contract['Contract_link'].apply(pd.Series)
link_columns.columns = link_col_names
df_form2 = pd.concat([df_contract[['Contract_source']], link_columns], axis=1)

# 打印结果
print("形式一输出:")
print(df_form1)
print("\n形式二输出:")
print(df_form2)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 19:30:56