2018年7月24日 エンジニアリング

日本の都道府県区域に応じたRegionMapを作成する

著者 Kosho Owa (JP)

Kibanaチームからのお知らせの通り、KibanaのRegion Mapが、日本の都道府県の区域に応じたコロプレス地図(階級区域分布図)に対応しました。もし都道府県の人口密度のデータがあれば、それを色の濃淡で塗り分けることができます。ウェブサーバーのログファイルをElasticsearchにインデックスしていれば、アクセスが多かった都道府県を濃い色、少なかった地域を薄い色で表現することができます。もちろん、利用方法はこれらに限らず、都道府県の名称やコードなどの情報があれば、どのようなデータにも応用可能です。また、たとえ都道府県の情報がなくても、IPアドレスがあれば、LogstashのGeoIPフィルターで地理情報に変換し、Region Mapで可視化することができます。

対応する都道府県の識別子

地図そのものや都道府県の境界に関する情報は、Elastic Maps Serviceで配信しています。日本の都道府県を表すものとして有効なのは、現在以下の4種類です。

識別子 Join Field
ISO-3166-2 ISO-3166-2 identifier JP-01
全国地方公共団体コードのうち都道府県 Dantai administrative division code 010006
都道府県名(アルファベット) Prefecture name (English) Hokkaidō Prefecture
都道府県名(漢字) Prefecture name (Japanese) 北海道

つまりこれらのうちいずれかと数値を含む以下のようなドキュメントを作成し、Elasticsearchにインデックスすれば、Region Mapで可視化することができます。

{
  "region": "東京都",       // Prefecture name (Japanese)
  "population": 13742906
}

Japan Population Density

LogstashのGeoIPフィルターと組み合わせて使う

LogstashのGeoIPフィルターは、IPアドレスから、おおよその位置情報を知るのに便利です。大陸や国の情報だけでなく、都道府県、市区町村、緯度経度などの情報を入力データに付加します。

{
  "geoip": {
    "postal_code": "098-5722",
    "continent_code": "AS",
    "country_name": "Japan",
    "city_name": "Sapporo",
    "region_code": "01",
    "country_code3": "JP",
    "timezone": "Asia/Tokyo",
    "location": {
      "lat": 43.0642,
      "lon": 141.3469
    },
    "ip": "210.238.203.11",
    "region_name": "Hokkaido",
    "country_code2": "JP"
  }
}

このプラグインは、初期値ではGeoLite2データベースを利用していますが、このregion_nameは、Elastic Maps Serviceが対応するアルファベットの都道府県名とは一致しません。MaxMindのデータベースは、”Hokkaido”を返しますが、Elastic Maps Serviceが期待するのは、”Hokkaidō Prefecture”という文字列です。同様に”Ōsaka”は”Ōsaka Prefecture”、”Fukushima-ken”は”Fukushima Prefecture”と対応します。このいわゆるローマ字の都道府県名は”Japanese Industrial Standards Committee (JISC), 1997-03-25”で定められているようですが、複数の表記方法を許容しており、これを頼るのは適当ではありません。そこで、2桁のCountry(国)とSubdivision(区域)コードを結合して”JP-01”といったISO-3166-2に従った文字列を作成します。そのためにはLogstashのfilter内を以下のように定義します。

filter {
  geoip {
    source => "ip"
  }
  if [geoip][region_code] {
    mutate {
      add_field => {
        "[geoip][region_iso_code]" => "%{[geoip][country_code2]}-%{[geoip][region_code]}"
      }
    }
  }
}

これで得られたgeoip.region_iso_codeをRegion Mapのバケットとして利用することができます。Region MapのJoin Fieldの設定ではISO-3166-2 identifierを選択して下さい。

ElasticsearchのIngest Geoip Processorも同様のデータベースを使用していて、ローマ字の都道府県名を得られますが、バージョン6.3.1の時点でではSubdivision(区域)コードは取得できません。これは、今後のバージョンで対応する見込みです。その進捗に興味のある方は、こちらのPRをご覧ください。

KibanaのScript Fieldを使う

すでにElasticsearchにデータがインデックスされている場合には、どうでしょうか。Script Fieldを使ってCountry(国)とSubdivision(区域)コードを結合することが考えられます。Management > Index Patternsより該当するインデックスパターンを選択し、以下のようなScript Fieldを作成します。

Name: geoip.region_iso_code
Language: painless
Type: string
Script: doc['geoip.country_code2.raw'].value + "-" + doc['geoip.region_code.raw'].value

これで同様にgeoip.region_iso_codeをRegion Mapの都道府県情報として使用することができます。

まとめ

Region Mapを利用して日本の都道府県ごとの人口密度を表したのが、先の図です。Data Tableを使って人口密度が高い順に並べて表示するのは容易ですが、Region Mapを使うと人口密度がそれぞれ1位、2位の、東京、大阪が離れた場所にあることが容易にわかりますし、日本の地理に詳しくない方々にとっては有益な情報になるでしょう。また、Elasticsearchの集計機能(Aggregation)を利用すれば、ログやメトリックとして記録された時系列データからリアルタイムに素早く合計(Sum)、最大(Max)、最小(Min)、平均(Average)などを計算し、Region Mapに表現することが出来ます。