python - 鼠标悬停时用绘图注释底图
问题描述
我正在绘制带有底图的欧洲地图,并尝试使其尽可能具有交互性。我希望这张地图显示一些选定国家的一些数据(例如:能源消耗)作为给定年份的颜色。如果我用鼠标将鼠标悬停在一个国家上,我希望出现一个图,向我展示这种消费在过去几年中是如何演变的。我的问题是:如何用这样的图注释底图。我找到了一种用文本注释的方法(见下文),但不是用绘图。
这是我到目前为止所取得的成就。首先,我生成底图。
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import pandas as pd
import shapefile
from matplotlib.collections import PolyCollection
from matplotlib.patches import Polygon
from matplotlib import cm
%matplotlib nbagg
fig = plt.figure(figsize=(8,6.4))
ax = plt.subplot(111)
m = Basemap(projection='lcc', resolution='l', lat_0 = 50, lon_0 = 15, \
llcrnrlon = -9, llcrnrlat = 32, urcrnrlon= 40, urcrnrlat = 63)
请注意,为了只为某些选定的国家着色,我使用的 shapefile 不是来自底图本身,而是来自natural earth website。该文件在ne_10m_admin_0_countries
此处具有名称。
sfile = 'ne_10m_admin_0_countries/ne_10m_admin_0_countries'
m.readshapefile(sfile, 'areas', linewidth=0.1)
shp = shapefile.Reader(sfile)
shapes = shp.shapes()
records = shp.records()
请注意,我使用底图来绘制所有国家/地区,但稍后我会在循环中为我感兴趣的国家/地区着色。在进入该循环之前,我创建了一个列表,其中将包含我绘制的国家的多边形补丁以及链接到它们的注释
poly_with_annotation = []
数据可以在 dataframe 中找到df_mean
,其中每一列是不同的国家,每一行是不同的年份。(这里dict_country
只是一个字典,包含国家名称和要查看的shapefile记录之间的对应关系。这无关紧要,基本上我们只是绘制我们感兴趣的国家。)
for column, country in dict_country.items():
record = records[records_dict[country]]
shape = shapes[records_dict[country]]
lons,lats = zip(*shape.points)
data = np.array(m(lons, lats)).T
if len(shape.parts) == 1:
segs = [data,]
else: # Some countries have islands or are given as several polygons
segs = []
for i in range(1,len(shape.parts)):
index = shape.parts[i-1]
index2 = shape.parts[i]
segs.append(data[index:index2])
segs.append(data[index2:])
polys = PolyCollection(segs, antialiaseds=(1,))
polys.set_facecolors(cm.Reds(df_mean.loc[default_year,column]/df_mean.max().max()))
polys.set_edgecolors('k')
polys.set_linewidth(0.3)
ax.add_collection(polys)
现在是重要的部分。我知道如何用文本注释它。这是我所拥有的:
lon0 = 10
lat0 = 50
annotation = ax.annotate(\
"Mouse over country %s" % country, \
xy=m(lon0,lat0), xycoords='data', \
xytext=m(lon0+2,lat0+2), textcoords='data', \
horizontalalignment="left", \
bbox=dict(boxstyle="round", facecolor="w", \
edgecolor="0.5", alpha=0.9) \
)
# by default, disable the annotation visibility
annotation.set_visible(False)
poly_with_annotation.append([polys, annotation])
# When my mouse hovers above a given patch (country), execute the on_move function
on_move_id = fig.canvas.mpl_connect('motion_notify_event', on_move)
其中on_move
函数定义为
def on_move(event):
visibility_changed = False
for poly, annotation in poly_with_annotation:
should_be_visible = (poly.contains(event)[0] == True)
if should_be_visible != annotation.get_visible():
visibility_changed = True # on change la visibilité de l'annotation
annotation.set_visible(should_be_visible)
if visibility_changed:
plt.draw()
这很好用(见图,我的鼠标在法国上空)。
但我希望这样而不是“将鼠标悬停在国家 FRA”上,它显示了这个国家多年来数据的演变图(类似于df_mean.plot(y='FRA')
)
请注意,这受到以下答案的启发:
解决方案
推荐阅读
- php - 如何修复此错误:调用未定义函数 odbc_connect()
- c# - Netcore API 未连接到 AWS Lambda 上的 MySQL RDS
- reactjs - 如何通过点击 react-swipeable-views 渲染组件?
- python - 大摇大摆地检索 Oauth2 令牌并使用 Python 与 API 交互
- npm - 错误:EACCES 权限被拒绝,打开 './.eslintrc.json
- mysql - SELECT FOR UPDATE中的MySQL 5.6死锁,同时按主键选择不同的行
- android - 如何在 Material TextInputLayout 中制作自定义 MultiAutoCompleteTextView?
- docker - python 会自动在 Dockerfile 中获取别名吗?
- java - Atlassian Confluence SDK 启动 App 404 问题
- bootstrap-4 - Bootstrap 4+ - 垂直+水平对齐 2 个 div 在另一个 div 中彼此顶部设置高度