Python:不仅基于值,而且基于其他参与者的最小距离对来选择单个最小距离对

Python:不仅基于值,而且基于其他参与者的最小距离对来选择单个最小距离对,python,pandas,loops,dictionary,Python,Pandas,Loops,Dictionary,例如,我有两个实体列表和一个测量它们之间距离的函数。 比如说它的名字和电子邮件。在下表中,我测量了每封电子邮件与每个名字的距离 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@ - {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
解释表:

电子邮件/姓名 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
假设您拥有此数据帧:

电子邮件/姓名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@C
2@A
1@B
编辑:首先将数据帧转换为
numpy.ndarray


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

对于此数据帧:

电子邮件/姓名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
这:

印刷品:

3@C
4@B
5@A
6@D
未分配的电子邮件:
['1@' '2@']

哇,很酷的解决方案!我仍然需要一些时间来处理它,理解np.unravel_索引是如何工作的,但解决方案似乎是正确的。谢谢。@Oleksii我“借用”了这句话:还有一个请求——有时可能是电子邮件多于姓名。如何捕获这些“未分配的”电子邮件?@Oleksii查看我的编辑
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)
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)