Reputation: 1521
I am trying to animate a geopandas plot unsing FuncAnimation. Basically eu_private_map is a geopandas.geodataframe.GeoDataFrame and among other fields, it contains several columns with the values for parameter x in different EU states across 10 consecutive years. Each column are the values of x for one year.
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())
The colorbar is giving me a hard time. On the one hand, if I set legend = True, I do not like the fact that it does not have the same size (see figure) as the figure and it creates a weird effect (see figure). I tried this but I got an error: AttributeError: 'AxesSubplot' object has no attribute 'autoscale_None'. However I cannot spot the trouble in the code, any help to fix both issues at once? Thanks a lot
Upvotes: 1
Views: 3041
Reputation: 765
For new answer-seekers who are stumbling on to this, the idea is to use init_func
parameter for the FuncAnimation
function. This was answered here.
the init_func
will render the colorbar whereas the animate
function will not render the colorbar.
Limitation: I am assuming the colorbar and its ticks do not change and this answer will keep the old colorbar intact while updating the chart axes.
Upvotes: 0
Reputation: 1
Hei,
found a way to make a log scale color plot
norm=matplotlib.colors.LogNorm()
does the trick:
A logarithmic colorbar in matplotlib scatter plot
and you can also add vmin and vmax like this:
norm=colors.LogNorm(vmin=vmin, vmax=vmax)
good to remember though it works only for vmin and vmax positive. E.g.
norm=colors.LogNorm(vmin=0.1, vmax=1000000)
Upvotes: 0
Reputation: 1521
After trying many ways that failed to work for geopandas & animate, I ended up finding a solution to make it work being the main idea to separate the colorbar from the animate function to the init function of the plot.
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())
Upvotes: 1