2017-04-26 2 views
3

Ich habe eine MultiDiGraph in networkx erstellt, für die ich Gewichte an den Kanten hinzufügen möchte, nach denen ich ein neues Gewicht basierend auf der Häufigkeit/Anzahl der zuweisen Randvorkommen. Ich habe den folgenden Code die Grafik zu erstellen und Gewichte hinzufügen, aber ich bin nicht sicher, wie Gewichte zu bewältigen basierend Neuzuweisung auf Zahl:Python/NetworkX: Hinzufügen von Gewichten zu Kanten nach Häufigkeit der Kanten

g = nx.MultiDiGraph() 

df = pd.read_csv('G:\cluster_centroids.csv', delimiter=',') 
df['pos'] = list(zip(df.longitude,df.latitude)) 
dict_pos = dict(zip(df.cluster_label,df.pos)) 
#print dict_pos 


for row in csv.reader(open('G:\edges.csv', 'r')): 
    if '[' in row[1]:  # 
     g.add_edges_from(eval(row[1])) 

for u, v, d in g.edges(data=True): 
    d['weight'] = 1 
for u,v,d in g.edges(data=True): 
    print u,v,d 

bearbeiten

ich in der Lage war, um erfolgreich Gewichte zuweisen jede Kante, erster Teil meiner ursprünglichen Frage, mit folgendem:

for u, v, d in g.edges(data=True): 
    d['weight'] = 1 
for u,v,d in g.edges(data=True): 
    print u,v,d 

ich bin aber nach wie vor nicht in der Lage Gewichte neu zuweisen basierend auf der Anzahl, wie oft eine Kante (eine einzige Kante in meinem Diagramm auftritt, kann mehrfach auftreten,) Ich muss dies erreichen, um Kanten mit einer höheren Zählung anders als Kanten mit einer niedrigeren Zählung (mit Kantenfarbe oder Breite) zu visualisieren. Ich bin mir nicht sicher, wie mit der Neuzuweisung von Gewichtungen basierend auf der Anzahl verfahren werden soll. Im Folgenden finden Sie Beispieldaten und Links zu meinem vollständigen Datensatz.

Daten

Probe Zentroide (Knoten):

cluster_label,latitude,longitude 
0,39.18193382,-77.51885109 
1,39.18,-77.27 
2,39.17917928,-76.6688633 
3,39.1782,-77.2617 
4,39.1765,-77.1927 
5,39.1762375,-76.8675441 
6,39.17468,-76.8204499 
7,39.17457332,-77.2807235 
8,39.17406072,-77.274685 
9,39.1731621,-77.2716502 
10,39.17,-77.27 

Beispiel Kanten:

user_id,edges 
11011,"[[340, 269], [269, 340]]" 
80973,"[[398, 279]]" 
608473,"[[69, 28]]" 
2139671,"[[382, 27], [27, 285]]" 
3945641,"[[120, 422], [422, 217], [217, 340], [340, 340]]" 
5820642,"[[458, 442]]" 
6060732,"[[291, 431]]" 
6912362,"[[68, 27]]" 
7362602,"[[112, 269]]" 

Voll Daten:

Zentroide (Knoten): https://drive.google.com/open?id=0B1lvsCnLWydEdldYc3FQTmdQMmc

Kanten: https://drive.google.com/open?id=0B1lvsCnLWydEdEtfM2E3eXViYkk

UPDATE

I war in der Lage, zumindest zeitweise durch Gewicht hohe Ränder, das Problem der übermäßig disproportional Kantenbreiten zu lösen, indem ein minLineWidth Einstellung und durch die Multiplikation Gewicht:

minLineWidth = 0.25 

for u, v, d in g.edges(data=True): 
    d['weight'] = c[u, v]*minLineWidth 
edges,weights = zip(*nx.get_edge_attributes(g,'weight').items()) 

und Verwendung in width=[d['weight'] for u,v, d in g.edges(data=True)]nx.draw_networkx_edges() wie unten in der Lösung bereitgestellt.

Zusätzlich konnte ich Farbe maßstabs mit dem folgenden:

# Set Edge Color based on weight 
values = range(7958) #this is based on the number of edges in the graph, use print len(g.edges()) to determine this 
jet = cm = plt.get_cmap('YlOrRd') 
cNorm = colors.Normalize(vmin=0, vmax=values[-1]) 
scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=jet) 
colorList = [] 

for i in range(7958): 
    colorVal = scalarMap.to_rgba(values[i]) 
    colorList.append(colorVal) 

Und dann das Argument edge_color=colorList in nx.draw_networkx_edges() verwenden.

enter image description here

+0

Bitte geben Sie eine [MCVE]. Wir haben Ihre Eingabedateien nicht, daher ist es für uns schwieriger, mit Ihrem Code zu arbeiten. Extrahieren Sie gerade genug Code, um das Problem zu isolieren. –

+0

Ich entschuldige mich, ich wollte zunächst Proben zur Verfügung stellen. Ich habe Beispiele für beide Dateien sowie Links zu den vollständigen Daten auf Google Drive zur Verfügung gestellt. –

+0

Angenommen, eine Kante zwischen Knoten A und Knoten B erscheint dreimal in Ihren Daten. Wollen Sie mehrere gewichtete Kanten zwischen den Knoten haben (dh es gibt 3 Kanten zwischen A und B und jede hat eine Gewichtung 3), oder möchten Sie eine einzelne gewichtete Kante (dh eine Kante zwischen A und B mit Gewicht 3)) – edo

Antwort

3

dies testen Größe auf.

Hinweis: Ich habe ein Duplikat einer vorhandenen Kante hinzugefügt, um das Verhalten zu zeigen, wenn Wiederholungen in Ihrem Multigraph vorhanden sind.

from collections import Counter 
c = Counter(g.edges()) # Contains frequencies of each directed edge. 

for u, v, d in g.edges(data=True): 
    d['weight'] = c[u, v] 

print(list(g.edges(data=True))) 
#[(340, 269, {'weight': 1}), 
# (340, 340, {'weight': 1}), 
# (269, 340, {'weight': 1}), 
# (398, 279, {'weight': 1}), 
# (69, 28, {'weight': 1}), 
# (382, 27, {'weight': 1}), 
# (27, 285, {'weight': 2}), 
# (27, 285, {'weight': 2}), 
# (120, 422, {'weight': 1}), 
# (422, 217, {'weight': 1}), 
# (217, 340, {'weight': 1}), 
# (458, 442, {'weight': 1}), 
# (291, 431, {'weight': 1}), 
# (68, 27, {'weight': 1}), 
# (112, 269, {'weight': 1})] 

Edit: Um die Grafik mit Kantengewichten als Dicken zu visualisieren, verwenden:

nx.draw_networkx(g, width=[d['weight'] for _, _, d in g.edges(data=True)]) 
+0

Das hat funktioniert, danke. Als eine Seite habe ich erwähnt, dass ich versuche, das Gewicht zu verwenden, um die Kantenbreite oder Farbe zu bestimmen. Wie kann ich Ihre Lösung dazu verwenden? Ich habe versucht, die hier bereitgestellten Lösungen http://stackoverflow.com/questions/17632151/coloring-networkx-edges-based-on-weight?rq=1 und hier http://stackoverflow.com/questions/22967086/colouring-edges -mit-Gewicht-im-Netzwerkx, aber ich habe kein Glück, Ihre Lösung an sie zu schneidern. Danke noch einmal! –

+0

Aktualisiert meine Antwort; sollte deine Frage adressieren. –

+0

Ich habe einen Wertfehler erhalten: 'brauche mehr als 2 Werte zum Entpacken' –

Verwandte Themen