如何从 NetwokX / OSMnx 导出并返回?

How to export from NetwokX / OSMnx and back?

我希望能够将 OSMnx 制作的图形(换句话说,NetworkX 图形)导出到 CSV 中,并在以后调用它。找不到任何好的方法,所以我尝试将它导出到 Numpy / Pandas 并导出它。 所以我建立了这个小例子:

import networkx as nx
import osmnx as ox
G = ox.graph_from_place('Bar Ilan University, Israel')
F = nx.to_numpy_matrix(G)
G = nx.from_numpy_matrix(F, create_using=nx.MultiDiGraph)
ox.plot.plot_graph(G)

它 returns 这个错误似乎没有任何帮助:

--------------------------------------------------------------------------- TypeError Traceback (most recent call last) in 4 F = nx.to_numpy_matrix(G) 5 G = nx.from_numpy_matrix(F, create_using=nx.MultiDiGraph) ----> 6 ox.plot.plot_graph(G)

~\Anaconda3\envs\ox\lib\site-packages\osmnx\plot.py in plot_graph(G, bbox, fig_height, fig_width, margin, axis_off, equal_aspect, bgcolor, show, save, close, file_format, filename, dpi, annotate, node_color, node_size, node_alpha, node_edgecolor, node_zorder, edge_color, edge_linewidth, edge_alpha, use_geom) 353 354 log('Begin plotting the graph...') --> 355 node_Xs = [float(x) for _, x in G.nodes(data='x')] 356 node_Ys = [float(y) for _, y in G.nodes(data='y')] 357

~\Anaconda3\envs\ox\lib\site-packages\osmnx\plot.py in (.0) 353 354 log('Begin plotting the graph...') --> 355 node_Xs = [float(x) for _, x in G.nodes(data='x')] 356 node_Ys = [float(y) for _, y in G.nodes(data='y')] 357

TypeError: float() argument must be a string or a number, not 'NoneType'

osmnx 图的节点如下所示:

G.nodes(data=True)

NodeDataView({970069268: {'y': 32.0682358, 'x': 34.841011, 'osmid': 970069268}, 970069273: {'y': 32.0722176, 'x': 34.8442006, 'osmid': 970069273}, 970069285: {'y': 32.0695886, 'x': 34.8419506, 'osmid': 970069285, 'highway': 'mini_roundabout'},
[...]
})

将此图转换为邻接矩阵仅保留有关哪些节点已连接的信息,而不是有关各个节点的位置的信息,也不会保留任何其他属性的信息。因此,从邻接矩阵创建的图如下所示:

G.nodes(data=True)

out:
NodeDataView({0: {}, 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {}, 8: {}, 9: {}, 10: {}, 
[...]
})

osmnx 绘图函数尝试检索位置信息:

node_Xs = [float(x) for _, x in G.nodes(data="x")]

但得到 None,这不是预期的格式,因此出现错误。

你能做什么:

将节点信息保存到 csv:

def nodes_to_csv(G, savepath):
    unpacked = [pd.DataFrame({**{'node': node, **data}}, index=[i]) for i, (node, data) in enumerate(G.nodes(data=True))]
    df = pd.concat(unpacked)
    df.to_csv(savepath)
    return df

def nodes_from_csv(path):
    df = pd.read_csv(path, index_col=0)
    nodes = []
    
    for ix , row in df.iterrows():
        d = dict(row)
        node = d.pop('node')
        nodes.append((node, {k:v for k,v in d.items() if v}))
        
    return nodes

#saving and retrieving:
nodes_to_csv(G, 'test.csv')
nodes = nodes_from_csv('test.csv')

# saving the adjacency info is more conveniently done with
# to_pandas_edgelist, because to_numpy_matrix loses the node 
# names as well.
adj_matrix = nx.to_pandas_edgelist(G)


# graph construction:
H = nx.from_pandas_edgelist(adj_matrix, create_using=nx.MultiDiGraph)
H.update(nodes=nodes) # adds node info

# osmnx stores metadata in the .graph attribute
# the plotting function accesses that, so in order
# to use the plotting function, 
# you need to also transfer metadata:
q = G.graph.copy()
H.graph=q

ox.plot.plot_graph(H)

@warped 对如何序列化 to/from CSV 给出了详尽的回答。换个角度,如果你的目标只是序列化to/from磁盘,文件格式(即CSV)不是必需的,那么考虑使用OSMnx的save_graphmlload_graphmlfunctions.