【问题标题】:How to add a colorbar to geopandas plot with matplotlib animation如何使用 matplotlib 动画向 geopandas 绘图添加颜色条
【发布时间】:2019-08-02 02:16:44
【问题描述】:

我正在尝试为 geopandas 情节设置动画,而不是 FuncAnimation。基本上 eu_private_map 是一个 geopandas.geodataframe.GeoDataFrame 和其他字段,它包含几个列,其中包含连续 10 年不同欧盟国家的参数 x 值。每列是一年的 x 值。

from matplotlib.animation import FuncAnimation
from IPython.display import HTML
from mpl_toolkits.axes_grid1 import make_axes_locatable

fig = plt.figure() 
ax1 = fig.add_subplot(1,1,1)

def animate(year):
        ax1.clear()
        my_map = eu_private_map.plot(ax=ax1, column=year, vmin=0, vmax=30, legend=False)
        divider = make_axes_locatable(ax1)
        cax = divider.append_axes("right", size="5%", pad=0.05)
        plt.colorbar(my_map, cax=cax)

# the FuncAnimation function iterates through our animate function using the steps array
years = eu_private.columns.drop('country').tolist()
ani = FuncAnimation(fig, animate, years, interval=1000, blit=False)

HTML(ani.to_jshtml())

颜色条让我很难受。一方面,如果我设置legend = True,我不喜欢它没有与图相同的大小(见图),并且会产生奇怪的效果(见图)。我尝试了this,但出现错误:AttributeError:'AxesSubplot' 对象没有属性'autoscale_None'。但是我无法发现代码中的问题,有什么帮助可以同时解决这两个问题吗?非常感谢

【问题讨论】:

  • 如果你设置blit=False,你可以绕过动画函数返回任何东西的要求。我认为 blitting 在这里没有任何意义,因为无论如何您都将动画转换为视频。这样做时您可能会遇到其他问题,但如果是这种情况,更新问题是有意义的。
  • 您说的非常对,非常感谢。你能解释一下 blit 在做什么吗?我没有从文档中得到它。现在颜色条给出了问题,所以我将编辑问题并解决这个问题。
  • The docs say "获取一个现有位图 [..],然后在顶部再“blit”一位艺术家。因此,通过管理保存的“干净”位图,我们只能重新画出每一帧都在变化的少数艺术家 [...]。” 因此,我们的想法是不要重新绘制在整个帧中保持不变的图形的所有部分。这在屏幕上绘制图形时有效,但为了保存,无论如何都需要为每一帧绘制完整的图片。 ax.clear() 也使 blitting 过时了,因为在清除所有内容后,一切都不相同了。

标签: python pandas matplotlib animation geopandas


【解决方案1】:

在尝试了许多对 geopandas & animate 无效的方法后,我最终找到了一个解决方案,使其成为将颜色条从动画函数分离到绘图的 init 函数的主要思想。

from matplotlib.animation import FuncAnimation
from IPython.display import HTML
from mpl_toolkits.axes_grid1 import make_axes_locatable


fig = plt.figure(figsize=(20,10)) 
ax1 = fig.add_subplot(1,1,1)

def animate(year):
        ax1.clear()
        eu_private_map.plot(color='gainsboro', ax=ax1, linewidth=0.6, edgecolor='1')
        sm = eu_private_map.dropna().plot(ax=ax1, column=year, vmin=0, vmax=30, cmap = 'viridis',
                                              legend=False, linewidth=0.6, edgecolor='1')
        ax1.set_title(year, fontdict={'fontsize': '23'})
        ax1.axis('off')

def init():
    # Create colorbar as a legend
    sm = plt.cm.ScalarMappable(cmap='viridis', norm=plt.Normalize(vmin=0, vmax=30))
    # empty array for the data range
    sm._A = []
    # add the colorbar to the figure

    divider = make_axes_locatable(ax1)
    cax = divider.append_axes("right", size="5%", pad=0.5)


    cbar = fig.colorbar(sm, cax=cax)
    cbar.ax.tick_params(labelsize=14) 


# the FuncAnimation function iterates through our animate function using the steps array
years = eu_private.columns.drop('country').tolist()[::-1]
ani = FuncAnimation(fig, animate, years, interval=1000, blit=False, init_func=init)

HTML(ani.to_jshtml())

【讨论】:

  • 解决方案改编自这篇原创博文(不是说它不是动态的):towardsdatascience.com/…
  • 代码不可运行,名称“eu_private”未定义。
【解决方案2】:

嘿, 找到了一种制作对数刻度颜色图的方法 norm=matplotlib.colors.LogNorm() 成功了:

A logarithmic colorbar in matplotlib scatter plot

你也可以像这样添加 vmin 和 vmax: norm=colors.LogNorm(vmin=vmin, vmax=vmax)

虽然它仅适用于 vmin 和 vmax 正数,但请记住这一点。例如。 norm=colors.LogNorm(vmin=0.1, vmax=1000000)

【讨论】:

    【解决方案3】:

    对于遇到此问题的新答案寻求者,我们的想法是为 FuncAnimation 函数使用 init_func 参数。这是here的回答。

    init_func 将呈现颜色条,而 animate 函数将不呈现颜色条。

    限制:我假设颜色条及其刻度不会改变,这个答案将在更新图表轴时保持旧颜色条不变。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-17
      • 1970-01-01
      • 1970-01-01
      • 2020-08-15
      • 2019-08-22
      • 2019-03-23
      相关资源
      最近更新 更多