Python cartopyを使用して国にラベルを付ける方法は?


8

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()

私はこれを手に入れます:

ここに画像の説明を入力してください

質問:ブルガリア(またはで言及している他の国)に 赤い " A "を表示するには、何を書けばよいcountry.attributes['SOVEREIGNT']ですか?現在、ラベルはまったく表示されておらず、ラベルのフォントを変更する方法がわかりません。したがって、以下はラベルを追加せずに色を変更するだけのようです。

ax.add_geometries(country.geometry, ccrs.PlateCarree(), facecolor=(0, 1, 0), label = "A")

回答:


9

ジオメトリの重心を取得して、その位置にテキストをプロットできます。

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、の代わりにを使用することを検討してください。NaturalEarthのドキュメントを 参照してください。

小さな国/地域を強調表示するには、次のようなものでジオメトリにバッファを追加できます。

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

ここに画像の説明を入力してください


間違いなく良い答えです、努力をありがとう!また、まったく関係のない質問として、シンガポールまたはリヒテンシュタインを緑色でマッピングしたい場合はどうすればよいですか。
Vityata

1
回答を編集しました。この画像は、面積が2平方度未満の場合(マッピングに最適な単位ではありません)、2度のバッファを持つポリゴンを示しています。国自体を過剰にプロットしないように、ラベルにオフセットを追加しました。
Rutger Kassies

をチェックすることで、依存する地域をフィルターにかけることができましたcountry.attributes['NAME_EN'] == "France"。とにかく、「シンガポール」と「リヒテンシュタイン」については、手動で座標をつけたほうがいいかな?
Vityata

1
これらの国々は大きな地図では非常に小さくなりますが、同じ概念を使用してそれを実現することもできます。
Rutger Kassies

1
ドキュメントでこの発言に気づきました。「海外の従属地域を分解して表示したい場合(ISOコードなど、フランスを参照)、代わりにマップ単位を使用してください。」この場合はもっと適切かもしれないと思った。:それは、「約」の部分にあります naturalearthdata.com/downloads/10m-cultural-vectors/...
ルトガーKassies
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.