Using python3 and cartopy, having this code:
import matplotlib.pyplot as plt
import cartopy
import cartopy.io.shapereader as shpreader
import cartopy.crs as ccrs
ax = plt.axes(projection=ccrs.PlateCarree())
ax.add_feature(cartopy.feature.LAND)
ax.add_feature(cartopy.feature.OCEAN)
ax.add_feature(cartopy.feature.COASTLINE)
ax.add_feature(cartopy.feature.BORDERS, linestyle='-', alpha=.5)
ax.add_feature(cartopy.feature.LAKES, alpha=0.95)
ax.add_feature(cartopy.feature.RIVERS)
ax.set_extent([-150, 60, -25, 60])
shpfilename = shpreader.natural_earth(resolution='110m',
category='cultural',
name='admin_0_countries')
reader = shpreader.Reader(shpfilename)
countries = reader.records()
for country in countries:
if country.attributes['SOVEREIGNT'] == "Bulgaria":
ax.add_geometries(country.geometry, ccrs.PlateCarree(), facecolor=(0, 1, 0), label = "A")
else:
ax.add_geometries(country.geometry, ccrs.PlateCarree(), facecolor=(1, 1, 1), label = country.attributes['SOVEREIGNT'])
plt.rcParams["figure.figsize"] = (50,50)
plt.show()
I get this:
Question:
What should I write, in order to get a red "A" over Bulgaria (or any other country, which I refer to in country.attributes['SOVEREIGNT']
)? Currently the label is not shown at all and I am not sure how to change the font of the label. Thus, it seems that the following only changes the color, without adding the label:
ax.add_geometries(country.geometry, ccrs.PlateCarree(), facecolor=(0, 1, 0), label = "A")
You can retrieve the centroid of the geometry and plot the text at that location:
import matplotlib.patheffects as PathEffects
for country in countries:
if country.attributes['SOVEREIGNT'] == "Bulgaria":
g = ax.add_geometries(country.geometry, ccrs.PlateCarree(), facecolor=(0, 1, 0), label="A")
x = country.geometry.centroid.x
y = country.geometry.centroid.y
ax.text(x, y, 'A', color='red', size=15, ha='center', va='center', transform=ccrs.PlateCarree(),
path_effects=[PathEffects.withStroke(linewidth=5, foreground="k", alpha=.8)])
else:
ax.add_geometries(country.geometry, ccrs.PlateCarree(), facecolor=(1, 1, 1), label = country.attributes['SOVEREIGNT'])
With the extent focused on "Bulgaria" it looks like:
edit:
To get "dependencies" separate, consider using the admin_0_map_units
instead of admin_0_map_countries
, see the Natural Earth documentation
.
To highlight small countries/regions you could add a buffer to the geometry with something like:
highlight = ['Singapore', 'Liechtenstein']
for country in countries:
if country.attributes['NAME'] in highlight:
if country.geometry.area < 2:
geom = [country.geometry.buffer(2)]
else:
geom = [country.geometry]
g = ax.add_geometries(geom, ccrs.PlateCarree(), facecolor=(0, 0.5, 0, 0.6), label="A", zorder=99)
x = country.geometry.centroid.x
y = country.geometry.centroid.y
ax.text(x, y+5, country.attributes['NAME'], color='red', size=14, ha='center', va='center', transform=ccrs.PlateCarree(),
path_effects=[PathEffects.withStroke(linewidth=3, foreground="k", alpha=.8)])
else:
ax.add_geometries(country.geometry, ccrs.PlateCarree(), facecolor=(1, 1, 1), label=country.attributes['NAME'])
You could split a specific country with something like this, It uses Shapely to perform an intersection at the middle of the geometry. Ultimately it might be "cleaner" to separate the plotting and spatial analysis (splitting etc) in to more distinct steps. Mixing it like this probably makes it harder to re-use the code for other cases.
from shapely.geometry import LineString, MultiLineString
for country in countries:
if country.attributes['NAME'] in 'China':
# line at the centroid y-coord of the country
l = LineString([(-180, country.geometry.centroid.y),
(180, country.geometry.centroid.y)])
north_poly = MultiLineString([l, north_line]).convex_hull
south_poly = MultiLineString([l, south_line]).convex_hull
g = ax.add_geometries([country.geometry.intersection(north_poly)], ccrs.PlateCarree(), facecolor=(0.8, 0.0, 0.0, 0.4), zorder=99)
g = ax.add_geometries([country.geometry.intersection(south_poly)], ccrs.PlateCarree(), facecolor=(0.0, 0.0, 0.8, 0.4), zorder=99)
x = country.geometry.centroid.x
y = country.geometry.centroid.y
ax.text(x, y, country.attributes['NAME'], color='k', size=16, ha='center', va='center', transform=ccrs.PlateCarree(),
path_effects=[PathEffects.withStroke(linewidth=5, foreground="w", alpha=1)], zorder=100)
else:
ax.add_geometries(country.geometry, ccrs.PlateCarree(), facecolor=(1, 1, 1), label=country.attributes['NAME'])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With