NetworkX - 如何从 Shapefile 创建 MultiDiGraph?
NetworkX - How to create MultiDiGraph from Shapefile?
我刚刚开始使用 NetworkX 并尝试学习如何将它与 Shapefile 一起使用。
现在我有一个带有道路网络的 .shp,我想用 NetworkX 在图表中表示它,这样我就可以找到 2 个 GPS 点之间的最短路径。我尝试使用 this,但问题是,当我 运行 write_shp() 函数时,我丢失了边,因为有向图不允许相同的两个节点之间存在多条边。下图中的箭头显示了我使用有向图丢失的边的示例。
所以我想知道是否有任何方法可以创建 MultiDiGraph 这样我就不会丢失任何边,或者是否有任何方法可以使用它。我在想也许我可以编写一些代码来从 Shapefile 中提取属性并在不使用 NetworkX 的 read_shp() 的情况下创建 MultiDiGraph,但是我没有任何使用图形的经验,所以我不是完全确定这是否可能。
非常感谢您能给我的任何帮助或指导,或者如果我遗漏了任何文档,请告诉我。提前致谢。
尽我所能从你的问题中得到答案,下面将执行此操作,基本上是从原始 read_shp
命令复制而来。
def read_multi_shp(path):
"""
copied from read_shp, but allowing MultiDiGraph instead.
"""
try:
from osgeo import ogr
except ImportError:
raise ImportError("read_shp requires OGR: http://www.gdal.org/")
net = nx.MultiDiGraph() # <--- here is the main change I made
def getfieldinfo(lyr, feature, flds):
f = feature
return [f.GetField(f.GetFieldIndex(x)) for x in flds]
def addlyr(lyr, fields):
for findex in xrange(lyr.GetFeatureCount()):
f = lyr.GetFeature(findex)
flddata = getfieldinfo(lyr, f, fields)
g = f.geometry()
attributes = dict(zip(fields, flddata))
attributes["ShpName"] = lyr.GetName()
if g.GetGeometryType() == 1: # point
net.add_node((g.GetPoint_2D(0)), attributes)
if g.GetGeometryType() == 2: # linestring
attributes["Wkb"] = g.ExportToWkb()
attributes["Wkt"] = g.ExportToWkt()
attributes["Json"] = g.ExportToJson()
last = g.GetPointCount() - 1
net.add_edge(g.GetPoint_2D(0), g.GetPoint_2D(last), attr_dict=attributes) #<--- also changed this line
if isinstance(path, str):
shp = ogr.Open(path)
lyrcount = shp.GetLayerCount() # multiple layers indicate a directory
for lyrindex in xrange(lyrcount):
lyr = shp.GetLayerByIndex(lyrindex)
flds = [x.GetName() for x in lyr.schema]
addlyr(lyr, flds)
return net
我将返回的图表从 DiGraph
更改为 MultiDigraph
,并且我不得不更改 add_edge
命令,因为 MultiDiGraph
版本的语法与 DiGraph
如果多线在接头处断开,我想这个库python-s2g
(https://github.com/caesar0301/python-s2g)可以帮到你。连networkx的Graph对象都用在了hood下,那些多路径其实都是由graph数据记录的。
我在这里实现了一个解决方案:https://gitlab.com/njacadieux/upstream_downstream_shortests_path_dijkstra
我使用 GeoPandas 而不是 networkx.readwrite.nx_shp.read_shp 读取了 shapefile。当我构建图形时,我检查平行边。如果找到,而不是像 networkx.readwrite.nx_shp.read_shp 函数那样跳过它们,我将平行边分成两条等长的边,然后将用户长度除以 2。必须给出用户长度变量字段名称。
我刚刚开始使用 NetworkX 并尝试学习如何将它与 Shapefile 一起使用。
现在我有一个带有道路网络的 .shp,我想用 NetworkX 在图表中表示它,这样我就可以找到 2 个 GPS 点之间的最短路径。我尝试使用 this,但问题是,当我 运行 write_shp() 函数时,我丢失了边,因为有向图不允许相同的两个节点之间存在多条边。下图中的箭头显示了我使用有向图丢失的边的示例。
所以我想知道是否有任何方法可以创建 MultiDiGraph 这样我就不会丢失任何边,或者是否有任何方法可以使用它。我在想也许我可以编写一些代码来从 Shapefile 中提取属性并在不使用 NetworkX 的 read_shp() 的情况下创建 MultiDiGraph,但是我没有任何使用图形的经验,所以我不是完全确定这是否可能。
非常感谢您能给我的任何帮助或指导,或者如果我遗漏了任何文档,请告诉我。提前致谢。
尽我所能从你的问题中得到答案,下面将执行此操作,基本上是从原始 read_shp
命令复制而来。
def read_multi_shp(path):
"""
copied from read_shp, but allowing MultiDiGraph instead.
"""
try:
from osgeo import ogr
except ImportError:
raise ImportError("read_shp requires OGR: http://www.gdal.org/")
net = nx.MultiDiGraph() # <--- here is the main change I made
def getfieldinfo(lyr, feature, flds):
f = feature
return [f.GetField(f.GetFieldIndex(x)) for x in flds]
def addlyr(lyr, fields):
for findex in xrange(lyr.GetFeatureCount()):
f = lyr.GetFeature(findex)
flddata = getfieldinfo(lyr, f, fields)
g = f.geometry()
attributes = dict(zip(fields, flddata))
attributes["ShpName"] = lyr.GetName()
if g.GetGeometryType() == 1: # point
net.add_node((g.GetPoint_2D(0)), attributes)
if g.GetGeometryType() == 2: # linestring
attributes["Wkb"] = g.ExportToWkb()
attributes["Wkt"] = g.ExportToWkt()
attributes["Json"] = g.ExportToJson()
last = g.GetPointCount() - 1
net.add_edge(g.GetPoint_2D(0), g.GetPoint_2D(last), attr_dict=attributes) #<--- also changed this line
if isinstance(path, str):
shp = ogr.Open(path)
lyrcount = shp.GetLayerCount() # multiple layers indicate a directory
for lyrindex in xrange(lyrcount):
lyr = shp.GetLayerByIndex(lyrindex)
flds = [x.GetName() for x in lyr.schema]
addlyr(lyr, flds)
return net
我将返回的图表从 DiGraph
更改为 MultiDigraph
,并且我不得不更改 add_edge
命令,因为 MultiDiGraph
版本的语法与 DiGraph
如果多线在接头处断开,我想这个库python-s2g
(https://github.com/caesar0301/python-s2g)可以帮到你。连networkx的Graph对象都用在了hood下,那些多路径其实都是由graph数据记录的。
我在这里实现了一个解决方案:https://gitlab.com/njacadieux/upstream_downstream_shortests_path_dijkstra
我使用 GeoPandas 而不是 networkx.readwrite.nx_shp.read_shp 读取了 shapefile。当我构建图形时,我检查平行边。如果找到,而不是像 networkx.readwrite.nx_shp.read_shp 函数那样跳过它们,我将平行边分成两条等长的边,然后将用户长度除以 2。必须给出用户长度变量字段名称。