【问题标题】:GeoPandas plotting - any way to speed things up?GeoPandas 绘图 - 有什么方法可以加快速度?
【发布时间】:2016-02-16 07:01:03
【问题描述】:

我正在对一些地理数据运行梯度下降算法。目标是将不同的区域分配给不同的集群,以最小化一些目标函数。我正在尝试制作一部短片来展示算法的进展情况。现在我的方法是在每一步绘制地图,然后使用其他一些工具从所有静态图像中制作一个小电影(非常简单)。但是,我有大约 3000 个区域要绘制,并且 plot 命令需要 90 秒或更长时间才能运行,这会扼杀我的算法。

有一些明显的捷径:每第 N 次迭代保存一次图像,将所有步骤保存在一个列表中,并在最后制作所有图像(可能是并行的)。现在这一切都很好,但最终我的目标是一些交互式功能,用户可以输入一些参数并实时查看他们的地图收敛。在这种情况下,似乎最好动态更新地图。

有什么想法吗?这是基本命令(使用最新的 geopandas 开发版)

fig, ax = plt.subplots(1,1, figsize=(7,5))
geo_data.plot(column='cluster',ax=ax, cmap='gist_rainbow',linewidth=0)
fig.savefig(filename, bbox_inches='tight', dpi=400)

还尝试了类似于以下内容的内容(以下是缩写版本)。我打开一个图,并在每次迭代中更改并保存它。似乎根本没有加快速度。

fig, ax = plt.subplots(1,1, figsize=(7,5))
plot = geo_data.plot(ax=ax)
for iter in range(100): #just doing 100 iterations now
    clusters = get_clusters(...)
    for i_d, district in  enumerate(plot.patches):
        if cluster[i] == 1
            district.set_color("#FF0000")
        else:
            district.set_color("#d3d3d3")
    fig.savefig('test'+str(iter)+'.pdf')

更新:查看了来自 real-time plotting in while loop with matplotlib 的 drawow 和其他指针,但 shapefile 似乎太大/笨重而无法实时工作。

【问题讨论】:

    标签: python pandas matplotlib geopandas drawnow


    【解决方案1】:

    我认为有两个方面可以提高性能:1)使用 matplotlib 集合(当前的 geopandas 实现分别绘制每个多边形)和 2)只更新多边形的颜色而不是每次迭代再次绘制它(这个你已经这样做了,但是使用集合会更简单)。

    1) 使用 matplotlib 集合绘制多边形

    这是使用 geopandas 绘制 GeoSeries 多边形的更有效绘图功能的一种可能实现:

    from matplotlib.collections import PatchCollection
    from matplotlib.patches import Polygon
    import shapely
    
    def plot_polygon_collection(ax, geoms, values=None, colormap='Set1',  facecolor=None, edgecolor=None,
                                alpha=0.5, linewidth=1.0, **kwargs):
        """ Plot a collection of Polygon geometries """
        patches = []
    
        for poly in geoms:
    
            a = np.asarray(poly.exterior)
            if poly.has_z:
                poly = shapely.geometry.Polygon(zip(*poly.exterior.xy))
    
            patches.append(Polygon(a))
    
        patches = PatchCollection(patches, facecolor=facecolor, linewidth=linewidth, edgecolor=edgecolor, alpha=alpha, **kwargs)
    
        if values is not None:
            patches.set_array(values)
            patches.set_cmap(colormap)
    
        ax.add_collection(patches, autolim=True)
        ax.autoscale_view()
        return patches
    

    这比当前的 geopandas 绘图方法快 10 倍。

    2) 更新多边形的颜色

    获得图形后,可以使用set_array 方法一步完成更新多边形集合的颜色,其中数组中的值指示颜色(根据颜色图转换为颜色)

    例如(考虑到s_poly 带有多边形的 GeoSeries):

    fig, ax = plt.subplots(subplot_kw=dict(aspect='equal'))
    col = plot_polygon_collection(ax, s_poly.geometry)
    # update the color
    col.set_array( ... )
    

    带有一些虚拟数据的完整示例:

    from shapely.geometry import Polygon
    
    p1 = Polygon([(0, 0), (1, 0), (1, 1)])
    p2 = Polygon([(2, 0), (3, 0), (3, 1), (2, 1)])
    p3 = Polygon([(1, 1), (2, 1), (2, 2), (1, 2)])
    s = geopandas.GeoSeries([p1, p2, p3])
    

    绘制这个:

    fig, ax = plt.subplots(subplot_kw=dict(aspect='equal'))
    col = plot_polygon_collection(ax, s.geometry)
    

    给予:

    然后用指示簇的数组更新颜色:

    col.set_array(np.array([0,1,0]))
    

    给予

    【讨论】:

    • 这很棒。我在算法开始时调用 plot_polygon_collection(...) 。然后使用 plt.ion() 启用交互式绘图,构建我的图形并在每次迭代结束时使用 col.set_array(...)。地图实时更新。所以现在我真的不需要在每一步保存数字。如果我这样做了,这会将 fig.savefig(...) 函数缩短约 30 秒(60 秒 vs 90 秒)。
    • 节省 .png 数字而不是 .pdf 的收益更大。如果我这样做,我会得到预期的 10 倍加速(在我的情况下实际上是 20 倍)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-16
    • 2019-04-20
    • 1970-01-01
    相关资源
    最近更新 更多