python Matplotlib pick_event不适用于geopandas Dataframe

oo7oh9g9  于 2023-01-19  发布在  Python
关注(0)|答案(1)|浏览(158)

这是我的Jupyer Notebook source code
但是下面是一个硬编码的可复制的例子。(你需要从我的Github或真实源代码中访问UK. geojson文件:http://geoportal1-ons.opendata.arcgis.com/datasets/687f346f5023410ba86615655ff33ca9_1.geojson
我有一个geopandas数据框来绘制英国Map,然后在上面绘制某些坐标(公园运行位置)。
我希望能够交互式地"挑选"坐标,然后我将对它进行编码,以显示有关特定运行位置的信息。
我不明白为什么我调用的fig.canvas.mpl_connect('pick_event', onpick)函数不起作用。
拜托,谁能帮我想想办法?

import pandas as pd
import geopandas as gpd
import numpy as np
import matplotlib.pyplot as plt

##### Create hardcoded dataset ######
df = pd.DataFrame.from_dict({0: {'parkrun_name': 'Beeston',
  'location_name': 'Weirfields Recreation Ground',
  'longitude': -1.201737,
  'latitude': 52.913592,
  'Run Date': '12/11/2022',
  'Run Number': 370.0,
  'Pos': 107.0,
  'Time': '26:05',
  'Age Grade': '49.46%',
  'PB?': np.nan},
 1: {'parkrun_name': 'Colwick',
  'location_name': 'Colwick Country Park, Nottingham',
  'longitude': -1.09786,
  'latitude': 52.945171,
  'Run Date': '22/10/2022',
  'Run Number': 511.0,
  'Pos': 127.0,
  'Time': '29:44',
  'Age Grade': '43.39%',
  'PB?': np.nan},
 2: {'parkrun_name': 'Exmouth',
  'location_name': 'Exmouth',
  'longitude': -3.412392,
  'latitude': 50.614697,
  'Run Date': '24/12/2022',
  'Run Number': 189.0,
  'Pos': 197.0,
  'Time': '25:44',
  'Age Grade': '50.13%',
  'PB?': 'PB'},
}, orient='index')

###### Read in the UK Map File ######
uk = gpd.read_file("uk.geojson")

###### Convert df to geodf ######
gdf = gpd.GeoDataFrame(
    df, geometry=gpd.points_from_xy(df.longitude, df.latitude)
)
gdf.crs = "EPSG:4326"
gdf = gdf.to_crs(uk.crs)
###### Plot interactive map ######
%matplotlib widget

fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(111)
uk.plot(ax=ax, alpha=0.8)

def onclick(event):
    ax = plt.gca()
    # ax.set_title(f"You selected {event.x}, {event.y}")
    
    line = event.artist
    xdata, ydata = line.get_data()
    ind = event.ind
    
    tx = f"{np.array([xdata[ind], ydata[ind]]).T}"
    
    ax.set_title(f"{tx}")
    
gdf[gdf['Run Date'].isna()].plot(ax=ax, color='black', marker='.', markersize=8, alpha=0.2, picker=20)
gdf[gdf['Run Date'].notna()].plot(ax=ax, color='#AAFF00', marker='.', markersize=50, picker=20)

ax.set_xlim(-7,2)
ax.set_ylim(49,60)

cid = fig.canvas.mpl_connect('pick_event', onclick)
yhxst69z

yhxst69z1#

我是EOmaps的开发人员,这是一个旨在简化matplotlib/cartopyMap交互的软件包。
它还带有一个功能,使地理 Dataframe 可选择...这可能正是你正在寻找的:-)
下面是一个关于它目前如何工作的例子:
(查看geodataframes和回调上的文档以了解详细信息)

from eomaps import Maps

m = Maps()
m.add_feature.preset.coastline()

# fetch a geodataframe from NaturalEarth (with polygon geometries)
countries = m.add_feature.cultural.admin_0_countries.get_gdf(scale=110)
# fetch a geodataframe from NaturalEarth (with point geometries)
populated_places = m.add_feature.cultural.populated_places.get_gdf(scale=110)

# add the geo-dataframes to the map and make them "pickable"
m.add_gdf(countries, column="NAME", alpha=0.5,
          picker_name="countries", pick_method="contains")

m.add_gdf(populated_places, column="NAME", 
          picker_name="populated_places", pick_method="centroids")

# attach a pre-defined callback to show an annotation if you pick a geometry
m.cb.pick__countries.attach.annotate(
    text=lambda val, **kwargs: f"clicked in country:\n    {val}"
    )
m.cb.pick__populated_places.attach.annotate(
    text=lambda val, **kwargs: f"closest city to click-position:\n    {val}",
    xytext=(20,-20)
    )

# define a custom callback
def custom_cb(ID, val, pos, picker_name, **kwargs):
    print(f"### {picker_name} picked ID '{ID}' with value: '{val}' at position '{pos}'")

# execute the custom callback if you pick a geometry
m.cb.pick__populated_places.attach(custom_cb)
m.cb.pick__countries.attach(custom_cb)

m.ax.set_extent((-180.0, 180.0, -90.0, 90.0))

相关问题