2017-09-15 1 views
0

J'ai un graphe orienté (bipartite) où une entité légale est connectée par un bord à chaque candidat qu'elle a parrainé ou coparrainé. A partir de là, je veux un second (unipartite), non orienté, G, projeté à partir du premier dans lequel les nœuds sont candidats et les bords les reliant entre eux indiquent combien de fois ils ont reçu de l'argent ensemble de la même entité légale.Amélioration de la création d'un graphe non orienté projeté à partir d'un graphe orienté en utilisant Python

Toutes les informations sont codées dans une trame candidate_donator où chaque candidat est associé à un tuple contenant un donneur.

J'utilise Networkx pour créer le réseau et pour optimiser ma mise en œuvre car cela prend beaucoup de temps. Mon approche originale est:

candidate_donator = df.groupby('candidate').agg({'donator': lambda x: tuple(set(x))}) 

import itertools 
candidate_pairs= list(itertools.combinations(candidate_donator .index, 2)) #creating all possible unique combinations of pair candidates ~83 M 

for cpf1, cpf2 in candidate_pairs: 
    donators_filter = list(filter(set(candidate_pairs.loc[cpf1]).__contains__, candidate_pairs.loc[cpf2])) 
    G.add_edge(cpf1, cpf2, weight = len(donators_filter))  
+1

Certainement précalculer les bords, puis les ajouter en une seule fois au graphique. Chaque fois que vous ajoutez un bord au graphique, l'objet graphique entier est copié. – Paul

+0

En outre, quel est votre ratio entre le nombre total de donateurs uniques et le nombre total de candidats (uniques)? – Paul

Répondre

1

Essayez ceci:

#list of donators per candidate 
candidate_donator = df.groupby('candidate').agg({'donator': lambda x: tuple(set(x))}) 
#list of candidates per donator 
donator_candidate = df.groupby('donator').agg({'candidate': lambda x: tuple(set(x))}) 

#for each candidate 
for candidate_idx in candidate_donator.index: 
    #for each donator connected to this candidate 
    for donator_list in candidate_donator.loc[candidate_idx, 'donator']: 
     for last_candidate in donator_list: 
      #existing edge, add weight 
      if G.has_edge(candidate_idx, last_candidate): 
       G[candidate_idx][last_candidate] += 0.5 
      #non existing edge, weight = 0.5 (every edge will be added twice) 
      else: 
       G.add_edge(candidate_idx, last_candidate, weight = 0.5)