【问题标题】:How to put a label on a country with Python cartopy?如何使用 Python cartopy 在一个国家/地区贴上标签?
【发布时间】:2020-05-25 14:18:26
【问题描述】:

使用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")

【问题讨论】:

    标签: python pandas numpy dataframe cartopy


    【解决方案1】:

    您可以检索几何的质心并在该位置绘制文本:

    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'])
    

    随着范围集中在“保加利亚”上,它看起来像:

    编辑:

    要分离“依赖项”,请考虑使用admin_0_map_units 而不是admin_0_map_countries,请参阅Natural Earth documentation 。

    要突出小国家/地区,您可以在几何图形中添加一个缓冲区,例如:

    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 在几何图形的中间进行交叉。最终,将绘图和空间分析(分割等)分成更不同的步骤可能会更“干净”。像这样混合可能会使代码更难在其他情况下重用。

    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'])
    

    【讨论】:

    • 绝对是一个很好的答案,感谢您的努力!作为一个完全不相关的问题 - 如果我想用绿色绘制新加坡或列支敦士登的地图,我应该怎么做?
    • 我已对答案进行了编辑。如果面积小于 2 平方度(不是映射的最佳单位),则图像显示具有 2 度缓冲区的多边形。我在标签上添加了一个偏移量,以避免过度绘制国家/地区本身。
    • 我通过检查country.attributes['NAME_EN'] == "France" 设法过滤掉了依赖区域。无论如何,关于“新加坡”和“列支敦士登”,我想我应该尝试给出手动坐标?
    • 这些国家在大地图上会非常小,但我认为您仍然可以使用相同的概念来完成它。
    • 我在文档中注意到了这句话:“如果您想查看独立的海外地区(例如 ISO 代码,请参见法国),请改用地图单位。”并认为在这种情况下可能更合适。它位于“关于”部分:naturalearthdata.com/downloads/10m-cultural-vectors/…
    猜你喜欢
    • 2021-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-08
    • 1970-01-01
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多