PHPで人口を推計する

(1/1)
2012 年 2 月、国立社会保障・人口問題研究所が日本の将来推計人口を計算し直し、2060 年には 65 歳以上が 4 割に達するとして話題になった。この推計は妥当性があるのだろうか。
そこで今回は、PHP を使って人口の推計を行うシミュレーション・プログラムを作ってみることにする。

(2020 年 4 月 23 日)2018 年の統計データに更新した。

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

日本の人口推計

目次

サンプル・プログラム

圧縮ファイルの内容
population.phpサンプル・プログラム本体。
population2011.csv統計データ 2011年版
population2017.csv統計データ 2017年版
population2018.csv統計データ 2018年版
population2019.csv統計データ 2019年版

解説:準備

グラフ描画には JpGraph を利用する。導入方法については、「PHP と JpGraph で人口ピラミッドを表示する」を参照のこと。

0047: //元となるCSVデータファイル名
0048: //人口・死亡率:2019年 http://www.stat.go.jp/data/nenkan/70nenkan/02.html
0049: //出生率:2020年の中位値 http://www.ipss.go.jp/pp-zenkoku/j/zenkoku2017/pp29_Report2.pdf
0050: define('FILE_DATA', './population2019.csv');
0051: 
0052: //推計開始年(元データの年次)
0053: define('YEAR_START', 2019);

プログラム本体は "population.php"、初期値として使うデータが "population2018.csv" に入っている。同じディレクトリにおいて実行すること。

"population2018.csv" の各列の構造は以下の通り。いずれも 2018 年時点の値である。
  1. 年齢
  2. その年齢における男性の死亡率(千人あたり)
  3. その年齢における女性の死亡率(千人あたり)
  4. その年齢における出生率(女性一人あたり)
  5. その年齢における男性人口(千人)
  6. その年齢における女性人口(千人)
人口と死亡率については日本統計年鑑(総務省統計局)を参考にした。100 歳超の死亡率は分からないので、適当に設定した。出生率については、日本の将来推計人口(国立社会保障・人口問題研究所)の仮定値表の中位推計値を採用した。

0071: //従業者規模別民営事業所数(2014年)
0072: //http://www.stat.go.jp/data/nihon/07.html
0073: // num=事業所数, color=描画色
0074: $tableCompany = array(
0075: '1-4人'             => array('num'=>3225428,'color'=>'#006600'),
0076: '5-9人'             => array('num'=>1090283,'color'=>'#00AA00'),
0077: '10-19人'         => array('num'=>650018,   'color'=>'#00CC00'),
0078: '20-29人'         => array('num'=>230983,   'color'=>'#00FF00'),
0079: '30-49人'         => array('num'=>161096,   'color'=>'#00FF44'),
0080: '50-99人'         => array('num'=>101321,   'color'=>'#00FF88'),
0081: '100-199人'         => array('num'=>38678,    'color'=>'#00FFAA'),
0082: '200-299人'         => array('num'=>10387,    'color'=>'#00FFCC'),
0083: '300人以上'         => array('num'=>12247,    'color'=>'#00FFFF')
0084: );

生産年齢人口減少に伴う企業(事業所)数の減少を推計するため、従業者規模別民営事業所数は 2016 年度の数字を連想配列 $tableCompany に格納した。棒グラフで描くときの描画色もあわせて格納している。

解説:出生率

0216: /**
0217:  * 出生率の推計関数:推計開始年から一定
0218:  * @param array $items 推計表
0219:  * @return なし
0220: */
0221: function calcFertilityRatio1(&$items) {
0222:     global $MaxAge;
0223: 
0224:     for ($i = 1; $i < PERIOD$i++) {
0225:         $year = YEAR_START + $i;
0226:         for ($age = 0; $age <= $MaxAge$age++) {
0227:             $items[$year][$age]['fertility'] = $items[$year - 1][$age]['fertility'];
0228:         }
0229:     }
0230: }

0232: /**
0233:  * 出生率の推計関数:毎年1%ずつ減少,0.9で一定
0234:  * @param array $items 推計表
0235:  * @return なし
0236: */
0237: function calcFertilityRatio2(&$items) {
0238:     global $MaxAge;
0239: 
0240:     $d = (-0.01);  //毎年増分
0241:     $t2 = 0.9;        //下限値
0242:     for ($i = 1; $i < PERIOD$i++) {
0243:         $year = YEAR_START + $i;
0244:         $total = 0;
0245:         for ($age = 0; $age <= $MaxAge$age++) {
0246:             $items[$year][$age]['fertility'] = $items[$year - 1][$age]['fertility'] * (1 + $d);
0247:             $total += $items[$year][$age]['fertility'];
0248:         }
0249:         if ($total <= $t2)  $d = 0;
0250:     }
0251: }

0253: /**
0254:  * 出生率の推計関数:毎年1%ずつ増加,1.8で一定
0255:  * @param array $items 推計表
0256:  * @return なし
0257: */
0258: function calcFertilityRatio3(&$items) {
0259:     global $MaxAge;
0260: 
0261:     $d  = 0.01;       //毎年増分
0262:     $t1 = 1.8;        //上限値
0263:     for ($i = 1; $i < PERIOD$i++) {
0264:         $year = YEAR_START + $i;
0265:         $total = 0;
0266:         for ($age = 0; $age <= $MaxAge$age++) {
0267:             $items[$year][$age]['fertility'] = $items[$year - 1][$age]['fertility'] * (1 + $d);
0268:             $total += $items[$year][$age]['fertility'];
0269:         }
0270:         if ($total >= $t1)  $d = 0;
0271:     }
0272: }

0274: /**
0275:  * 出生率の推計関数:0.9と1.8の間で増減
0276:  * @param array $items 推計表
0277:  * @return なし
0278: */
0279: function calcFertilityRatio4(&$items) {
0280:     global $MaxAge;
0281: 
0282:     $sign = (-1); //増減符号
0283:     $d  = 0.01;       //毎年増分
0284:     $t1 = 1.8;        //上限値
0285:     $t2 = 0.9;        //下限値
0286:     for ($i = 1; $i < PERIOD$i++) {
0287:         $year = YEAR_START + $i;
0288:         $total = 0;
0289:         for ($age = 0; $age <= $MaxAge$age++) {
0290:             $items[$year][$age]['fertility'] = $items[$year - 1][$age]['fertility'] * (1 + $d * $sign);
0291:             $total += $items[$year][$age]['fertility'];
0292:         }
0293:         if ($total >= $t1)  $sign = (-1);
0294:         if ($total <= $t2)  $sign = (+1);
0295:     }
0296: }

シミュレーションでは、出生率の推移を幾つか選択できるようになっている。出生率を推計表 $items に返す関数を用意し、グローバル変数 $SelectOption1 に設定してやれば選択できるようになる。

出生率の変動によって人口推計結果が大幅に変わるので、適宜関数を用意してみてほしい。

解説:死亡率

0309: /**
0310:  * 死亡率の推計関数:推計開始年から一定
0311:  * @param array $items 推計表
0312:  * @return なし
0313: */
0314: function calcDeathRatio1(&$items) {
0315:     global $MaxAge;
0316: 
0317:     for ($i = 1; $i < PERIOD$i++) {
0318:         $year = YEAR_START + $i;
0319:         for ($age = 0; $age <= $MaxAge$age++) {
0320:             $items[$year][$age]['death_male'] = $items[$year - 1][$age]['death_male'];
0321:             $items[$year][$age]['death_female'] = $items[$year - 1][$age]['death_female'];
0322:         }
0323:     }
0324: }

0326: /**
0327:  * 死亡率の推計関数:推計開始年から毎年4‰ずつ減少
0328:  * @param array $items 推計表
0329:  * @return なし
0330: */
0331: function calcDeathRatio2(&$items) {
0332:     global $MaxAge;
0333: 
0334:     $d = (-0.004); //毎年増分
0335:     for ($i = 1; $i < PERIOD$i++) {
0336:         $year = YEAR_START + $i;
0337:         for ($age = 0; $age <= $MaxAge$age++) {
0338:             $items[$year][$age]['death_male'] = $items[$year - 1][$age]['death_male'] * (1 + $d);
0339:             $items[$year][$age]['death_female'] = $items[$year - 1][$age]['death_female'] * (1 + $d);
0340:         }
0341:     }
0342: }

0344: /**
0345:  * 死亡率の推計関数:推計開始年から毎年4‰ずつ減少
0346:  * @param array $items 推計表
0347:  * @return なし
0348: */
0349: function calcDeathRatio3(&$items) {
0350:     global $MaxAge;
0351: 
0352:     $d = (+0.004); //毎年増分
0353:     for ($i = 1; $i < PERIOD$i++) {
0354:         $year = YEAR_START + $i;
0355:         for ($age = 0; $age <= $MaxAge$age++) {
0356:             $items[$year][$age]['death_male'] = $items[$year - 1][$age]['death_male'] * (1 + $d);
0357:             $items[$year][$age]['death_female'] = $items[$year - 1][$age]['death_female'] * (1 + $d);
0358:         }
0359:     }
0360: }

シミュレーションでは、死亡率の推移を幾つか選択できるようになっている。死亡率を推計表 $items に返す関数を用意し、グローバル変数 $SelectOption2 に設定してやれば選択できるようになる。

死亡率の変動によって人口推計結果が大幅に変わるので、適宜関数を用意してみてほしい。

解説:事業所数

0362: /**
0363:  * 事業所数の推計関数:推計開始年から生産年齢人口に応じて変化
0364:  * @param array $items 推計表
0365:  * @return なし
0366: */
0367: function calcCompany(&$items) {
0368:     global $tableCompany;
0369: 
0370:     //初年度の生産年齢人口
0371:     $worker0 = 0;
0372:     for ($age = WORKER_AGE_MIN$age <= WORKER_AGE_MAX$age++) {
0373:         $worker0 += $items[YEAR_START][$age]['male'] + $items[YEAR_START][$age]['female'];
0374:     }
0375: 
0376:     //推計
0377:     for ($i = 0; $i < PERIOD$i++) {
0378:         $year = YEAR_START + $i;
0379:         $worker = 0;
0380:         for ($age = WORKER_AGE_MIN$age <= WORKER_AGE_MAX$age++) {
0381:             $worker += $items[$year][$age]['male'] + $items[$year][$age]['female'];
0382:         }
0383:         foreach ($tableCompany as $key=>$arr) {
0384:             $items[$year]['company'][$key] = $arr['num'] * ($worker / $worker0);
0385:         }
0386:     }
0387: }

事業所数は、先に計算した生産年齢人口に比例して、 $tableCompany が減少していくという単純な推計式とした。

解説:人口推計

0389: /**
0390:  * 人口推計+事業所数推計
0391:  * @param string $opt1 オプション1(出生率の推計関数名)
0392:  * @param string $opt2 オプション2(死亡率の推計関数名)
0393:  * @param string $opt3 オプション3(事業所数の推計関数名)
0394:  * @return array 人口推計結果/FALSE:データファイルがないなど
0395: */
0396: function calcPopulation($opt1$opt2$opt3) {
0397:     global $MaxAge;
0398: 
0399:     $items = array();
0400: 
0401:     //元となるデータファイルを読み込む
0402:     $infp = fopen(FILE_DATA, 'r');
0403:     if ($infp == FALSE)     return FALSE;
0404:     fgetcsv($infp, 9999, ',');      //ラベル行をスキップ
0405:     while (! feof($infp)) {
0406:         $arr = fgetcsv($infp, 9999, ',');
0407:         if ($arr == FALSE)  break;
0408:         if (! is_numeric($arr[1]))   continue;
0409:         $age = $arr[0];
0410:         $items[YEAR_START][$age]['death_male'] = $arr[1] / 1000;   //年齢別死亡率(男性)
0411:         $items[YEAR_START][$age]['death_female'] = $arr[2] / 1000;   //年齢別死亡率(女性)
0412:         $items[YEAR_START][$age]['fertility'] = $arr[3];  //年齢別出生率
0413:         $items[YEAR_START][$age]['male']   = $arr[4] / 10;   //男性人口(単位:万人)
0414:         $items[YEAR_START][$age]['female'] = $arr[5] / 10; //女性人口(単位:万人)
0415:     }
0416:     fclose($infp);
0417:     $MaxAge = $age;      //最高齢
0418:     $opt1($items);       //出生率の推計
0419:     $opt2($items);       //死亡率の推計
0420: 
0421:     //人口推計
0422:     for ($i = 1; $i < PERIOD$i++) {
0423:         $year = YEAR_START + $i;
0424: 
0425:         //0歳
0426:         $items[$year][0]['male'] = 0;
0427:         $items[$year][0]['female'] = 0;
0428:         for ($age = 0; $age <= $MaxAge$age++) {
0429:             $n = $items[$year - 1][$age]['female'] * $items[$year - 1][$age]['fertility'];            //出生数
0430:             $items[$year][0]['male']   += ($n / 2);
0431:             $items[$year][0]['female'] += ($n / 2);
0432:         }
0433: 
0434:         //1歳~$MaxAge歳
0435:         for ($age = 1; $age <= $MaxAge$age++) {
0436:             $items[$year][$age]['male'] = $items[$year - 1][$age - 1]['male'] * (1 - $items[$year][$age]['death_male']);
0437:             $items[$year][$age]['female'] = $items[$year - 1][$age - 1]['female'] * (1 - $items[$year][$age]['death_female']);
0438:         }
0439:     }
0440:     $opt3($items);       //事業所数の推計
0441: 
0442:     return $items;
0443: }

ユーザー関数 calcPopulation で人口推計を行い、結果を配列 $items に代入している。後続の関数は、この配列を表やグラフで出力しているだけである。

まず、冒頭で紹介した初期値データ・ファイル FILE_DATA を読み込む。そして、選択された関数により出生率と死亡率を計算し、推計表 $items に代入する。
次に、このデータを元に、毎年の年齢別人口を計算していく。
0 歳人口は、年齢毎に前年の女性人口と出生率を乗算し、男女半数ずつに分けて代入する。
1 歳以降の人口は、年齢毎に前年の男女別人口と男女別死亡率を乗算し、代入する。

考察

出生率が一定で、死亡率が毎年 4‰減少(平均寿命が伸びる)する場合が、冒頭で紹介した国立社会保障・人口問題研究所の 4 割という値に近くなる。
ただ、国立社会保障・人口問題研究の推計では 50 年後の男性の平均寿命が 84 歳(現在 79 歳)、女性が 91 歳(現在 86 歳)となっており、いくらなんでも長生きし過ぎなのではないかと感じる。
そこで本プログラムでは、死亡率が毎年 4‰増加(平均寿命が縮む)というオプションを用意してみた。この場合、50~100 年後には高齢者比率が減少する。
本プログラムでは各年齢の死亡率が一律に減少/増加するような関数しか用意していないが、高齢者ほど死亡率が高くなるようにすると、高齢者比率の減少は早く訪れる。

出生率については、当たり前のことだが、いま急に増やすことができたとしても、その効果が現れるのは数十年後になる。死亡率や出生率を多少変化させたところで、40~50 年後に高齢者割合が極大になる事態は避けられない。
むしろ出生率を急に増やすと、一時的に生産年齢人口が低下するため、現役世代への負担が重くなるという事態に陥る。
日本の人口推計
生産年齢人口比率は、すべてのシナリオで 2050 年から回復を見せるが、総人口が減少しているから、事業所数は減少し続ける。出生率が 1.8 なければ、急速に減少するから、わが国の将来の経済へのダメージが大きくなると推測できる。

余談

2012 年 2 月現在、社会保障と税の一体改革が国会の主な議題になっている。年金財政の試算を示すかどうかで、政府と野党の間で駆け引きが行われているが、この推計を元に、自力で年金財政や医療保険財政のシミュレーションを行うのも面白いだろう。
年金財政は、基礎年金勘定、国民年金勘定、厚生年金勘定に加え、各共済組合などの帳簿があるので、計算はかなり複雑になる。基礎数値は「厚生労働省年金局 年金財政ホームページ」が参考になる。

簡単に試算したところでは、団塊ジュニアが 65 歳以上になる 25 年後から財政が急激に悪化することが確認できた。
ただ、このまま婚姻率が上がらないと、3 号被保険者の数がそれほど増えない一方、出生率も極端に低下するだろうから、推計のブレ幅はかなり大きいと言える。

参考書籍

表紙 日本の中小企業
著者 関 満博
出版社 中央公論新社
サイズ 新書
発売日 2017年12月21日頃
価格 880円(税込)
rakuten
ISBN 9784121024688
高度経済成長を支え、高い技術力を賞賛された日本の中小企業。だが、近年は急激な人口減少や中国・アジアとの競争などで、苦しい状況にある。既存の企業は後継者不足に悩み、起業の件数も激減している。一九八六年に約八七万あった製造業事業所は、この三〇年のうちにほぼ半減した。こうした状況に突破口はあるのかー。現場主義を貫く経営学者が、豊富な事例を通して、課題と今後の展望を論じる。
 

参考サイト

(この項おわり)
header