Python: Graph using NetworkX and mplleaflet

2019-05-31 21:59发布

问题:

I have a networkx graph created from edges such as these:

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]]"

Example

Where the edges are a user's movements between clusters, identified by their cluster label, e.g., [[340, 269], [269, 340]]. This represents a user's movement from cluster 340 to cluster 269 and then back to cluster 340. These clusters have coordinates, stored in another file, in the form of latitude and longitude, such as these:

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

Is it possible to link the edges of my graph to their respective cluster in physical space using the node/cluster's lat/long and not in the abstract space of a graph? If so, how might I go about doing so? I would like to graph this on a map using a package such as mplleaflet (like shown here: http://htmlpreview.github.io/?https://github.com/jwass/mplleaflet/master/examples/readme_example.html) or directly into QGIS/ArcMap.

EDIT

I'm attempting to convert my csv with cluster centroid coordinates into a dictionary, however, I've run into several errors. Mainly, NetwotkXError: Node 0 has no position and IndexError: too many indices for array. Below is how I'm trying to convert to a dict and then graph with mplleaflet.

import csv
import networkx as nx
import pandas as pd
import matplotlib.pyplot as plt
import time
import mplleaflet


g = nx.Graph()

# Set node positions as a dictionary
df = pd.read_csv('G:\Programming Projects\GGS 681\dmv_tweets_20170309_20170314_cluster_centroids.csv', delimiter=',')
df.set_index('cluster_label', inplace=True)
dict_pos = df.to_dict(orient='index')
#print dict_pos

for row in csv.reader(open('G:\Programming Projects\GGS 681\dmv_tweets_20170309_20170314_edges.csv', 'r')):
    if '[' in row[1]:       #
        g.add_edges_from(eval(row[1]))

# Plotting with matplotlib
#nx.draw(g, with_labels=True, alpha=0.15, arrows=True, linewidths=0.01, edge_color='r', node_size=250, node_color='k')
#plt.show()

# Plotting with mplleaflet
fig, ax = plt.subplots()

nx.draw_networkx_nodes(g,pos=dict_pos,node_size=10)
nx.draw_networkx_edges(g,pos=dict_pos,edge_color='gray', alpha=.1)
nx.draw_networkx_labels(g,dict_pos, label_pos =10.3)
mplleaflet.display(fig=ax.figure)

回答1:

yes it is quite easily possible. Try something along this lines. Create a dictionary, where the node (cluster_label) is the key and longitude latitude are saved as values in a list. I would use pd.read_csv() to read the csv and then use the df.to_dict() to create the dictionary. It should look like this for example:

 dic_pos = {u'0': [-77.51885109, 39.18193382],
 u'1': [-76.6688633, 39.18],
 u'2': [-77.2617, 39.1791792],
 u'3': [-77.1927, 39.1782],
 .....

Then plotting the graph on a map is as easy as:

import mplleaflet

fig, ax = plt.subplots()

nx.draw_networkx_nodes(GG,pos=dic_pos,node_size=10,node_color='red',edge_color='k',alpha=.5, with_labels=True)
nx.draw_networkx_edges(GG,pos=dic_pos,edge_color='gray', alpha=.1)
nx.draw_networkx_labels(GG,pos=dic_pos, label_pos =10.3)

mplleaflet.display(fig=ax.figure) 

If it does not produce the expected result try to reverse latitude,longitude.