【问题标题】:NetworkX - How to create MultiDiGraph from Shapefile?NetworkX - 如何从 Shapefile 创建 MultiDiGraph?
【发布时间】:2015-08-26 13:22:45
【问题描述】:

我刚刚开始使用 NetworkX 并尝试学习如何将它与 Shapefile 一起使用。

现在我有一个带有道路网络的 .shp,我想用 NetworkX 在图中表示它,这样我就可以找到 2 个 GPS 点之间的最短路径。我尝试使用this,但问题是当我运行 write_shp() 函数时,我失去了边,因为有向图不允许在相同的两个节点之间有多个边。下图中的箭头显示了我使用有向图丢失的边的示例。

所以我想知道是否有任何方法可以创建 MultiDiGraph,这样我就不会丢失任何边缘,或者是否有任何方法可以使用。我在想也许我可以编写一些代码来从 Shapefile 中提取属性并在不使用 NetworkX 的 read_shp() 的情况下创建 MultiDiGraph,但是我根本没有任何使用图表的经验,所以我不确定它是否有可能。

非常感谢您能给我的任何帮助或指导,或者如果我错过了任何文档,请告诉我。提前致谢。

【问题讨论】:

  • 您能否提供一个最小的工作示例,并显示您想要的输出是什么?从您的问题中我可以看出,一个简单的解决方案是复制链接文档中的read_shp 代码并将net = nx.DiGraph() 更改为net = nx.MultiDiGraph()

标签: python networkx shapefile digraphs


【解决方案1】:

我可以从你的问题中得到最好的结果,下面的就可以了,基本上是从原始的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 不同

【讨论】:

  • 我得到 TypeError: unhashable type: 'dict' in File "C:\Python34\lib\site-packages\networkx\classes\multidigraph.py", line 262, in add_edge keydict= {key:datadict}
  • 您能提供一些示例输入和预期输出吗?然后我可以测试我的答案。
  • 什么意思?我将 read_shp() 与一个 shapefile 一起使用,该文件包含许多带有属性的线条(街道),而我想要得到的是一个包含所有线条的有向图。问题是,正如我在问题中所说,当使用 read_shp() 时,一些边缘被删除,但我需要将所有线条都作为边缘。如果您需要,我可以将我正在使用的 shapefile 发送给您。
  • 现在试试?如果有某种方法可以提供一个简单的 shapefile 来使用,那就太好了。否则我实际上无法测试我建议尝试的内容。
  • 我今天在研究另一个解决方案后再次尝试,它确实有效。我真的很抱歉,但我不知道为什么前几天它没有工作。感谢您的帮助。
【解决方案2】:

如果多线在接头处断开,我认为这个库python-s2g(https://github.com/caesar0301/python-s2g) 可以帮助你。即使在底层使用了networkx的Graph对象,这些多路径实际上是由图数据记录的。

【讨论】:

    【解决方案3】:

    我在这里实现了一个解决方案:https://gitlab.com/njacadieux/upstream_downstream_shortests_path_dijkstra

    我使用 GeoPandas 而不是 networkx.readwrite.nx_shp.read_shp 读取 shapefile。当我构建图表时,我会检查平行边。如果找到,而不是像 networkx.readwrite.nx_shp.read_shp 函数那样跳过它们,我将平行边分成两条等长的边,然后将用户长度除以 2。必须给出用户长度变量字段名称。

    【讨论】:

      猜你喜欢
      • 2022-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-06
      • 1970-01-01
      • 2021-01-23
      • 2021-12-28
      • 2017-06-28
      相关资源
      最近更新 更多