サンプル・プログラムの実行例
サンプル・プログラム
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年版 |
バージョン | 更新日 | 内容 |
---|---|---|
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年に更新 |
2.4 | 2021/04/23 | データを2019年に更新 |
関数/メソッド | 機能 | 詳細 |
---|---|---|
exitIfLessVersion | PHPが指定したバージョン未満ならメッセージを表示して強制終了する. | |
isCommandLine | コマンドラインから起動されたかどうかを求める. | |
isButton | HTML FORMで指定したボタンが押されたかどうかを求める. | filter_input()関数および $argv を参照する. |
getParam | HTML FORMで指定したINPUTの内容を取り出す. | filter_input()関数および $argv を参照する. |
validNumber | 数値バリデーションを行う. | 数値が整数か小数かを指定し,最小値と最大値を指定する. |
getValidNumber | HTML FORMで指定したINPUTの内容を数値として取り出す(バリデーション付き) | filter_input()関数および $argv を参照する. |
validString | 文字列バリデーションを行う. | filter_input()関数および $argv を参照する.文字列の最小長,最大長,排除または受容するパターンを指定する. |
getValidString | HTML FORMで指定したINPUTの内容を文字列として取り出す(バリデーション付き) | filter_input()関数および $argv を参照する. |
getPasswordHash | パスワード・ハッシュをつくる. | |
veryfyPassword | パスワードがハッシュに合致するかどうかを求める. | |
roundFloat | 小数を指定した桁数で丸めて文字列として返す。 | 与えた小数の有効桁数より指定桁数が多いときには,末尾に0をサプレスする. |
解説:準備
66: //元となるCSVデータファイル名
67: //人口・死亡率:2021年 https://www.stat.go.jp/data/nenkan/72nenkan/02.html
68: //出生率:2020年の中位値 https://www.ipss.go.jp/syoushika/tohkei/Popular/P_Detail2022.asp?fname=T04-09.htm
69: define('FILE_DATA', './population2022.csv');
70:
71: //推計開始年(元データの年次)
72: define('YEAR_START', 2021);
"population2022.csv" の各列の構造は以下の通り。いずれも2022年時点の値である。
- 年齢
- その年齢における男性の死亡率(千人あたり)
- その年齢における女性の死亡率(千人あたり)
- その年齢における出生率(女性一人あたり)
- その年齢における男性人口(千人)
- その年齢における女性人口(千人)
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: );
解説:出生率
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: }
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: }
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: }
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: }
出生率の変動によって人口推計結果が大幅に変わるので、適宜関数を用意してみてほしい。
解説:死亡率
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: }
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: }
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: }
死亡率の変動によって人口推計結果が大幅に変わるので、適宜関数を用意してみてほしい。
解説:事業所数
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: }
解説:人口推計
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を使って人口の推計を行うシミュレーション・プログラムを作ってみることにする。
(2023年12月20日)データを2022年版に更新,pahooInputData導入
(2023年5月5日)グラフにフッタを追加した。
(2023年2月12日)2021年の統計データに更新した。