如何从我的熊猫数据框中获取最多的配对?

时间:2019-01-23 14:29:03

标签: python dataframe graph matching

我有一个数据框,该数据框为每一行显示一对人类(名称_1和名称_2)以及相应的分数。分数是一个数值,表示这两个人在一起的程度。分数越高,人员1(名称_1)和人员2(名称_2)之间的匹配越好。

如您所见,某些名称可以找到两次或更多次。当然,一个人只能配对一次。我的目标是在数据框中找到尽可能多的对,并将每个对写入第二个数据框中。

让我挣扎的问题是:

我想我能得到最大的收获。由于我在第一栏中有8个不同的名称,因此数据框中有8对。不幸的是,最佳比赛的分数并没有明确分开。一个人可以与多个其他人匹配,而其他人只能与一个特定人匹配。我对匹配分数没有太大兴趣。我有兴趣不因配对失败而失去任何人。

我正在寻找一种查找和提取尽可能多的数据框对的方法。

这是数据框df:

      name_1     name_2  score
27      allen      jolly    1.8
23       anna       rock    2.8
22       anna  christina    1.1
26  christina       rock    2.3
24  christina      allen    1.4
25  christina      jolly    1.4
18      emily       rock    3.7
15      emily  sabastein    3.3
16      emily       anna    2.5
17      emily  christina    2.4
4       jacob      jolly    3.4
1       jacob       rick    2.9
3       jacob      allen    2.4
0       jacob       mary    2.3
2       jacob  christina    2.0
7        mary      jolly    1.7
5        mary       rick    1.4
6        mary  christina    1.3
14       rick       rock    2.8
9        rick  sabastein    2.8
8        rick      emily    2.5
13       rick      jolly    2.3
11       rick  christina    2.1
10       rick       anna    2.0
12       rick      allen    1.5
21  sabastein       rock    3.6
19  sabastein       anna    2.8
20  sabastein  christina    1.9

我认为就最高总分而言,最佳匹配是:

emely       rock        3.7
jacob       jolly       3.4
sabastein   anna        2.8
rick        allen       1.5
mary        christina   1.3 

我不确定这是否也是我可以获得的最大对数。如果您知道如何获得最佳配对(见上文)或最大配对数,我将非常高兴看到。

1 个答案:

答案 0 :(得分:1)

EDIT
同时,我发现了一个非常方便的功能,可以从数据框创建图形,但是您应该为此将列score重命名为weight
您可以简单地写:

G = nx.from_pandas_edgelist(df, 'name_1', 'name_2', 'weight')
mate = nx.max_weight_matching(G)

就是这样。
Rest仍然是我们下面讨论的一部分,您如何在...上进一步处理结果...


我的方法是

import pandas as pd
import networkx as nx

df['edges'] = df.apply(lambda r: (r.name_1, r.name_2, {'weight': r.score}), axis=1)

G = nx.Graph()

allnames = set(df.loc[:, ['name_1', 'name_2']].values.flatten())

for s in allnames:
    G.add_node(s)
G.add_edges_from(df.edges)

mate = nx.max_weight_matching(G)

结果:

res = pd.DataFrame(list(mate), columns=['name_1', 'name_2'])
res['score'] = res.apply(lambda r: G[r[0]][r[1]]['weight'], axis=1)

print(res)
print(f'\nMatchings: {len(res)}\nTotal Score: {res.score.sum():.1f}')            

#      name_1     name_2  score
#0       rock      emily    3.7                            
#1       rick  christina    2.1                          
#2       mary      jacob    2.3                            
#3  sabastein       anna    2.8                           
#4      jolly      allen    1.8                                             
#Matchings: 5                                                
#Total Score: 12.7      

DocSources:
对于设置图,您已经具有正确的链接。
有关maximum_matching函数,请参见此处https://networkx.github.io/documentation/networkx-1.10/reference/generated/networkx.algorithms.matching.max_weight_matching.html#networkx.algorithms.matching.max_weight_matching