I need your help with this. I want to left click on a country, ex Italy. Print the name Italy and color Italy on the map. Should be usable with any country. Here is my code:
Source: Animation Using Cartopy
Update:
Just wanted to share the new code, everything works fine.
You can now select/deselect any country.
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
import matplotlib.animation as animation
import cartopy
import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreader
from math import log
from math import exp
from matplotlib import colors
from shapely.geometry.multipolygon import MultiPolygon
# Grab :
# % of electricity from renewable sources EG.ELC.RNWX.ZS
# 1960 - 2013
# Make fake data
Indicator_df = pd.DataFrame({
'CountryName': ['United States'] * 4 + ['Argentina'] * 4,
'Year': [1960, 1961, 1962, 1963] * 2,
'Value': [5, 10, 20, 30] * 2
})
# setup colorbar stuff and shape files
norm = mpl.colors.Normalize(vmin=0, vmax=30)
colors_in_map = []
logbase = exp(1)
for i in range(30):
val = log(i + 1, logbase) / log(31, logbase)
colors_in_map.append((1 - val, val, 0))
cmap = colors.ListedColormap(colors_in_map)
shpfilename = shpreader.natural_earth(resolution='110m',
category='cultural',
name='admin_0_countries')
reader = shpreader.Reader(shpfilename)
countries_map = reader.records()
# These don't need to constantly be redefined, especially edgecolor
facecolor = 'gray'
edgecolor = 'black'
fig, ax = plt.subplots(figsize=(12, 6),
subplot_kw={'projection': ccrs.PlateCarree()})
# Draw all the gray countries just once in an init function
# I also make a dictionary for easy lookup of the geometries by country name later
geom_dict = {}
country_to_geom_and_artist = {}
def init_run():
for n, country in enumerate(countries_map):
if country.geometry.geom_type == "Polygon":
geom = MultiPolygon([country.geometry])
else:
geom = country.geometry
# ax.add_geometries(geom,
# ccrs.PlateCarree(),
# facecolor=facecolor,
# edgecolor=edgecolor)
# geom_dict[country.attributes['NAME_LONG']] = geom
feature_artist = ax.add_geometries(country.geometry, ccrs.PlateCarree(),
facecolor=facecolor, edgecolor=edgecolor,label=repr(country.attributes['NAME_CIAWF']))
geom_dict[country.attributes['NAME_CIAWF']] = feature_artist
country_to_geom_and_artist[country.attributes['NAME_CIAWF']] = (country.geometry, feature_artist)
def run(data, cname='United States'):
"""Update the Dist"""
# "data" in this setup is a frame number starting from 0, so it corresponds nicely
# with your years
# data = 0
year = 1960 + data
# get a subset of the df for the current year
year_df = Indicator_df[Indicator_df['Year'] == year]
for i, row in year_df.iterrows():
# This loops over countries, gets the value and geometry and adds
# the new-colored shape
#geom = geom_dict[row['CountryName']]
geom = geom_dict[cname]
value = row['Value']
#value = 10
greenamount = (log(float(value) + 1, logbase) / log(31, logbase))
facecolor = 1 - greenamount, greenamount, 0
'''
ax.add_geometries(geom,
ccrs.PlateCarree(),
facecolor=facecolor,
edgecolor=edgecolor)
'''
geom._feature._kwargs['facecolor'] = facecolor
# I decreased the indent of this, you only need to do it once per call to run()
ax.set_title(cname)
cax = fig.add_axes([0.92, 0.2, 0.02, 0.6])
cb = mpl.colorbar.ColorbarBase(cax,
cmap=cmap,
norm=norm,
spacing='proportional')
cb.set_label('%')
init_run()
run(0)
import shapely.geometry as sgeom
clist = []
def onclick(event):
if event.button == 1:
if event.inaxes and isinstance(event.inaxes, cartopy.mpl.geoaxes.GeoAxes):
ax = event.inaxes
target = ccrs.PlateCarree()
lon, lat = target.transform_point(event.xdata, event.ydata,
ax.projection)
point = sgeom.Point(lon, lat)
for country, (geom, artist) in country_to_geom_and_artist.items():
if geom.contains(point):
print('Clicked on {}'.format(country))
if country in clist:
clist.remove(country)
run(0, country)
else:
clist.append(country)
run(2, country)
plt.draw() #redraw
break
plt.connect('button_press_event', onclick)
plt.rcParams["figure.figsize"] = (50,50)
plt.show()
'''
ani = animation.FuncAnimation(fig,
run,
init_func=init_run,
frames=4,
interval=500,
blit=False)
#ani.save(filename="test.gif")
'''
[result][1] [1]: https://i.stack.imgur.com/gQVtu.png