GeoPandas地图动画无效果:使用FuncAnimation未生效问题
问题分析与修复方案
你的动画不生效主要源于几个关键错误,逐一修正后即可解决:
1. 回调函数名称不匹配
你定义的动画执行函数是animate,但FuncAnimation中指定的回调是update,名称完全不匹配,导致动画框架无法找到要执行的函数。
2. 未清除原有绘图内容
每次绘制新日期的地图时,没有清除轴上的旧图层,新内容直接叠加在旧内容上,视觉上完全看不出变化,必须在animate函数开头添加ax.clear()清除上一帧内容。
3. 动画对象未保存
创建FuncAnimation后,没有将其赋值给变量,Python的垃圾回收机制会直接回收这个临时对象,导致动画无法运行。
4. 无效的日期自增代码
date += TimeDelta(1)完全多余,frames参数已经传入了所有要迭代的日期,函数会自动接收每个frame的日期值,不需要手动修改。
5. 重复生成图例
每次调用plot时都设置legend=True会导致图例重复叠加,建议只在初始化时生成一次,或者绘图时关闭自动生成图例。
修正后的完整代码
import geopandas as gpd import pandas as pd import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation # 加载地理数据 link = 'https://raw.githubusercontent.com/leakyMirror/map-of-europe/master/GeoJSON/europe.geojson' europe = gpd.read_file(link) europe_w_needed_countries = europe[europe.NAME.isin(train.country.unique())] def create_gdf(date): a = new_train.query(f"date == '{date}'").groupby('country').sum().reset_index() # 用merge代替concat,避免索引不匹配风险,确保国家名称精准对应 b = europe_w_needed_countries[['NAME', 'LON', 'LAT', 'geometry']].rename(columns={'NAME':'country'}) merged_gdf = pd.merge(a, b, on='country', how='left') return gpd.GeoDataFrame(merged_gdf) # 初始化绘图 fig, ax = plt.subplots(figsize=(15,8)) fontsize = 13 def animate(date): ax.clear() # 清除上一帧所有内容 gdf = create_gdf(date) # 绘图时关闭自动生成图例,避免重复叠加 gdf.plot(ax=ax, column='num_sold', cmap='OrRd', edgecolor='black') ax.set_title('Books Sold From 1/1/2017 - 12/31/2020') ax.set_axis_off() ax.text(20, 45, f'Date:\n{date}', fontsize=fontsize, horizontalalignment='center') for lon, lat, country in zip(gdf.LON, gdf.LAT, gdf.country): ax.text(lon - 1.5, lat, country, fontsize=fontsize) # 修正回调函数名称,并保存动画对象 anim = FuncAnimation(fig, animate, interval=250, frames=new_train.index.unique()) # Jupyter环境下显示动画需添加以下代码 # from IPython.display import HTML # HTML(anim.to_jshtml()) # 保存动画为文件(需安装ffmpeg) # anim.save('book_sales_animation.mp4', writer='ffmpeg')
额外优化建议
- 原代码用
pd.concat合并数据存在索引不匹配风险,改用pd.merge基于国家名称匹配更可靠。 - 如果部分日期无数据,建议在
create_gdf中添加空数据判断逻辑,避免绘图报错。 - 国家名称位置问题可以改用GeoPandas的
centroid属性获取多边形中心坐标,替代现有固定的LON/LAT值。
内容的提问来源于stack exchange,提问作者javanewb1
相关产品推荐
相关产品推荐

