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

サンプル・プログラム
population.php | サンプル・プログラム本体。 |
pahooInputData.php | データ入力に関わる関数群。 使い方は「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。 |
population2011.csv | 統計データ 2011年版 |
population2017.csv | 統計データ 2017年版 |
population2018.csv | 統計データ 2018年版 |
population2019.csv | 統計データ 2019年版 |
population2020.csv | 統計データ 2020年版 |
population2021.csv | 統計データ 2021年版 |
population2022.csv | 統計データ 2022年版 |
population2023.csv | 統計データ 2023年版 |
バージョン | 更新日 | 内容 |
---|---|---|
2.5.4 | 2025/01/19 | データを2023年版に更新,PHP8.4対応 |
2.5.3 | 2023/12/20 | データを2022年版に更新,pahooInputData導入 |
2.5.2 | 2023/05/05 | グラフにフッタを追加 |
2.5.1 | 2023/02/12 | データを2021年に更新 |
2.5 | 2022/11/01 | データを2020年に更新 |
バージョン | 更新日 | 内容 |
---|---|---|
1.8.0 | 2024/11/12 | validRegexPattern() 追加 |
1.7.0 | 2024/10/09 | validURL() validEmail() 追加 |
1.6.0 | 2024/10/07 | isButton() -- buttonタグに対応 |
1.5.0 | 2024/01/28 | exitIfExceedVersion() 追加 |
1.4.2 | 2024/01/28 | exitIfLessVersion() メッセージ修正 |
解説:準備
population.php
66: // 元となるCSVデータファイル名
67: // 人口・死亡率:2023年 https://www.stat.go.jp/data/nenkan/74nenkan/02.html
68: // 出生率:2022年 https://www.ipss.go.jp/syoushika/tohkei/Popular/Popular2024.asp?chap=4
69: define('FILE_DATA', './population2023.csv');
70:
71: // 推計開始年(元データの年次)
72: define('YEAR_START', 2021);

"population2023.csv" の各列の構造は以下の通り。いずれも2023年時点の値である。
- 年齢
- その年齢における男性の死亡率(千人あたり)
- その年齢における女性の死亡率(千人あたり)
- その年齢における出生率(女性一人あたり)
- その年齢における男性人口(千人)
- その年齢における女性人口(千人)
population.php
90: // 従業者規模別民営事業所数(2016年)
91: // http://www.stat.go.jp/data/nihon/07.html
92: // num=事業所数, color=描画色
93: $tableCompany = array(
94: '1-4人' => array('num'=>3047110,'color'=>'#006600'),
95: '5-9人' => array('num'=>1057293,'color'=>'#00AA00'),
96: '10-19人' => array('num'=>649836, 'color'=>'#00CC00'),
97: '20-29人' => array('num'=>232601, 'color'=>'#00FF00'),
98: '30-49人' => array('num'=>163074, 'color'=>'#00FF44'),
99: '50-99人' => array('num'=>100428, 'color'=>'#00FF88'),
100: '100-199人' => array('num'=>39002, 'color'=>'#00FFAA'),
101: '200-299人' => array('num'=>10454, 'color'=>'#00FFCC'),
102: '300人以上' => array('num'=>12223, 'color'=>'#00FFFF')
103: );
解説:出生率
population.php
206: /**
207: * 出生率の推計関数:推計開始年から一定
208: * @param array $items 推計表
209: * @return なし
210: */
211: function calcFertilityRatio1(&$items) {
212: global $MaxAge;
213:
214: for ($i = 1; $i < PERIOD; $i++) {
215: $year = YEAR_START + $i;
216: for ($age = 0; $age <= $MaxAge; $age++) {
217: $items[$year][$age]['fertility'] = $items[$year - 1][$age]['fertility'];
218: }
219: }
220: }
population.php
222: /**
223: * 出生率の推計関数:毎年1%ずつ減少,0.9で一定
224: * @param array $items 推計表
225: * @return なし
226: */
227: function calcFertilityRatio2(&$items) {
228: global $MaxAge;
229:
230: $d = (-0.01); // 毎年増分
231: $t2 = 0.9; // 下限値
232: for ($i = 1; $i < PERIOD; $i++) {
233: $year = YEAR_START + $i;
234: $total = 0;
235: for ($age = 0; $age <= $MaxAge; $age++) {
236: $items[$year][$age]['fertility'] = $items[$year - 1][$age]['fertility'] * (1 + $d);
237: $total += $items[$year][$age]['fertility'];
238: }
239: if ($total <= $t2) $d = 0;
240: }
241: }
population.php
243: /**
244: * 出生率の推計関数:毎年1%ずつ増加,1.8で一定
245: * @param array $items 推計表
246: * @return なし
247: */
248: function calcFertilityRatio3(&$items) {
249: global $MaxAge;
250:
251: $d = 0.01; // 毎年増分
252: $t1 = 1.8; // 上限値
253: for ($i = 1; $i < PERIOD; $i++) {
254: $year = YEAR_START + $i;
255: $total = 0;
256: for ($age = 0; $age <= $MaxAge; $age++) {
257: $items[$year][$age]['fertility'] = $items[$year - 1][$age]['fertility'] * (1 + $d);
258: $total += $items[$year][$age]['fertility'];
259: }
260: if ($total >= $t1) $d = 0;
261: }
262: }
population.php
264: /**
265: * 出生率の推計関数:0.9と1.8の間で増減
266: * @param array $items 推計表
267: * @return なし
268: */
269: function calcFertilityRatio4(&$items) {
270: global $MaxAge;
271:
272: $sign = (-1); // 増減符号
273: $d = 0.01; // 毎年増分
274: $t1 = 1.8; // 上限値
275: $t2 = 0.9; // 下限値
276: for ($i = 1; $i < PERIOD; $i++) {
277: $year = YEAR_START + $i;
278: $total = 0;
279: for ($age = 0; $age <= $MaxAge; $age++) {
280: $items[$year][$age]['fertility'] = $items[$year - 1][$age]['fertility'] * (1 + $d * $sign);
281: $total += $items[$year][$age]['fertility'];
282: }
283: if ($total >= $t1) $sign = (-1);
284: if ($total <= $t2) $sign = (+1);
285: }
286: }

出生率の変動によって人口推計結果が大幅に変わるので、適宜関数を用意してみてほしい。
解説:死亡率
population.php
299: /**
300: * 死亡率の推計関数:推計開始年から一定
301: * @param array $items 推計表
302: * @return なし
303: */
304: function calcDeathRatio1(&$items) {
305: global $MaxAge;
306:
307: for ($i = 1; $i < PERIOD; $i++) {
308: $year = YEAR_START + $i;
309: for ($age = 0; $age <= $MaxAge; $age++) {
310: $items[$year][$age]['death_male'] = $items[$year - 1][$age]['death_male'];
311: $items[$year][$age]['death_female'] = $items[$year - 1][$age]['death_female'];
312: }
313: }
314: }
population.php
316: /**
317: * 死亡率の推計関数:推計開始年から毎年4‰ずつ減少
318: * @param array $items 推計表
319: * @return なし
320: */
321: function calcDeathRatio2(&$items) {
322: global $MaxAge;
323:
324: $d = (-0.004); // 毎年増分
325: for ($i = 1; $i < PERIOD; $i++) {
326: $year = YEAR_START + $i;
327: for ($age = 0; $age <= $MaxAge; $age++) {
328: $items[$year][$age]['death_male'] = $items[$year - 1][$age]['death_male'] * (1 + $d);
329: $items[$year][$age]['death_female'] = $items[$year - 1][$age]['death_female'] * (1 + $d);
330: }
331: }
332: }
population.php
334: /**
335: * 死亡率の推計関数:推計開始年から毎年4‰ずつ減少
336: * @param array $items 推計表
337: * @return なし
338: */
339: function calcDeathRatio3(&$items) {
340: global $MaxAge;
341:
342: $d = (+0.004); // 毎年増分
343: for ($i = 1; $i < PERIOD; $i++) {
344: $year = YEAR_START + $i;
345: for ($age = 0; $age <= $MaxAge; $age++) {
346: $items[$year][$age]['death_male'] = $items[$year - 1][$age]['death_male'] * (1 + $d);
347: $items[$year][$age]['death_female'] = $items[$year - 1][$age]['death_female'] * (1 + $d);
348: }
349: }
350: }

死亡率の変動によって人口推計結果が大幅に変わるので、適宜関数を用意してみてほしい。
解説:事業所数
population.php
352: /**
353: * 事業所数の推計関数:推計開始年から生産年齢人口に応じて変化
354: * @param array $items 推計表
355: * @return なし
356: */
357: function calcCompany(&$items) {
358: global $tableCompany;
359:
360: // 初年度の生産年齢人口
361: $worker0 = 0;
362: for ($age = WORKER_AGE_MIN; $age <= WORKER_AGE_MAX; $age++) {
363: $worker0 += $items[YEAR_START][$age]['male'] + $items[YEAR_START][$age]['female'];
364: }
365:
366: // 推計
367: for ($i = 0; $i < PERIOD; $i++) {
368: $year = YEAR_START + $i;
369: $worker = 0;
370: for ($age = WORKER_AGE_MIN; $age <= WORKER_AGE_MAX; $age++) {
371: $worker += $items[$year][$age]['male'] + $items[$year][$age]['female'];
372: }
373: foreach ($tableCompany as $key=>$arr) {
374: $items[$year]['company'][$key] = $arr['num'] * ($worker / $worker0);
375: }
376: }
377: }
解説:人口推計
population.php
379: /**
380: * 人口推計+事業所数推計
381: * @param string $opt1 オプション1(出生率の推計関数名)
382: * @param string $opt2 オプション2(死亡率の推計関数名)
383: * @param string $opt3 オプション3(事業所数の推計関数名)
384: * @return array 人口推計結果/FALSE:データファイルがないなど
385: */
386: function calcPopulation($opt1, $opt2, $opt3) {
387: global $MaxAge;
388:
389: $items = array();
390:
391: // 元となるデータファイルを読み込む
392: $infp = fopen(FILE_DATA, 'r');
393: if ($infp == FALSE) return FALSE;
394: fgetcsv($infp, 9999, ',', '"', '\\'); // ラベル行をスキップ
395: while (! feof($infp)) {
396: $arr = fgetcsv($infp, 9999, ',', '"', '\\');
397: if ($arr == FALSE) break;
398: if (! is_numeric($arr[1])) continue;
399: $age = $arr[0];
400: $items[YEAR_START][$age]['death_male'] = $arr[1] / 1000; // 年齢別死亡率(男性)
401: $items[YEAR_START][$age]['death_female'] = $arr[2] / 1000; // 年齢別死亡率(女性)
402: $items[YEAR_START][$age]['fertility'] = $arr[3]; // 年齢別出生率
403: $items[YEAR_START][$age]['male'] = $arr[4] / 10; // 男性人口(単位:万人)
404: $items[YEAR_START][$age]['female'] = $arr[5] / 10; // 女性人口(単位:万人)
405: }
406: fclose($infp);
407: $MaxAge = $age; // 最高齢
408: $opt1($items); // 出生率の推計
409: $opt2($items); // 死亡率の推計
410:
411: // 人口推計
412: for ($i = 1; $i < PERIOD; $i++) {
413: $year = YEAR_START + $i;
414:
415: // 0歳
416: $items[$year][0]['male'] = 0;
417: $items[$year][0]['female'] = 0;
418: for ($age = 0; $age <= $MaxAge; $age++) {
419: $n = $items[$year - 1][$age]['female'] * $items[$year - 1][$age]['fertility']; // 出生数
420: $items[$year][0]['male'] += ($n / 2);
421: $items[$year][0]['female'] += ($n / 2);
422: }
423:
424: // 1歳~$MaxAge歳
425: for ($age = 1; $age <= $MaxAge; $age++) {
426: $items[$year][$age]['male'] = $items[$year - 1][$age - 1]['male'] * (1 - $items[$year][$age]['death_male']);
427: $items[$year][$age]['female'] = $items[$year - 1][$age - 1]['female'] * (1 - $items[$year][$age]['death_female']);
428: }
429: }
430: $opt3($items); // 事業所数の推計
431:
432: return $items;
433: }

まず、冒頭で紹介した初期値データ・ファイル FILE_DATA を読み込む。そして、選択された関数により出生率と死亡率を計算し、推計表 $items に代入する。
次に、このデータを元に、毎年の年齢別人口を計算していく。
0歳人口は、年齢毎に前年の女性人口と出生率を乗算し、男女半数ずつに分けて代入する。
1歳以降の人口は、年齢毎に前年の男女別人口と男女別死亡率を乗算し、代入する。
考察
ただ、国立社会保障・人口問題研究の推計では50年後の男性の平均寿命が84歳(現在79歳)、女性が91歳(現在86歳)となっており、いくらなんでも長生きし過ぎなのではないかと感じる。
そこで本プログラムでは、死亡率が毎年4‰増加(平均寿命が縮む)というオプションを用意してみた。この場合、50~100年後には高齢者比率が減少する。
本プログラムでは各年齢の死亡率が一律に減少/増加するような関数しか用意していないが、高齢者ほど死亡率が高くなるようにすると、高齢者比率の減少は早く訪れる。

出生率については、当たり前のことだが、いま急に増やすことができたとしても、その効果が現れるのは数十年後になる。死亡率や出生率を多少変化させたところで、40~50年後に高齢者割合が極大になる事態は避けられない。
むしろ出生率を急に増やすと、一時的に生産年齢人口が低下するため、現役世代への負担が重くなるという事態に陥る。

余談
年金財政は、基礎年金勘定、国民年金勘定、厚生年金勘定に加え、各共済組合などの帳簿があるので、計算はかなり複雑になる。基礎数値は「厚生労働省年金局 年金財政ホームページ」が参考になる。

簡単に試算したところでは、団塊ジュニアが65歳以上になる25年後から財政が急激に悪化することが確認できた。
ただ、このまま婚姻率が上がらないと、3号被保険者の数がそれほど増えない一方、出生率も極端に低下するだろうから、推計のブレ幅はかなり大きいと言える。
参考書籍
参考サイト
- 日本の将来推計人口:国立社会保障・人口問題研究所
- 日本統計年鑑:総務省統計局
- PHPとJpGraphで人口ピラミッドを表示する:ぱふぅ家のホームページ
そこで今回は、PHPを使って人口の推計を行うシミュレーション・プログラムを作ってみることにする。
(2025年1月19日)データを2023年版に更新,PHP8.4対応