目次
サンプル・プログラムの実行例
いまから100年前は釣り鐘型をしていたものが、太平洋戦争終戦の年には男性の壮年人口が極端に減り、戦後には団塊の世代の突出部分と丙午の凹みがあらわれ、21世紀には壺型へと変化していく。80歳以上人口の重みの違いも、あらためて認識することができるだろう。
サンプル・プログラムのダウンロード
| shiftPopulationPyramid.php | サンプル・プログラム |
| .pahooEnv | クラウドサービスを利用するためのアカウント情報などを記入する .env ファイル。 使い方は「各種クラウド連携サービス(WebAPI)の登録方法」を参照。include_path が通ったディレクトリに配置すること。 |
| pahooInputData.php | データ入力に関わる関数群。 使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。 |
| pahooCache.php | キャッシュ処理に関わるクラス pahooCache。 キャッシュ処理に関わるクラスの使い方は「PHPで天気予報を求める」を参照。include_path が通ったディレクトリに配置すること。 |
| p1920_1994.csv | 1920~1994年の年別・男女別・年齢別人口データを収録したCSVファイル。 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 1.0.0 | 2026/01/24 | 初版 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 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() 追加 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 1.3.0 | 2025/12/06 | PHP8.5対応:curl_closeを使わない |
| 1.2.0 | 2025/09/06 | cLoad() HTTPヘッダを送信できるようにした |
| 1.1.3 | 2025/08/10 | var→public |
| 1.1.2 | 2023/07/22 | bug-fix |
| 1.1.1 | 2023/02/11 | コメント追記 |
準備:PHP の https対応
Windowsでは、"php.ini" の下記の行を有効化する。
extension=php_openssl.dllLinuxでは --with-openssl=/usr オプションを付けて再ビルドする。→OpenSSLインストール手順
これで準備は完了だ。
準備:pahooInputData 関数群
また、各種クラウドサービスに登録したときに取得するアカウント情報、アプリケーションパスワードなどを登録した .pahooEnv ファイルから読み込む関数 pahooLoadEnv を備えている。こちらについては、「各種クラウド連携サービス(WebAPI)の登録方法」をご覧いただきたい。
準備:pahooCache クラス
pahooCache.php
13: class pahooCache {
14: const LIFE_CACHE = (2 * 60); // キャッシュ保持時間(デフォルト;分)
15: const DEF_DIRCACHE = './pcache/'; // キャッシュ・ディレクトリ(デフォルト)
16:
17: public $lifeCache; // キャッシュ保持時間(分)(0:キャッシュしない)
18: public $dirCache; // キャッシュ用ディレクトリ
19: public $httpHeader; // HTTPヘッダ(空文字の時は何も送らない)
20: public $error; // エラーフラグ
21: public $errmsg; // エラーメッセージ
22: public $debug; // デバッグ用ファイル名
23:
24: /**
25: * コンストラクタ
26: * 参考サイト https://www.pahoo.org/e-soul/webtech/php06/php06-72-01.shtm
27: * @param int $life キャッシュ保持時間(分)(省略可能)
28: * @param string $dir キャッシュ・ディレクトリ(省略可能)
29: * @param array $httpHeader httpヘッダに渡す配列(省略可能)
30: * USER AGENT偽装に用いることを想定
31: * (例)
32: * array(
33: * 'User-Agent: Mozilla/5.0(Windows NT 10.0; Win64; x64) pahooAppy/pahoo.org AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36',
34: * 'Accept-Language: ja-JP'
35: * );
36: * @return なし
37: */
38: function __construct($life=self::LIFE_CACHE, $dir=self::DEF_DIRCACHE, $httpHeader=NULL) {
39: if ($life < 0) {
40: $life = 0;
41: }
42: if (preg_match('/\/$/ui', $dir) == 0) {
43: $dir = $dir . '/';
44: }
45: $this->error = FALSE;
46: $this->errmsg = '';
47: $this->debug = '';
48: $this->lifeCache = $life;
49: $this->dirCache = $dir;
50: $this->httpHeader = $httpHeader;
51:
52: // PHP5以上であることを調べる.
53: if (! $this->isphp5over()) {
54: $this->error = TRUE;
55: $this->errmsg = '動作にはPHP5以上が必要です';
56: return;
57: }
58:
59: // キャッシュ・ディレクトリが無ければ作成する.
60: if (! is_dir($this->dirCache)) {
61: $res = mkdir($this->dirCache, 0744);
62: if ($res == FALSE) {
63: $this->error = TRUE;
64: $this->errmsg = 'キャッシュ・ディレクトリ "' . $this->$dirCache . '" の作成に失敗しました';
65: return;
66: }
67: }
68: }
そこで、頻繁に変更がないデータについては、一度取り込んだら、こちら側のサーバのローカルストレージにキャッシュしておく仕組みを用意した。それが pahooCacheクラス である。同梱のクラス・ファイル "pahooCache.php" は include_path が通ったディレクトリに配置してほしい。他のプログラムでも pahooCacheクラス を利用するが、常に最新のクラス・ファイルを1つ配置すればよい。
pahooCacheクラス の注意ポイントは、キャッシュ時間(単位:分)とキャッシュを保存するディレクトリをコンストラクタで指定している点だ。これらはプログラムによって変わるものである。インスタンス化するときの値は、pahooCacheクラス を利用するメイン・プログラムの方で解説する。
サイトによっては、User-Agent などを必要とすることがあるだろう。そこで、第3引数に HTTPヘッダ として送信するデータを配列で渡すことができるようにした。配列の構造はコメントを参照していただきたい。
PHPのクラスについては「PHPでクラスを使ってテキストの読みやすさを調べる」を参照されたい。
準備:jqPlotプラグイン
shiftPopulationPyramid.php
124: <!-- jqPlot 本体 -->
125: <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqPlot/1.0.9/jquery.jqplot.min.css">
126: <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
127: <script src="https://cdnjs.cloudflare.com/ajax/libs/jqPlot/1.0.9/jquery.jqplot.min.js"></script>
128:
129: <!-- プラグイン -->
130: <script src="https://cdnjs.cloudflare.com/ajax/libs/jqPlot/1.0.9/plugins/jqplot.barRenderer.min.js"></script>
131: <script src="https://cdnjs.cloudflare.com/ajax/libs/jqPlot/1.0.9/plugins/jqplot.categoryAxisRenderer.min.js"></script>
132: <script src="https://cdnjs.cloudflare.com/ajax/libs/jqPlot/1.0.9/plugins/jqplot.canvasAxisTickRenderer.min.js"></script>
133: <script src="https://cdnjs.cloudflare.com/ajax/libs/jqPlot/1.0.9/plugins/jqplot.canvasTextRenderer.min.js"></script>
134: <style type="text/css">
HTMLの <head> タグに、ライブラリ「jQuery」と、必要な jPlotプラグインを記述する。
プログラムの流れ
- サーバ‥‥データの読み込み,グラフ描画スクリプトの生成
- クライアント‥‥スライダーを動かしたときにインタラクティブにグラフを描き変える
準備:各種定数など
shiftPopulationPyramid.php
51: // 各種定数(START) ===========================================================
52:
53: // グラフの幅・高さ
54: define('GRAPH_WIDTH', 600);
55: define('GRAPH_HEIGHT', 600);
56:
57: // jqPlotのあるフォルダ
58: //define('JQPLOT', '../../../../common/jqplot/');
59: define('JQPLOT', './common/jqplot/');
60:
61: // 1920~1994年の年齢別人口データを収録したCSVファイル
62: // 元データ https://api.e-stat.go.jp/rest/3.0/app/getStatsData?appId=858e563093591e6063fb302cbc5669fdef933ae7&statsDataId=0003448228
63: define('POPULATION_CSV', './p1920_1994.csv');
64:
65: // 年齢の最大値・最小値
66: define('AGE_MAX', 100);
67: define('AGE_MIN', 0);
68:
69: // 年齢別人口の最大値(万人)
70: define('HEADCOUNT_MAX', 140);
71:
72: // キャッシュ保持時間(分) 0:キャッシュしない
73: // 政府統計 e-Stat へのアクセス負荷軽減
74: define('LIFE_CACHE_DATA', (60 * 24 * 30));
75:
76: // キャッシュ・ディレクトリ
77: // 書き込み可能で,外部からアクセスされないディレクトリを指定してください.
78: define('DIR_CACHE_DATA', './pcache_estat/');
79:
80: // APPID
81: if (isset($_ENV['PAHOO_ESTAR_APIKEY'])) {
82: define('ESTAT_APPID', $_ENV['PAHOO_ESTAR_APIKEY']);
83: } else {
84: define('ESTAT_APPID', '');
85: }
86:
87: // 各種定数(END) ===============================================================
今回は、e-Stat 政府の統計窓口の API を使ってデータを引き出すため、APPID が必要となる。無料で取得できる。取得方法は、「e-Stat 政府統計の総合窓口 - 各種クラウド連携サービス(WebAPI)の登録方法」をご覧いただきたい。
解説:e-Stat API を使ってデータを取得する
shiftPopulationPyramid.php
227: /**
228: * 政府統計 e-Stat API を使ってデータを取得する
229: * @param string $appid APPID
230: * @param array $populations 人口データを格納する配列
231: * @return int 取得データ数/FALSE:取得失敗
232: */
233: function getPopulationDataFromEstat($appid, &$populations) {
234: $dataIDlist = array(
235: '0003448228', // 2020~2024年
236: '0003459018', // 2015~2019年
237: '0004008040', // 2010~2014年
238: '0004010040', // 2005~2009年
239: '0004018845', // 2000~2004年
240: '0004029959', // 1995~1999年
241: );
242: $classList = array(
243: 'cat01', 'cat02', 'cat03', 'time'
244: );
245:
246: $codeList = array();
247: $cnt = 0;
248:
249: // インスタンス生成
250: $pcc = new pahooCache(LIFE_CACHE_DATA, DIR_CACHE_DATA);
251:
252: // データ読み込み
253: foreach ($dataIDlist as $dataID) {
254: $url = "https://api.e-stat.go.jp/rest/3.0/app/getStatsData?appId={$appid}&statsDataId={$dataID}";
255:
256: // データ取得
257: $xmlString = $pcc->load($url);
258: // エラーチェック
259: if ($xmlString === FALSE) return FALSE;
260:
261: // XMLパーシング
262: $xml = @simplexml_load_string($xmlString);
263: // エラーチェック
264: if ($xml === FALSE) return FALSE;
265: if (! isset($xml->STATISTICAL_DATA->CLASS_INF->CLASS_OBJ)) return FALSE;
266: if (! isset($xml->STATISTICAL_DATA->DATA_INF->VALUE)) return FALSE;
267:
268: // データ要素を取得する
269: foreach ($xml->STATISTICAL_DATA->CLASS_INF->CLASS_OBJ as $obj) {
270: $attr = $obj->attributes();
271: $objID = (string)$attr['id'];
272: foreach ($obj->CLASS as $class) {
273: $attr = $class->attributes();
274: $className = (string)$attr['name'];
275: // 年齢のコード
276: if (preg_match('/^([0-9]+)歳/ui', $className, $arr) > 0) {
277: $codeList[$objID][(string)$attr['code']] = (int)$arr[1];
278: // 西暦年のコード
279: } else if (preg_match('/^([0-9]+)年/ui', $className, $arr) > 0) {
280: $codeList[$objID][(string)$attr['code']] = (int)$arr[1];
281: // その他のコード
282: } else if (preg_match('/^(男|女|総人口|日本人人口)$/ui', $className, $arr) > 0) {
283: $codeList[$objID][(string)$attr['code']] = $className;
284: }
285: }
286: }
287:
288: // データを連想配列に格納する
289: foreach ($xml->STATISTICAL_DATA->DATA_INF->VALUE as $value) {
290: $attr = $value->attributes();
291: $flag = TRUE;
292: // 西暦年
293: if (! isset($codeList['time'][(string)$attr['time']])) {
294: $flag = FALSE;
295: } else {
296: $time = $codeList['time'][(string)$attr['time']];
297: }
298: // 総人口|日本人人口
299: if (! isset($codeList['cat02'][(string)$attr['cat02']])) {
300: $flag = FALSE;
301: } else {
302: $cat02 = $codeList['cat02'][(string)$attr['cat02']];
303: }
304: // 男|女
305: if (! isset($codeList['cat01'][(string)$attr['cat01']])) {
306: $flag = FALSE;
307: } else {
308: $cat01 = $codeList['cat01'][(string)$attr['cat01']];
309: }
310: // 年齢
311: if (! isset($codeList['cat03'][(string)$attr['cat03']])) {
312: $flag = FALSE;
313: } else {
314: $cat03 = $codeList['cat03'][(string)$attr['cat03']];
315: }
316: // データを配列に代入
317: if ($flag) {
318: $populations[$time][$cat02][$cat01][$cat03] = (int)$value * 1000;
319: $cnt++;
320: }
321: }
322: }
323: // インスタンス解放
324: $pcc = NULL;
325:
326: return $cnt;
327: }
得られた XML形式データを連想配列 $populations に格納する。ここで、人口ピラミッドを描きやすいように連想配列の構造は
$populations[西暦年(int)][総人口)|日本人人口)][男|女)][年齢(int)]のようにした。
e-Stat API では、5年ごとに行われる国勢調査を基準にデータが作成され、5年ごとに dataID が変わる。そこで、dataID のリストを、あらかじめ配列 $dataIDlist に用意した。今後、国勢調査が行われる都度、要素である dataID を増やしていく必要がある。
なお、1994年(平成6年)以前は後述するように Excelファイルとして提供されているため、別の関数を使って読み込むことにする。
応答データ(XML形式)は下記のような構造をしている。
<DATA_INF> タグの中にある <VALUE> タグに1つ1つの人口データが格納されている。属性に cat91, cat02, vat03, area, time, unit があるが、それぞれが意味する内容は、<CLASS_INF> タグの中に記載されている。
解説:1920~1994年の人口データを収録したCSVファイルからデータを取得する
shiftPopulationPyramid.php
182: /**
183: * 1920~1994年の年齢別人口データを収録したCSVファイルからデータを取得する
184: * @param string $fname CSVファイル名
185: * @param array $populations 人口データを格納する配列
186: * @return int 取得データ数/FALSE:取得失敗
187: */
188: function getPopulationDataFromCSV($fname, &$populations) {
189: $infp = fopen($fname, 'r');
190: if ($infp == FALSE) return FALSE;
191:
192: // 年号
193: $years = array();
194: $str = fgets($infp);
195: if (($arr = preg_split('/\,/i', $str)) === FALSE) return FALSE;
196: foreach ($arr as $val) {
197: if (preg_match('/([0-9]+)/i', $val, $arr2) > 0) {
198: $years[] = (int)$arr2[1];
199: }
200: }
201:
202: // 男女ラベル(読み飛ばす)
203: $str = fgets($infp);
204:
205: // 年齢別人口
206: $cnt = $age = 0;
207: while (! feof($infp)) {
208: $str = fgets($infp);
209: if (($arr = preg_split('/\,/i', $str)) === FALSE) continue;
210: for ($i = 1; $i < count($arr); $i++) {
211: $year = $years[(int)floor(($i - 1) / 2)];
212: $sex = (($i - 1) % 2 === 0) ? '男' : '女';
213: if (preg_match('/([0-9]+)/i', $arr[$i], $arr2) > 0) {
214: $populations[$year]['総人口'][$sex][$age] = (int)$arr2[1] * 1000;
215: $populations[$year]['日本人人口'][$sex][$age] = (int)$arr2[1] * 1000;
216: $cnt += 2;
217: } else {
218: $populations[$year]['総人口'][$sex][$age] = 0;
219: $populations[$year]['日本人人口'][$sex][$age] = 0;
220: }
221: }
222: $age++;
223: }
224: return $cnt;
225: }
このファイルを直接パースしてもいいのだが、よく見ると、年によって年齢の最大値・最小値が異なっていたり、太平洋戦争中に集計できていない年があったりと、シートによって構造がまちまちである。
そこで、生成AIサービス「Microsoft Copilot」を使って、読み込みやすいCSVファイル形式に変換したものが、同梱のファイル "p1920_1994.csv" である。
ユーザー関数 getPopulationDataFromCSV は、このCSVファイルを読み込んで、前述の連想配列 $populations に格納する。
数字以外の記号が入っていたり、数字が入っていない要素は 0 を代入するようにした。
解説:指定年の人口ピラミッドを描画するスクリプトを生成する
shiftPopulationPyramid.php
329: /**
330: * jqPlotを使って指定年の人口ピラミッドを描画するスクリプトを生成する
331: * @param array $populations 人口データ
332: * @return string JavaScript
333: */
334: function makeJavaScriptDrawPopulationPyramid($populations) {
335: // 年齢
336: $ageMin = AGE_MIN;
337: $ageMax = AGE_MAX;
338: // 年齢別人口
339: $headcountMin = 0 - HEADCOUNT_MAX;
340: $headcountMax = HEADCOUNT_MAX;
341: // 棒グラフの幅
342: $barWidth = (int)(GRAPH_HEIGHT / ($ageMax - $ageMin));
343:
344: $js =<<< EOT
345: function drawPopulationPyramid(year) {
346: const populations = {
347:
348: EOT;
349: foreach ($populations as $year=>$values) {
350: $ages = '';
351: for ($age = $ageMin; $age <= $ageMax; $age++) {
352: $ages = $ages . $age . ',';
353: }
354: $js .=<<< EOT
355: {$year} : {
356: age: [ {$ages} ],
357:
358: EOT;
359:
360: // 男性人口
361: $male = '';
362: for ($age = $ageMin; $age <= $ageMax; $age++) {
363: if (isset($values['日本人人口']['男'][$age])) {
364: $male = $male . '-' . (int)($values['日本人人口']['男'][$age] / 10000) . ',';
365: } else {
366: $male = $male . '-0,';
367: }
368: }
369: $js .=<<< EOT
370: male: [ {$male} ],
371:
372: EOT;
373:
374: // 女性人口
375: $female = '';
376: for ($age = $ageMin; $age <= $ageMax; $age++) {
377: if (isset($values['日本人人口']['女'][$age])) {
378: $female = $female . (int)($values['日本人人口']['男'][$age] / 10000) . ',';
379: } else {
380: $female = $female . '0,';
381: }
382: }
383: $js .=<<< EOT
384: female: [ {$female} ]
385: },
386:
387: EOT;
388: }
389: $js .=<<< EOT
390: };
391:
392: const ages = populations[year].age;
393: const males = populations[year].male;
394: const females = populations[year].female;
395:
396: let yTicks = ages.map(function (age) {
397: return (age % 5 === 0) ? age.toString() : "";
398: });
399:
400: // jqPlot 用データ形式 [値, カテゴリ]
401: const maleSeries = [];
402: const femaleSeries = [];
403:
404: for (let i = 0; i < ages.length; i++) {
405: maleSeries.push([males[i], ages[i]]);
406: femaleSeries.push([females[i], ages[i]]);
407: }
408:
409: // 再描画対策
410: $('#chart').empty();
411:
412: // 描画関数
413: $.jqplot('chart', [maleSeries, femaleSeries], {
414: // title: year + '年',
415: stackSeries: true,
416: seriesDefaults: {
417: renderer: $.jqplot.BarRenderer,
418: rendererOptions: {
419: barDirection: 'horizontal',
420: fillToZero: true,
421: barWidth: {$barWidth},
422: shadow: false
423: }
424: },
425: series: [
426: { label: '男性' },
427: { label: '女性' }
428: ],
429: // グラフの色(正数・負数)
430: seriesColors: ['dodgerblue', 'violet'],
431: negativeSeriesColors: ['dodgerblue', 'violet'],
432: // 軸の設定
433: axes: {
434: yaxis: {
435: renderer: $.jqplot.CategoryAxisRenderer,
436: label: '年齢',
437: ticks: yTicks,
438: },
439: xaxis: {
440: label: '人口(万人)',
441: min: {$headcountMin},
442: max: {$headcountMax},
443: tickInterval: 20,
444: tickOptions: {
445: formatter: function (format, value) {
446: return Math.abs(value);
447: }
448: }
449: }
450: },
451: legend: {
452: show: true,
453: location: 'e'
454: }
455: });
456: }
457:
458: EOT;
459: return $js;
460: }
関数 drawPopulationPyramid の中では、まず、前述の連想配列 [$population] を JavaScript で利用しやすいオブジェクト配列 population に変換する。
次に、グラフ描画関数 $.jqplot を用意する。
スライダーでグラフを再描画していくので、事前に empty() メソッドを使って、1つ前のグラフを消去しておく。
人口ピラミッドは、jqPlot プラグインから見た場合には横棒グラフであり、男性は負数のグラフになっている。横軸のメモリが負数にならないよう、xaxis:tickOptions で絶対値を表示するように指定している。
また、正数(女性)と負数(男性)の棒グラフのカラー指定ができるよう、seriesColors と negativeSeriesColors の両方に同じカラーコードを指定する点に留意されたい。
解説:西暦年を指定するスライダーを生成する
shiftPopulationPyramid.php
462: /**
463: * 西暦年を指定するスライダーを作成
464: * @param array $populations 人口データ
465: * @return string JavaScript
466: */
467: function makeSlider($populations) {
468: // 西暦年を取得する
469: $years = array_keys($populations);
470: sort($years);
471:
472: $width = GRAPH_WIDTH;
473: $html =<<< EOT
474: <div style="width:{$width}px; text-align:center; margin-top:16px;" id="valueDisplay"></div>
475: <input style="width:{$width}px;" type="range" name="slider" id="slider" min="0" max="0" step="1">
476: <script>
477: const keys = [
478:
479: EOT;
480:
481: foreach ($years as $year) {
482: $html .= $year . ',';
483: }
484:
485: $html .=<<< EOT
486: ];
487:
488: // スライダーの設定
489: const slider = document.getElementById('slider');
490: slider.max = keys.length - 1;
491: slider.value = 2020;
492:
493: // 値の表示
494: const display = document.getElementById('valueDisplay');
495: function updateDisplay() {
496: const index = parseInt(slider.value);
497: display.innerHTML = keys[index] + '年';
498:
499: drawPopulationPyramid(keys[index]);
500: }
501: slider.addEventListener('input', updateDisplay);
502:
503: // 初期表示;1秒待ってから表示
504: new Promise(function(resolve) {
505: setTimeout(function() {
506: resolve();
507: }, 1000);
508: }).then(function() {
509: updateDisplay();
510: });
511: </script>
512:
513: EOT;
514:
515: return $html;
516: }
スライダーは、スライダー本体を構築する html 文と、スライダーを動かしたときのインタラクティブなイベントを指定する JavaScript 部分に分かれる。
スライダーが動いたときに発火する JavaScript 関数が updateDisplay である。スライダーから西暦年を取りだし、前述のユーザー関数ユーザー関数 makeJavaScriptDrawPopulationPyramid で生成した JavaScript 関数 drawPopulationPyramid を呼び出す。こうすることで、グラフの再描画はクライアントサイド(JavaScript)で完結する。
なお、前述のユーザー関数 makeJavaScriptDrawPopulationPyramid が PHP の連想配列 [$population] を JavaScript のオブジェクト配列 population に変換する時間を担保する意味で、初回表示は Promise を使って1秒間待つようにしておいた。
解説:メイン・プログラム
shiftPopulationPyramid.php
580: // メイン・プログラム ======================================================
581:
582: $populations = array();
583: $errmsg = '';
584:
585: // 1920~1994年のデータ取得
586: getPopulationDataFromCSV(POPULATION_CSV, $populations);
587: // 1995年以降のデータ取得
588: getPopulationDataFromEstat(ESTAT_APPID, $populations);
589:
590: // 描画用JavaScript生成
591: $js = makeJavaScriptDrawPopulationPyramid($populations);
592:
593: // スライダー作成
594: $slider = makeSlider($populations);
595:
596: // 表示HTML作成
597: $HtmlBody = makeCommonBody($js, $slider, $errmsg);
598:
599: // 表示処理
600: echo $HtmlHeader;
601: echo $HtmlBody;
602: echo $HtmlFooter;
603:
604:
605: /*
- 1920~1994年(平成6年)のデータ取得
- 1995年(平成7年)以降のデータ取得
- 描画用JavaScript生成
- スライダー作成
- 表示HTML作成
- 表示処理
参考サイト
- PHPとJpGraphで人口ピラミッドを表示する:ぱふぅ家のホームページ
- e-Stat 政府の統計窓口
- e-Stat 政府統計の総合窓口 - 各種クラウド連携サービス(WebAPI)の登録方法:ぱふぅ家のホームページ
- PHPで相関係数と回帰直線を表示:ぱふぅ家のホームページ
- PHPで 都道府県別の就業率の分布を地図上に描く:ぱふぅ家のホームページ

今回は、「e-Stat 政府の統計窓口」から、毎年の男女別・年齢別人口データを取りだし、スライダーを使ったインタラクティブに人口ピラミッドの経年変化を表示するプログラムを作ってみることにする。