12
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

plotlyを利用した世界地図での国・地域塗り分け

Posted at

概要

Pythonのplotlyライブラリを利用すると、国・地域別データを世界地図上へ簡単に可視化できるようになります。しかもインタラクティブな感じに!今回は2024年の訪日外国人データを例に、Pythonのplotlyライブラリを用いた国・地域別データの可視化について簡単にまとめておきます。地図上に色を使って数値を反映させることで、地理的な意味での傾向や特徴が視覚的に理解できるようになるはず:scream:

world_map_consumption.png

本当はマウスカーソル動かすと、国名や数値のポップアップ、拡大縮小や移動もできるのですが...静止画像なので無理かな:sweat_smile:

利用する主要ライブラリ
plotly: インタラクティブなグラフや地図データの可視化を簡単に作成できるライブラリ

【注意】
plotlyライブラリをインストールするだけでは動作しないことがあります。必要に応じて追加ライブラリも合わせてインストールしてください。個人的にはnbformatのインストールを促されました:wink:

演習用のファイル

演習1:訪日観光客などの人数

演習2:一人あたりの消費金額

出典

1. 利用するデータ

世界地図上に可視化するので、国や地域の数値データであれば問題なく地図上に表示できます。今回は、2024年の訪日外国人の居住地や消費動向を可視化してみたいと思います。:sweat_drops:

1.1 外客数データ

2024年の訪日外国人数のデータからです。日本政府観光局の統計を利用しました。日本政府観光局から「国籍/目的別 訪日外客数(2004年~2024年)」を選択して、PDFファイルをダウンロードします。何故かPDFなのです。ファイルの中身は、「2024年 国籍別 / 目的別 訪日外客数 (確定値)」が記載されています。

PDFの中身.jpg

ここから国・地域名、総数、観光客、その他客の4列を抽出します。国・地域に対応するISOの3文字コードも事前に追記しておきます。地域コードはwiki pediaのISO 3166-1を参考にしました1。ISO3コードがない地域は、「その他」として一括してあります。完成したCSVファイル名はforeign_visitors_2024.csvとしました。

外客数データ
import pandas as pd
df = pd.read_csv("./data/foreign_visitors_2024.csv")

データの冒頭5行は次のような形になります。

地域 総人数 観光客 商用客 その他客 コード
韓国 8817765 8452682 185779 179304 KOR
中国 6981342 6064115 277983 639244 CHN
台湾 6044316 5867101 93017 84198 TWN
香港 2683391 2637761 23549 22081 HKG
タイ 1148848 1092472 25658 30718 THA

セクション3で総人数や観光客の人数を地図に可視化していきます。

1.2 消費単価データ

続いて居住地別の訪日外国人の消費単価データについてです。観光庁のインバウンド消費動向調査(旧 訪日外国人消費動向調査)を利用します。消費単価は一人あたりの消費額で単位は「円」です。聞き取り調査っぽいようです。

データは観光庁ホームページインバウンド消費動向調査(旧 訪日外国人消費動向調査)の「2024年年間 集計表」[Excel:4.5MB]からダウンロードします。ファイル名は001879064.xlsでした。

今回は「表3-2 居住地(21区分)別 1人1回当たり旅行消費単価」を使って演習用データに加工しました。表3-2の地域名、消費単価、回答数を抽出します。外客数のデータと同様に表に記載されている21区分の居住地に対応するISOの3文字コードも事前に追記しておきます。完成したCSVファイル名はinbound_comsumption_2024.csvとしました。

消費単価データ
import pandas as pd
df = pd.read_csv("./data/inbound_comsumption_2024.csv")

データの冒頭5行は表のような形です。人数が調査回答者数となります。

地域 コード 人数 消費単価
韓国 KOR 3529 98385.2324
台湾 TWN 2898 154042.4972
香港 HKG 2835 230987.6834
中国 CHN 4326 256701.8395
タイ THA 1374 174018.8578

セクション3で消費単価を地図に可視化していきます。

2. plotly.express の最低限の使い方

plotlyは非常に高・多機能なライブラリです。世界地図でよく見かけるメルカトル図法やモルワイデ図法っぽい地図に、国や地域の塗り分けを行う機能に絞って必要最低限な事項をまとめておきます。

plotlyは、国・地域のISO 3文字コード2と対応するデータがあれば、plotly.express.choropleth の引数に、可視化したいデータの列名と対応する色を指定するだけで地図上に着色できるという手軽さが特徴です。地理情報の境界データであるシェイプファイルをダウンロードすることで注目したい国や地域に限定したカスタマイズも可能となります。世界地図だと境界データを意識する必要がないのも嬉しい限り:heart_eyes:

2.1 塗り分け例1(カテゴリ別)

実際に塗り分けてみます。とりあえず、日本と着色して地図上で目立ちそうな地域を適当に選んでみました。カテゴリも「A、B、C」の3種類で順番に並べただけです。

地域 コード カテゴリ
日本 JPN A
中国 CHN B
オーストラリア AUS C
アメリカ USA A
カナダ CAN B

国・地域を表すコードとカテゴリを利用した色付けサンプルコードが次のパターンになります。

カテゴリ別の着色
import plotly.express as px
import pandas as pd

# 1. データ:表のデータと同じ
#  最初からISO3コードでの国名とカテゴリ名
df = pd.DataFrame({
    "code": ["JPN", "CHN", "AUS", "USA","CAN"],
    "category":  ["A", "B", "C", "A", "B"]
})

# 2. 色指定:辞書形式でカテゴリーと色をマッピング
#    色:RGBA、hexカラーコード(#112233)も利用可能
color_map = {
    "A": "rgb(0,0,255)",  # rgba(0,0,255,0.5)も利用できる
    "B": "#FFAA33",
    "C": "yellow"}

# 3. コロプレスマップ
fig = px.choropleth(df, 
                    locations="code",
                    color="category",
                    color_discrete_map=color_map)

# 4. 表示
fig.show()

コードのポイント

  • (2) カテゴリと対応する色を辞書形式で指定します。色はRGB・RGBAやHEXカラーコードも利用できます。サンプルコードではバラバラに指定してみました。
色指定
color_map = {"A": "rgb(0,0,255)", "B": "#FFAA33", "C": "yellow"}
  • (3) のコロプレスマップを設定する部分には、

    1. 利用するデータフレーム名: df
    2. 位置を表すlocations: code
    3. 色分けしたい列名: category
    4. color_discrete_mapにカラーマップ: color_map

    の4種類を指定します。

  • 位置情報にはISO3のコードを利用します。

  • カテゴリによる塗り分けは、color_discrete_mapとなります。

地図の準備
fig = px.choropleth(df, locations="code", color="category", color_discrete_map=color_map)
  • (4) fig.show()で画像を表示となります。

実際に表示される地図は次のような図形になります。

world_map_01.png

plotly.express.choroplethのオプション周りは、公式ページのplotly.express.choroplethが参考になります。

カテゴリ別の可視化だと、あるショップの展開で「既存店の進出国 (A)・これから展開したい国や地域 (B)・更にその先 (C)」みたいな時に使えるかな。

2.2 塗り分け例2(数値別)

数値の大小を色の濃淡で表示するタイプの可視化に移ります。人口やGDPで時々見られる定番のタイプです :airplane: 塗り分け例1と同一国を使い、カテゴリの部分を適当な数値に変更しました。

地域 コード 数値
日本 JPN 500
中国 CHN 1000
オーストラリア AUS 300
アメリカ USA 1500
カナダ CAN 400

国・地域を表すコードと数値を利用した色付けサンプルコードが次のパターンになります。

数値データのグラデーション表現
import plotly.express as px
import pandas as pd

# 1. データ:表のデータでコードと数値部分だけ抜き出しています
df = pd.DataFrame({
    "code": ["JPN", "CHN", "AUS", "USA","CAN"],
    "numbers":  [500, 1000, 300, 1500, 400]
})

# 2. コロプレスマップ
fig = px.choropleth(df, 
                    locations="code",
                    color="numbers",
                    color_continuous_scale="Blues")

# 3. 表示
fig.show()

コードのポイント

  • 数値の大小でグラデーション表示するには、
    1. 利用するデータフレーム名: df
    2. 位置を表すlocations: code
    3. 色分けしたい数値の列名: numbers
    4. color_continuous_scaleでカラーマップ: Blues

 の4種類を指定します。

  • 数値のグラデーションによる塗り分けは、color_continuous_scaleとなります。
  • color_continuous_scaleは、単色グラデーション、虹色などいくつも種類があります。

実際に表示される地図は次のような図形になります

world_map_02.png

カテゴリによる塗り分けよりも単純ですが、標準状態のグラデーションだと白っぽい部分がわかりにくいかな?

3. :airplane:訪日外客数や消費単価の可視化🧳

3.1 外客数データの可視化

2024年の外客数データを加工したforeign_visitors_2024.csvを利用して地図上に数値を塗り分けていきます。塗り分け例2(数値別)をベースにしつつ、機能をいくつか盛り込んでみました。

訪日外国人地域別人数
import plotly.express as px
import pandas as pd

# 1. データの読み込みとその他行の削除
df = pd.read_csv("./data/foreign_visitors_2024.csv")
df = df.dropna().copy()   # その他の行を削除 このブロックだけならcopy()不要

# 2. 最小値と最大値を利用してグラデーションの範囲を決める。
# 下限:最小値×0.9
# 上限:最大値×1.1
column_name = "観光客"
margin = 0.1
min_value = df[column_name].min()*(1-margin)
max_value = df[column_name].max()*(1+margin)

# 3. コロプレスマップ
fig = px.choropleth(df,                      # データフレームを指定
                    locations="コード",       # ISO3コードで塗り分け
                    color=column_name,       # 塗り分けるデータフレームの列名
                    hover_name="地域",
                    hover_data={column_name: ":,", "コード": False}, # カンマ区切り表示、コードは非表示
                    range_color=[min_value, max_value],              # 色の範囲を指定
                    color_continuous_scale="Rainbow")                # 虹色にしてみた

# 4. 地図の設定
fig.update_geos(projection_type="robinson",               # 図法の指定
                landcolor="rgb(255, 255, 255)",           # 地図の基本色
                projection_rotation=dict(lat=0, lon=148), # 日本を中心に持ってくる
                showcountries=True,                       # 国境描画
                countrycolor="lightgray",                 # 国境線の色。デフォルトは黒っぽい色?
                countrywidth=0.3,                         # 国境線の太さ。デフォルト:0.5        
                )

# 5. 地図のレイアウト設定
fig.update_layout(dragmode=False,
                  width=800,
                  height=550,
                  title=f"2024年 訪日{column_name} 地域別表示")

# 6. 地図表示
fig.show()

コードのポイント

  • (2) range_colorで色付けする際の最小値と最大値が指定できます。margin分だけ余裕をもたせました。最小値は0.9倍で、最大値は1.1倍で設定してありますが、marginを設けないほうが良い場合もあります。
  • (3) 基本の4つに加えて、ツールチップの制御(hover_◯◯)と色付けする数値の範囲(range_color)の項目を追加しています。
  • (3) locationsで塗り分ける地域を指定、colorで色を付ける部分の数値を指定、サンプルコードでは、観光客列になります。hover_◯◯は、マウスを近づけたときの動作です。地図上の国・地域にマウスカーソルを移動させると名前や人数が表示されます。range_colorで最小値〜最大値の範囲を指定します。今回は虹色で着色してみました。オレンジの韓国がちょっと見づらい?
  • (4) 地図に関する設定です。地図の図法はrobinsonを指定、natural earthが一般的らしいです。日本人にとって見慣れた形にするために、日本を中心に移動させました。projection_rotationに緯度と経度を入力して微調整してください3
  • (5) レイアウトの設定です。dragmode=Falseとすることでマウス操作が制限されます。意図しない拡大縮小や移動が起こらないはず!widthやheightで画像サイズを決められます。

最終的な表示結果は次のような形になります。まあまあといった感じでしょうか :sweat_smile: ちなみに、伝統的な棒グラフも作成してみました。

world_map_visitors.png

世界地図表示はグローバル感があって格好良い:sunglasses: しかし何だろうか?単純にできる古典的な棒グラフに負けた気がする:scream::scream::scream:

bar_graph.png

今回は数値を地図表に表現することが目的だったので解釈は二の次とはいうものの、少しだけ眺めてみました。観光客だと韓国、中国、台湾、アメリカの順番のようです。ポップアップやはりアジア圏が多い。時差も少ないですし。他の年と比較してみると面白いかもしれません。韓国から8,452,682人(845万人)の観光客、圧倒的な人数ですね。

商用客に変更すると順位が変更なります。たしか、中国、韓国、アメリカ、台湾の順位だったかな?

3.2 消費単価データの可視化

一人あたりの消費単価も地図を塗りつぶして表現してみます。

消費単価
import plotly.express as px
import pandas as pd

# 1. データの読み込み
df = pd.read_csv("./data/inbound_consumption_2024.csv")
df = df.dropna()   # その他の行を削除

# 2. 最小値と最大値を利用してグラデーションの範囲を決める。
# 下限:最小値x0.9
# 上限:最大値x1.1
margin = 0.1
min_value = df["消費単価"].min()*(1-margin)
max_value = df["消費単価"].max()*(1+margin)

# 2. 地図表示
fig = px.choropleth(df, 
                    locations="コード",
                    color="消費単価",
                    hover_name="地域",
                    hover_data={"消費単価": ":,",       # ツールチップの設定。カンマ区切り表示
                                "コード": False},       # 「コード」は非表示
                    range_color=[min_value, max_value], # 色の範囲を指定
                    color_continuous_scale="Rainbow")    # グラデーションの色指定

# 3. 地図の基本設定
fig.update_geos(projection_type="natural earth",          # 図法
                landcolor="rgba(255, 255, 255, 0.1)",   # 地図の基本色
                projection_rotation=dict(lat=0, lon=148), # 日本を中心に持ってくる
                showcountries=True,                       # 国境描画
                countrycolor="lightgray",                 # 国境線の色。
                countrywidth=0.3,                         # 国境線の太さ。デフォルト:0.5        
                )

# 4. レイアウトに関する設定
fig.update_layout(dragmode=False,          # マウスの利用不可
                  coloraxis_colorbar=dict(title="消費単価(円)",
                                          tickformat=",.0f"  # カンマ区切り整数
                  ),
                  width=800,
                  height=550,
                  title="2024年 訪日観光客の消費単価")
# 5. 表示
fig.show()

コードのポイント

  • (3) 地図の図法だけ natural earth に変更してみました。

表示される画像は次のようになります。きれいに塗り分けられているように見えます。

world_map_consumption.png

演習用のファイルではマウスカーソルを色のついた付近に持っていくと、国・地域名や消費単価が表示されるはずです。やはり、単純にできる古典的な棒グラフに負けた気がする 😱 格好いいけど情報のわかりやすさという点では棒グラフかも:scream::scream::scream:

bar_graph_03.png

2024年の調査結果のデータによるとフランス、イギリス、オーストラリアあたりの一人あたり消費が大きいようです。爆買イメージの中国は11番目でその他を除くと...「真ん中あたり」 :smile: 一人あたりの消費だと中央値付近のようです。観光客数が6,064,115 (約600万人)と多いので、総額が大きく見えるのかな?600万人で単価が256,701円ということは、...およそ1.55兆円の消費総額です。まさに、単位が兆のレベル :sweat_smile: 一方、845万人と観光客数が多い韓国は、2024年は消費単価が思いの外、小さくて98,385円でした。掛け算で求める消費総額は約0.83兆円となります。観光客数・消費単価ともに5位がアメリカ?

注意

  • 本記事で使用している観光客数や一人あたり消費額のデータについては、出典によって若干の差異が見られる場合がございます。
  • データは演習用としてご用意したものですので、ご利用の際はこの点をご留意くださいますようお願いいたします:sweat_drops:

出典と参考

データソース

おすすめ

  1. 国・地域名をコードに変換するライブラリもあるのですが(例 country-converter)日本語に対応していない気がします。探せばあるのかもしれない。

  2. wikipediaによるとISO 3166-1 alpha-3と呼ばれるらしい。英字3文字による国名コードで日本だとJPNになります。

  3. 数値は適当です。表示された地図と全体のバランスを見つつ、好みに応じて上下左右(東西南北)へ移動してもらえると幸いです。

12
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?