如何使用 Python cartopy 在国家/地区贴上标签?
How to put a label on a country with Python cartopy?
使用python3和cartopy,代码如下:
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()
我明白了:
问题:
我应该写什么,以便在保加利亚(或我在 country.attributes['SOVEREIGNT']
中提到的任何其他国家/地区)获得红色“A”?目前标签根本没有显示,我不确定如何更改标签的字体。因此,似乎以下仅更改颜色,而没有添加标签:
ax.add_geometries(country.geometry, ccrs.PlateCarree(), facecolor=(0, 1, 0), label = "A")
您可以检索几何的质心并在该位置绘制文本:
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'])
将范围集中在 "Bulgaria" 上,它看起来像:
编辑:
要分离 "dependencies",请考虑使用 admin_0_map_units
而不是 admin_0_map_countries
,请参阅 Natural Earth 文档
.
要突出显示小 countries/regions,您可以向几何体添加一个缓冲区,例如:
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'])
你可以用这样的东西分割一个特定的国家,它使用 Shapely 在几何体的中间执行交叉。最终可能 "cleaner" 将绘图和空间分析(拆分等)分成更多不同的步骤。像这样混合它可能会使代码更难在其他情况下重用。
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'])
使用python3和cartopy,代码如下:
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()
我明白了:
问题:
我应该写什么,以便在保加利亚(或我在 country.attributes['SOVEREIGNT']
中提到的任何其他国家/地区)获得红色“A”?目前标签根本没有显示,我不确定如何更改标签的字体。因此,似乎以下仅更改颜色,而没有添加标签:
ax.add_geometries(country.geometry, ccrs.PlateCarree(), facecolor=(0, 1, 0), label = "A")
您可以检索几何的质心并在该位置绘制文本:
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'])
将范围集中在 "Bulgaria" 上,它看起来像:
编辑:
要分离 "dependencies",请考虑使用 admin_0_map_units
而不是 admin_0_map_countries
,请参阅 Natural Earth 文档
.
要突出显示小 countries/regions,您可以向几何体添加一个缓冲区,例如:
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'])
你可以用这样的东西分割一个特定的国家,它使用 Shapely 在几何体的中间执行交叉。最终可能 "cleaner" 将绘图和空间分析(拆分等)分成更多不同的步骤。像这样混合它可能会使代码更难在其他情况下重用。
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'])