PHPで 都道府県別の就業率の分布を地図上に描く

(1/1)
PHPで 都道府県別の最低賃金の分布を地図上に描く」では、あらかじめ配列変数に用意したデータを白地図にマッピングした。今回は、「e-Stat 政府の統計窓口」から国勢調査のデータを引きだし、白地図にマッピングする PHPプログラムを作ってみる。

目次

サンプル・プログラムの実行例

PHPで都道府県別の最低賃金の分布を地図上に描く

サンプル・プログラムのダウンロード

圧縮ファイルの内容
mappingLaborForceParticipationRate.phpサンプル・プログラム
.pahooEnvクラウドサービスを利用するためのアカウント情報などを記入する .env ファイル。
使い方は「各種クラウド連携サービス(WebAPI)の登録方法」を参照。include_path が通ったディレクトリに配置すること。
pahooInputData.phpデータ入力に関わる関数群。
使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。
pahooGeoCode.php住所・緯度・経度に関わるクラス pahooGeoCode。
使い方は「PHPで住所・ランドマークから最寄り駅を求める」「PHPで住所・ランドマークから緯度・経度を求める」などを参照。include_path が通ったディレクトリに配置すること。
jp.json都道府県境界を描くためのGeoJSONデータ。
使い方は「PHPで住所・ランドマークから最寄り駅を求める」「PHPで都道府県別の最低賃金の分布を地図上に描く」などを参照。pahooGeoCode.php と同じディレクトリに配置すること。
mappingLaborForceParticipationRate.php 更新履歴
バージョン 更新日 内容
1.0.0 2025/10/13 初版
pahooInputData.php 更新履歴
バージョン 更新日 内容
2.0.1 2025/08/11 getParam() bug-fix
2.0.0 2025/08/11 pahooLoadEnv() 追加
1.9.0 2025/07/26 getParam() 引数に$trim追加
1.8.1 2025/03/15 validRegexPattern() debug
1.8.0 2024/11/12 validRegexPattern() 追加
pahooGeoCode.php 更新履歴
バージョン 更新日 内容
6.9.0 2025/09/21 jsPolygon, jsPolygon_Gmap, jsPolygon_Leaflet, loadGeoJSON, getPrefBorderList を追加
6.8.0 2025/08/10 アクセスキーなどを ".pahooEnd" に分離
6.7.1 2025/07/26 jsLine_Gmap() - bug-fix
6.7.0 2025/07/20 drawJSmap,drawGMap -- 引数 $markerLevel 追加
6.6.0 2025/07/19 drawJSmap,drawGMap,drawLeaflet -- マップ中心マーカー表示引数を追加

準備:PHP の https対応

クラウド連携や相手先サイトのデータを読み込むのに https通信を使うため、PHPに OpenSSLモジュールが組み込まれている必要がある。関数  phpinfo  を使って、下図のように表示されればOKだ。
OpenSSL - PHP
そうでない場合は、次の手順に従ってOpenSSLを有効化し、PHPを再起動させる必要がある。

Windowsでは、"php.ini" の下記の行を有効化する。
extension=php_openssl.dll
Linuxでは --with-openssl=/usr オプションを付けて再ビルドする。→OpenSSLインストール手順

これで準備は完了だ。

準備:pahooInputData 関数群

PHPのバージョンや入力データのバリデーションなど、汎用的に使う関数群を収めたファイル "pahooInputData.php" が同梱されているが、include_path が通ったディレクトリに配置してほしい。他のプログラムでも "pahooInputData.php" を利用するが、常に最新のファイルを1つ配置すればよい。

また、各種クラウドサービスに登録したときに取得するアカウント情報、アプリケーションパスワードなどを登録した .pahooEnv ファイルから読み込む関数 pahooLoadEnv を備えている。こちらについては、「各種クラウド連携サービス(WebAPI)の登録方法」をご覧いただきたい。

準備:pahooGeoCode クラス

pahooGeoCode.php

  41: class pahooGeoCode {
  42:     public $items;      // 検索結果格納用
  43:     public $error;      // エラー・フラグ
  44:     public $errmsg;     // エラー・メッセージ
  45:     public $hits;       // 検索ヒット件数
  46:     public $webapi// 直前に呼び出したWebAPI URL
  47: 
  48:     // 都道府県境界線データ
  49:     // SimpleMaps.com is a product of Pareto Software, LLC. © 2010-2025
  50:     // https://simplemaps.com/gis/country/jp
  51:     // ※各自の環境に合わせて設定すること
  52:     public $GeoJsonJP = __DIR__ . '/jp.json';
  53: 
  54:     // -- 以下のデータは .env ファイルに記述可能
  55:     // Google Cloud Platform APIキー
  56:     // https://cloud.google.com/maps-platform/
  57:     // ※Google Maps APIを利用しないのなら登録不要
  58:     public $GOOGLE_API_KEY_1 = '';      // HTTPリファラ用
  59:     public $GOOGLE_API_KEY_2 = '';      // IP制限用
  60:     public $GOOGLE_MAP_ID    = '';      // GoogleMaps ID
  61: 
  62:     // Yahoo! JAPAN Webサービス アプリケーションID
  63:     // https://e.developer.yahoo.co.jp/register
  64:     // ※Yahoo! JAPAN Webサービスを利用しないのなら登録不要
  65:     public $YAHOO_APPLICATION_ID = '';
  66: 
  67:     // OSM Nominatim Search API利用時に知らせるメールアドレス
  68:     // https://wiki.openstreetmap.org/wiki/JA:Nominatim#.E6.A4.9C.E7.B4.A2
  69:     // ※OSM Nominatim Search APIを利用しないのなら登録不要
  70:     public $NOMINATIM_EMAIL = '';
  71: 
  72:     // IP2Location.io APIキー
  73:     // https://www.ip2location.io/
  74:     // ※IP2Location.ioを利用しないのなら登録不要
  75:     public $IP2LOCATION_API_KEY = '';

GoogleマップやLeafletなどによる地図描画や住所検索を行うためのクラスが pahooGeoCode である。同梱のクラス・ファイル "pahooGeoCode.php" は include_path が通ったディレクトリに配置してほしい。他のプログラムでも pahooGeoCodeクラス を利用するが、常に最新のクラス・ファイルを1つ配置すればよい。

地図や住所検索として Google を利用するのであれば Google Cloud Platform APIキーマップID が必要で、その入手方法は「Google Cloud Platform - WebAPIの登録方法」を、Yahoo!JAPAN を利用するのであれば Yahoo! JAPAN Webサービス アプリケーションIDが必要で、その入手方法は「Yahoo!JAPAN デベロッパーネットワーク - WebAPIの登録方法」を、IP2Location.ioを利用するのであれば「PHPでIPアドレスやホスト名から住所を求める」を、それぞれ参照されたい。

PHPのクラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。

準備:各種定数など

mappingLaborForceParticipationRate.php

  53: // 各種定数(START) ===========================================================
  54: 
  55: // Spinner - jQuery UI を使用するかどうか
  56: define('USESPINNER', TRUE);
  57: 
  58: // 数値増減クリックで即計算するかどうか(TRUE:即計算,FALE:計算ボタンを用意)
  59: define('ONCHANGE', FALSE);
  60: 
  61: // 入力可能な西暦年
  62: define('YEAR_MIN', 1950);       // 最小値【変更不可】
  63: define('YEAR_MAX', 2020);       // 最大値【変更不可】
  64: define('YEAR_INTERVAL', 5);     // 年の間隔【変更不可】;国勢調査の年
  65: 
  66: // 地図描画サービスの選択
  67: //    0:Google
  68: //    2:地理院地図・OSM
  69: define('MAPSERVICE', 2);
  70: 
  71: // マップの表示サイズ(単位:ピクセル)
  72: define('MAP_WIDTH',  600);
  73: define('MAP_HEIGHT', 700);
  74: // マップID
  75: define('MAPID', 'map_id');
  76: 
  77: // 初期値
  78: define('DEF_LONGITUDE', 135.4604252);       // 中心座標(経度)
  79: define('DEF_LATITUDE',   35.7883146);       //         (緯度)
  80: define('DEF_TYPE',      'GSIBLANK');        // マップタイプ(地理院白地図)
  81: define('DEF_ZOOM',      5);                 // ズーム
  82: define('DEF_CATEGORY', 'world');            // カテゴリ
  83: 
  84: // キャッシュ保持時間(分) 0:キャッシュしない
  85: // 政府統計 e-Stat へのアクセス負荷軽減
  86: define('LIFE_CACHE_DATA', (60 * 24 * 10));
  87: 
  88: // キャッシュ・ディレクトリ
  89: // 書き込み可能で,外部からアクセスされないディレクトリを指定してください.
  90: define('DIR_CACHE_DATA',   './pcache_estat/');
  91: 
  92: // 政府統計 e-Stat 統計表ID
  93: // 2020年国勢調査:時系列データ:人口の労働力状態,就業者の産業・職業
  94: define('ESTAT_LaborForceParticipationRate', '0003412176');
  95: 
  96: // APPID
  97: if (isset($_ENV['PAHOO_ESTAR_APIKEY'])) {
  98:     define('ESTAT_APPID', $_ENV['PAHOO_ESTAR_APIKEY']);
  99: else {
 100:     define('ESTAT_APPID', '');
 101: }
 102: 
 103: // 各種定数(END) ===============================================================

各種パラメータは定数を defineしている。とくに記載のないものは、適宜変更してかまわない。

表示する地図は、Googleマップ地理院地図・オープンストリートマップ(OSM)から選べる。あらかじめ、定数 MAPSERVIC に値を設定すること。今回は地理院白地図を表示するよう、定数 DEF_TYPEGSIBLAN を設定しているが、他の値でも構わない。

今回は、e-Stat 政府の統計窓口の API を使ってデータを引き出すため、APPID が必要となる。無料で取得できる。取得方法は、「e-Stat 政府統計の総合窓口 - 各種クラウド連携サービス(WebAPI)の登録方法」をご覧いただきたい。
就業率は、2020年(令和2年)の国勢調査で得られた時系列データの人口の労働力状態,就業者の産業・職業を利用する。詳しくは後述するが、e-Stat 政府の統計窓口 では統計表の1つ1つにID番号が割り振られており、これを定数 ESTAT_LaborForceParticipationRate に define しておく。

解説:データのメタ構造を取得

mappingLaborForceParticipationRate.php

 318: /**
 319:  * 政府統計 e-Stat API を使ってデータのメタ構造を取得する
 320:  * @param   string $appid  APPID
 321:  * @param   string $dataID データのID
 322:  * @return  array 取得データ(JSONデコード)/FALSE:取得失敗
 323: */
 324: function getEstatMetaInfo($appid, $dataID) {
 325:     $url = "https://api.e-stat.go.jp/rest/3.0/app/json/getMetaInfo?appId={$appid}&statsDataId={$dataID}&lang=J";
 326: 
 327:     // インスタンス生成
 328:     $pcc = new pahooCache(LIFE_CACHE_DATA, DIR_CACHE_DATA);
 329:     // データ取得
 330:     $json = $pcc->load($url);
 331:     // インスタンス解放
 332:     $pcc = NULL;
 333:     // エラーチェック
 334:     if ($json === FALSE)    return FALSE;
 335: 
 336:     // JSONデコード
 337:     return json_decode($json, TRUE);
 338: }

e-Stat 政府の統計窓口 API で得られるデータ構造は、かなり複雑な構造をしている。そこでまず、データ構造取得する API を呼び出し、得られた JSON 形式のメタ情報を配列として返す。

mappingLaborForceParticipationRate.php

 340: /**
 341:  * 政府統計 e-Stat API を使ってデータのメタ構造をHTML文書にする.
 342:  * @param   string $appid  APPID
 343:  * @param   string $dataID データのID
 344:  * @return  string HTML文書/FALSE:メタ構造の取得に失敗
 345: */
 346: function meta2html($appid, $dataID) {
 347:     $outstr = '';
 348: 
 349:     $data = getEstatMetaInfo($appid, $dataID);
 350:     if ($data === FALSE)    return FALSE;
 351: 
 352:     // メタ情報を $meta に代入する.
 353:     $meta = $data['GET_META_INFO']['METADATA_INF'?? NULL;
 354:     if ($meta === NULL)     return FALSE;
 355: 
 356:     $outstr ."<h3>データID:{$dataID} のメタ構造</h3>\n";
 357: 
 358:     // TABLE_INF の解釈
 359:     $table = $meta['TABLE_INF'?? [];
 360:     if ($table) {
 361:         $statName = htmlspecialchars($table['STAT_NAME']['$'?? ($table['STAT_NAME'?? ''));
 362:         $govOrg   = htmlspecialchars($table['GOV_ORG']['$'?? ($table['GOV_ORG'?? ''));
 363:         $title    = htmlspecialchars($table['TITLE']['$'?? ($table['TITLE'?? ''));
 364:         $cycle    = htmlspecialchars($table['CYCLE'?? '');
 365:         $openDate = htmlspecialchars($table['OPEN_DATE'?? '');
 366:         $updated  = htmlspecialchars($table['UPDATED_DATE'?? '');
 367: 
 368:         $outstr .=<<< EOT
 369: <table class="basicInfo">
 370: <caption>基本情報</caption>
 371: <tr><th>項目</th><th>値</th></tr>
 372: <tr><th>統計名</th><td>{$statName}</td></tr>
 373: <tr><th>所管機関</th><td>{$govOrg}</td></tr>
 374: <tr><th>表題</th><td>{$title}</td></tr>
 375: <tr><th>周期</th><td>{$cycle}</td></tr>
 376: <tr><th>公開日</th><td>{$openDate}</td></tr>
 377: <tr><th>更新日</th><td>{$updated}</td></tr>
 378: </table>
 379: 
 380: EOT;
 381:     }
 382: 
 383:     // CLASS_INF の解釈
 384:     $classInf = $meta['CLASS_INF']['CLASS_OBJ'?? [];
 385:     if ($classInf === NULL)     return FALSE;
 386:     foreach ($classInf as $classObj) {
 387:         $id   = $classObj['@id'?? '';
 388:         $name = $classObj['@name'?? '';
 389:         $desc = $classObj['@description'?? '';
 390:         $classList = $classObj['CLASS'?? [];
 391: 
 392:         // CLASS が単体オブジェクトの場合は配列にする
 393:         if ($classList && array_keys($classList!== range(0, count($classList)-1)) {
 394:             $classList = [$classList];
 395:         }
 396: 
 397:         $outstr ."<table class=\"classInfo\">\n";
 398:         $outstr .'<caption>' . $name . ' (' . $id . ')</caption>';
 399:         if ($desc) {
 400:             $outstr .'<tr><td colspan="5">' . nl2br(htmlspecialchars($desc)) . "</td></tr>\n";
 401:         }
 402: 
 403:         $outstr ."<tr><th>コード</th><th>名称</th><th>レベル</th><th>親コード</th><th>単位</th></tr>\n";
 404:         foreach ($classList as $c) {
 405:             $code   = htmlspecialchars($c['@code'?? '');
 406:             $cname  = htmlspecialchars($c['@name'?? ($c['name'?? ''));
 407:             $level  = htmlspecialchars($c['@level'?? '');
 408:             $parent = htmlspecialchars($c['@parentCode'?? '');
 409:             $unit   = htmlspecialchars($c['@unit'?? '');
 410:             $outstr .'<tr>';
 411:             $outstr .'<td>' . $code . '</td>';
 412:             $outstr .'<td>' . $cname . '</td>';
 413:             $outstr .'<td>' . $level . '</td>';
 414:             $outstr .'<td>' . $parent . '</td>';
 415:             $outstr .'<td>' . $unit . '</td>';
 416:             $outstr ."</tr>\n";
 417:         }
 418:         $outstr .'</table>';
 419:     }
 420: 
 421:     return $outstr;
 422: }

つづいて、この配列を画面に表示するよう HTML文に変換するのがユーザー定義関数 meta2html である。
この関数は、統計表の種類(ID)によらず、共通して利用できる。就業率以外の統計表を白地図にマッピングしたいときにも利用できるだろう。

解説:e-Stat API を使ってデータを取得する

mappingLaborForceParticipationRate.php

 424: /**
 425:  * 政府統計 e-Stat API を使ってデータを取得する
 426:  * @param   string $appid  APPID
 427:  * @param   string $dataID データのID
 428:  * @return  array 取得データ(JSONデコード)/FALSE:取得失敗
 429: */
 430: function getEstatData($appid, $dataID) {
 431:     $url = "https://api.e-stat.go.jp/rest/3.0/app/json/getStatsData?appId={$appid}&statsDataId={$dataID}";
 432: 
 433:     // インスタンス生成
 434:     $pcc = new pahooCache(LIFE_CACHE_DATA, DIR_CACHE_DATA);
 435:     // データ取得
 436:     $json = $pcc->load($url);
 437:     // インスタンス解放
 438:     $pcc = NULL;
 439:     // エラーチェック
 440:     if ($json === FALSE)    return FALSE;
 441: 
 442:     // JSONデコード
 443:     return json_decode($json, TRUE);
 444: }

e-Stat 政府の統計窓口 API を使ってデータを得るのがユーザー関数 getEstatData である。API に負荷をかけないよう、pahooCacheクラスを使ってデータ取得する。
得られた JSON形式データは配列にして返す。

mappingLaborForceParticipationRate.php

 446: /**
 447:  * 指定年の各都道府県別の15歳以上労働力率を取得する
 448:  * @param   int $year 取得したい年
 449:  * @return  array(都道府県コード, 15歳以上人口)
 450: */
 451: function getLaborForceParticipationRate($year) {
 452:     $data = getEstatData(ESTAT_APPID, ESTAT_LaborForceParticipationRate);
 453:     if ($data === FALSE)    return FALSE;
 454: 
 455:     // DATA 部分の取得
 456:     $statsData = $data['GET_STATS_DATA']['STATISTICAL_DATA'?? NULL;
 457:     if (!$statsData)    return FALSE;
 458: 
 459:     $tabData = $statsData['DATA_INF']['VALUE'?? [];
 460: 
 461:     // 配列へ格納
 462:     $items = [];
 463:     foreach ($tabData as $d) {
 464:         $tabCode  = $d['@tab']  ?? '';      // 表章項目コード
 465:         $timeCode = $d['@time'?? '';      // 年コード
 466:         $areaCode = $d['@area'?? '';      // 都道府県コード
 467:         $val = $d['$'?? 0;
 468: 
 469:         // 労働力率かつ指定年
 470:         if (($tabCode === '1240'&& ($timeCode >= (sprintf('%04d', $year. '000000'))) {
 471:             $prefId = (int)substr($areaCode, 0, 2);
 472:             $items[$prefId] = (float)$val;
 473:         }
 474:     }
 475: 
 476:     return $items;
 477: }

この配列から、指定した西暦年にマッチするデータを抽出するのがユーザー定義関数 getLaborForceParticipationRate である。
前述の meta2html 関数で得られたメタ情報を元に、都道府県コードを添字に、労働力率を値として配列 $items に格納して返す。

解説:メイン・プログラム

mappingLaborForceParticipationRate.php

 633:     // データの取得
 634:     $items = getLaborForceParticipationRate($year);
 635:     if ($items === FALSE) {
 636:         $errmsg = 'データ取得に失敗しました';
 637:     } else {
 638:         // 都道府県テーブルに代入する
 639:         foreach ($items as $key=>$val) {
 640:             $prefTable[$key][2] = $val;
 641:         }
 642: 
 643:         // データの最大値と最小値を取得する.
 644:         list($min, $max) = getMinMaxInTable($prefTable);
 645: 
 646:         // 都道府県境界データをGeoJSON配列で取得する.
 647:         $prefBorderList = $pgc->getPrefBorderList();
 648: 
 649:         // 最低賃金を色分け表示するための多角形を生成する.
 650:         $jsPolygons = '';
 651:         foreach ($prefBorderList as $id=>$prefBorders) {
 652:             $color = getColorCode($prefTable[$id][2], $min, $max);
 653:             foreach ($prefBorders['geometry'as $prefBorder) {
 654:                 $jsPolygons .$pgc->jsPolygon($prefBorder, $color, '0.6', 1, $color, '0.6', MAPSERVICE);
 655:             }
 656:         }
 657: 
 658:         // 白地図を描画するJavaScriptコードを生成する.
 659:         $mapid  = MAPID;
 660:         $height = MAP_HEIGHT;
 661:         $jsmap  = $pgc->drawJSMap(MAPID, DEF_LATITUDE, DEF_LONGITUDE, DEF_TYPE, DEF_ZOOM, NULL, NULL, MAPSERVICE, $jsPolygons);
 662:         $res =<<< EOT
 663: {$jsmap}
 664: <div id="{$mapid}" style="width:{$width}px; height:{$height}px; margin:20px 0px 20px 0px;"></div>
 665: 
 666: EOT;
 667:     }
 668: }

メイン・プログラムでは、getLaborForceParticipationRate で得られたデータを、あらかじめ用意した都道府県テーブル(配列) $prefTable に代入し、白地図を描画する JavaScriptコードを生成する。
白地図を描画する JavaScriptコードを生成する関数/メソッドは「PHPで 都道府県別の最低賃金の分布を地図上に描く」で説明したので、ここでは割愛する。

参考サイト

(この項おわり)
header