【问题标题】:Python: Select single minimum-distance pair based not only on values, but also on other participants minimum-distance pairsPython:不仅根据值,还根据其他参与者的最小距离对选择单个最小距离对
【发布时间】:2026-01-15 18:20:07
【问题描述】:

例如,我有两个实体列表和一个测量它们之间距离的函数。 假设它是名称和电子邮件。在下表中,我测量了每封电子邮件与每个姓名的距离。

    1@ - {A:0.2, B:0.3, C:0.4, D:0.6}
    2@ - {A:0.15, B:0.2, C:0.2, D:0.5}
    3@ - {A:0.1, B:0.05, C:0.03, D:0.2}

现在我想为名称中的每个电子邮件找到单个最小距离对。但是,请注意,如果两个电子邮件具有相同的最小距离候选名称,则距离最小的人获胜。在这种情况下,另一封电子邮件应该选择第二个最接近的候选名称并再次检查。

所以,在这种情况下,结果应该是:

    1@: B  
    2@: A
    3@: C

表格说明:

emails/names A B C D
1@ 0.2 0.3 0.4 0.6
2@ 0.15 0.2 0.2 0.5
3@ 0.1 0.05 0.03 0.2

速度很重要。它可以以数据帧或字典的形式处理,没关系。
感谢您的帮助。


更新:

当Email数量>Names数量时有可能,所以有些Email会被unassign,也需要catch。

【问题讨论】:

    标签: python pandas loops dictionary


    【解决方案1】:

    假设你有这个数据框:

      emails/names     A     B     C    D
    0           1@  0.20  0.30  0.40  0.6
    1           2@  0.15  0.20  0.20  0.5
    2           3@  0.10  0.05  0.03  0.2
    

    然后:

    df = df.set_index("emails/names")
    numpy_df = df.to_numpy()
    
    forbidden_rows, forbidden_cols = [], []
    while len(forbidden_rows) != len(df):
        row, col = np.unravel_index(numpy_df.argmin(), df.shape)
        numpy_df[:, col] = np.inf
        numpy_df[row, :] = np.inf
        forbidden_rows.append(df.index[row])
        forbidden_cols.append(df.columns[col])
    
    for r, c in zip(forbidden_rows, forbidden_cols):
        print(r, c)
    

    打印:

    3@ C
    2@ A
    1@ B
    

    编辑:首先将数据帧转换为numpy.ndarray


    编辑:打印未分配的电子邮件:

    对于这个数据框:

      emails/names     A     B     C    D
    0           1@  0.20  0.30  0.40  0.6
    1           2@  0.15  0.20  0.20  0.5
    2           3@  0.10  0.05  0.03  0.2
    3           4@  0.10  0.05  0.03  0.2
    4           5@  0.11  0.25  0.43  0.2
    5           6@  0.12  0.35  0.53  0.3
    

    这个:

    df = df.set_index("emails/names")
    numpy_df = df.to_numpy()
    
    forbidden_rows, forbidden_cols = [], []
    while len(forbidden_rows) != len(df) and len(forbidden_cols) != len(df.columns):
        row, col = np.unravel_index(numpy_df.argmin(), df.shape)
        numpy_df[:, col] = np.inf
        numpy_df[row, :] = np.inf
        forbidden_rows.append(df.index[row])
        forbidden_cols.append(df.columns[col])
    
    for r, c in zip(forbidden_rows, forbidden_cols):
        print(r, c)
    
    print("Unassigned emails:")
    print(df.index[~df.index.isin(forbidden_rows)].values)
    

    打印:

    3@ C
    4@ B
    5@ A
    6@ D
    Unassigned emails:
    ['1@' '2@']
    

    【讨论】:

    • 哇,很酷的解决方案!我仍然需要一些时间来处理它,了解 np.unravel_index 的工作原理,但解决方案似乎是正确的。谢谢。
    • @Oleksii 我“借用”了这个:*.com/questions/3230067/…
    • 另一个请求 - 有时可能是电子邮件多于名称时的情况。如何捕获此类“未分配”的电子邮件?
    最近更新 更多