GeoPandas 绘图 - 有什么方法可以加快速度吗?
GeoPandas plotting - any way to speed things up?
我正在运行对某些地理数据使用梯度下降算法。目标是将不同的区域分配给不同的集群,以最小化某些 objective 功能。我正在尝试制作一部展示算法进展情况的短片。现在我的方法是在每一步绘制地图,然后使用一些其他工具从所有静态图像制作一部小电影(非常简单)。但是,我有大约 3000 个区域要绘制,绘图命令需要 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 中的 drawnow 和其他指针,但 shapefile 似乎太 big/clunky 无法实时工作。
我认为有两个方面可能会提高性能: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]))
给予
我正在运行对某些地理数据使用梯度下降算法。目标是将不同的区域分配给不同的集群,以最小化某些 objective 功能。我正在尝试制作一部展示算法进展情况的短片。现在我的方法是在每一步绘制地图,然后使用一些其他工具从所有静态图像制作一部小电影(非常简单)。但是,我有大约 3000 个区域要绘制,绘图命令需要 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 中的 drawnow 和其他指针,但 shapefile 似乎太 big/clunky 无法实时工作。
我认为有两个方面可能会提高性能: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]))
给予