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)