PHPで人口を推計する

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

サンプル・プログラム

プログラムを実行する

ダウンロード(PHP4/5共用)

サンプル・プログラムの解説:準備

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

population.csvの各列の構造は以下の通り。いずれも 2011 年時点の値である。
  1. 年齢
  2. その年齢における男性の死亡率(千人あたり)
  3. その年齢における女性の死亡率(千人あたり)
  4. その年齢における出生率(女性一人あたり)
  5. その年齢における男性人口(千人)
  6. その年齢における女性人口(千人)


人口と死亡率については日本統計年鑑(総務省統計局)を参考にした。死亡率については 2009 年の値を採用している。ただし 100 歳超の死亡率は分からないので、適当に設定した。
出生率については、日本の将来推計人口の仮定値表(国立社会保障・人口問題研究所)の中位推計で 2010 年の値を採用した。
グラフを描くために JpGraph ライブラリを用いている。JpGraph の入手・設置方法については「PHP と JpGraph で人口ピラミッドを表示する」を参照のこと。

シミュレーションのための初期値は定数で用意している。コメントにしたがって適宜変更して構わない。

0036: //JpGraph(各自の環境に合わせて)
0037: require_once('../../../../common/jpgraph/jpgraph.php');
0038: require_once('../../../../common/jpgraph/jpgraph_bar.php');
0039: require_once('../../../../common/jpgraph/jpgraph_line.php');
0040: 
0041: //グラフの幅・高さ(デフォルト値)
0042: define('WIDTH', 600);
0043: define('HEIGHT', 400);
0044: 
0045: //推計開始年(元データの年次)
0046: define('YEAR_START', 2011);
0047: 
0048: //推計期間(年)
0049: define('PERIOD', 100);
0050: 
0051: //生産年齢
0052: define('WORKER_AGE_MIN', 15);     //下限年齢
0053: define('WORKER_AGE_MAX', 64);     //上限年齢

サンプル・プログラムの解説:出生率

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

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

0123: /**
0124:  * オプション1(出生率)選択肢
0125:  * @global array $SelectOption1
0126: */
0127: $SelectOption1 = array(
0128:     //関数名               タイトル             ラジオボタンcheked
0129:     'calcFertilityRatio1' => array('title'=>'一定', 'checked'=>'checked'),
0130:     'calcFertilityRatio2' => array('title'=>'毎年1%ずつ減少,0.9で一定', 'checked'=>''),
0131:     'calcFertilityRatio3' => array('title'=>'毎年1%ずつ増加,1.8で一定', 'checked'=>''),
0132:     'calcFertilityRatio4' => array('title'=>'0.9と1.8の間で増減', 'checked'=>'')
0133: );
0134: 
0135: /**
0136:  * 出生率の推計関数:推計開始年から一定
0137:  * @param array $items 推計表
0138:  * @return なし
0139: */
0140: function calcFertilityRatio1(&$items) {
0141:     global $MaxAge;
0142: 
0143:     for ($i = 1; $i < PERIOD; $i++) {
0144:         $year = YEAR_START + $i;
0145:         for ($age = 0; $age <= $MaxAge$age++) {
0146:             $items[$year][$age]['fertility'] = $items[$year - 1][$age]['fertility'];
0147:         }
0148:     }
0149: }
0150: 
0151: /**
0152:  * 出生率の推計関数:毎年1%ずつ減少,0.9で一定
0153:  * @param array $items 推計表
0154:  * @return なし
0155: */
0156: function calcFertilityRatio2(&$items) {
0157:     global $MaxAge;
0158: 
0159:     $d = (-0.01);  //毎年増分
0160:     $t2 = 0.9;        //下限値
0161:     for ($i = 1; $i < PERIOD; $i++) {
0162:         $year = YEAR_START + $i;
0163:         $total = 0;
0164:         for ($age = 0; $age <= $MaxAge$age++) {
0165:             $items[$year][$age]['fertility'] = $items[$year - 1][$age]['fertility'] * (1 + $d);
0166:             $total += $items[$year][$age]['fertility'];
0167:         }
0168:         if ($total <= $t2)  $d = 0;
0169:     }
0170: }
0171: 
0172: /**
0173:  * 出生率の推計関数:毎年1%ずつ増加,1.8で一定
0174:  * @param array $items 推計表
0175:  * @return なし
0176: */
0177: function calcFertilityRatio3(&$items) {
0178:     global $MaxAge;
0179: 
0180:     $d  = 0.01;       //毎年増分
0181:     $t1 = 1.8;        //上限値
0182:     for ($i = 1; $i < PERIOD; $i++) {
0183:         $year = YEAR_START + $i;
0184:         $total = 0;
0185:         for ($age = 0; $age <= $MaxAge$age++) {
0186:             $items[$year][$age]['fertility'] = $items[$year - 1][$age]['fertility'] * (1 + $d);
0187:             $total += $items[$year][$age]['fertility'];
0188:         }
0189:         if ($total >= $t1)  $d = 0;
0190:     }
0191: }
0192: 
0193: /**
0194:  * 出生率の推計関数:0.9と1.8の間で増減
0195:  * @param array $items 推計表
0196:  * @return なし
0197: */
0198: function calcFertilityRatio4(&$items) {
0199:     global $MaxAge;
0200: 
0201:     $sign = (-1); //増減符号
0202:     $d  = 0.01;       //毎年増分
0203:     $t1 = 1.8;        //上限値
0204:     $t2 = 0.9;        //下限値
0205:     for ($i = 1; $i < PERIOD; $i++) {
0206:         $year = YEAR_START + $i;
0207:         $total = 0;
0208:         for ($age = 0; $age <= $MaxAge$age++) {
0209:             $items[$year][$age]['fertility'] = $items[$year - 1][$age]['fertility'] * (1 + $d * $sign);
0210:             $total += $items[$year][$age]['fertility'];
0211:         }
0212:         if ($total >= $t1)  $sign = (-1);
0213:         if ($total <= $t2)  $sign = (+1);
0214:     }
0215: }

サンプル・プログラムの解説:死亡率

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

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

0217: /**
0218:  * オプション2(死亡率)選択肢
0219:  * @global array $SelectOption1
0220: */
0221: $SelectOption2 = array(
0222:     //関数名               タイトル             ラジオボタンcheked
0223:     'calcDeathRatio1' => array('title'=>'一定', 'checked'=>'checked'),
0224:     'calcDeathRatio2' => array('title'=>'毎年4‰ずつ減少', 'checked'=>''),
0225:     'calcDeathRatio3' => array('title'=>'毎年4‰ずつ増加', 'checked'=>'')
0226: );
0227: 
0228: /**
0229:  * 死亡率の推計関数:推計開始年から一定
0230:  * @param array $items 推計表
0231:  * @return なし
0232: */
0233: function calcDeathRatio1(&$items) {
0234:     global $MaxAge;
0235: 
0236:     for ($i = 1; $i < PERIOD; $i++) {
0237:         $year = YEAR_START + $i;
0238:         for ($age = 0; $age <= $MaxAge$age++) {
0239:             $items[$year][$age]['death_male'] = $items[$year - 1][$age]['death_male'];
0240:             $items[$year][$age]['death_female'] = $items[$year - 1][$age]['death_female'];
0241:         }
0242:     }
0243: }
0244: 
0245: /**
0246:  * 死亡率の推計関数:推計開始年から毎年4‰ずつ減少
0247:  * @param array $items 推計表
0248:  * @return なし
0249: */
0250: function calcDeathRatio2(&$items) {
0251:     global $MaxAge;
0252: 
0253:     $d = (-0.004); //毎年増分
0254:     for ($i = 1; $i < PERIOD; $i++) {
0255:         $year = YEAR_START + $i;
0256:         for ($age = 0; $age <= $MaxAge$age++) {
0257:             $items[$year][$age]['death_male'] = $items[$year - 1][$age]['death_male'] * (1 + $d);
0258:             $items[$year][$age]['death_female'] = $items[$year - 1][$age]['death_female'] * (1 + $d);
0259:         }
0260:     }
0261: }
0262: 
0263: /**
0264:  * 死亡率の推計関数:推計開始年から毎年4‰ずつ減少
0265:  * @param array $items 推計表
0266:  * @return なし
0267: */
0268: function calcDeathRatio3(&$items) {
0269:     global $MaxAge;
0270: 
0271:     $d = (+0.004); //毎年増分
0272:     for ($i = 1; $i < PERIOD; $i++) {
0273:         $year = YEAR_START + $i;
0274:         for ($age = 0; $age <= $MaxAge$age++) {
0275:             $items[$year][$age]['death_male'] = $items[$year - 1][$age]['death_male'] * (1 + $d);
0276:             $items[$year][$age]['death_female'] = $items[$year - 1][$age]['death_female'] * (1 + $d);
0277:         }
0278:     }
0279: }

サンプル・プログラムの解説:人口推計

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

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

0281: /**
0282:  * 人口推計
0283:  * @param string $opt1 オプション1(出生率の推計関数名)
0284:  * @param string $opt1 オプション2(死亡率の推計関数名)
0285:  * @return array 人口推計結果/FALSE:データファイルがないなど
0286: */
0287: function calcPopulation($opt1$opt2) {
0288:     global $MaxAge;
0289: 
0290:     $items = array();
0291: 
0292:     //元となるデータファイルを読み込む
0293:     $infp = fopen(FILE_DATA, 'r');
0294:     if ($infp == FALSE)     return FALSE;
0295:     while (!feof($infp)) {
0296:         $arr = fgetcsv($infp, 9999, ',');
0297:         if (! is_numeric($arr[0]))   continue;
0298:         $age = $arr[0];
0299:         $items[YEAR_START][$age]['death_male'] = $arr[1] / 1000;   //年齢別死亡率(男性)
0300:         $items[YEAR_START][$age]['death_female'] = $arr[2] / 1000;   //年齢別死亡率(女性)
0301:         $items[YEAR_START][$age]['fertility'] = $arr[3];  //年齢別出生率
0302:         $items[YEAR_START][$age]['male']   = $arr[4] / 10;   //男性人口(単位:万人)
0303:         $items[YEAR_START][$age]['female'] = $arr[5] / 10; //女性人口(単位:万人)
0304:     }
0305:     fclose($infp);
0306:     $MaxAge = $age;      //最高齢
0307:     $opt1($items);       //出生率の推計
0308:     $opt2($items);       //死亡率の推計
0309: 
0310:     //人口推計
0311:     for ($i = 1; $i < PERIOD; $i++) {
0312:         $year = YEAR_START + $i;
0313: 
0314:         //0歳
0315:         $items[$year][0]['male'] = 0;
0316:         $items[$year][0]['female'] = 0;
0317:         for ($age = 0; $age <= $MaxAge$age++) {
0318:             $n = $items[$year - 1][$age]['female'] * $items[$year - 1][$age]['fertility'];
0319:             $items[$year][0]['male']   += ($n / 2);
0320:             $items[$year][0]['female'] += ($n / 2);
0321:         }
0322: 
0323:         //1歳〜$MaxAge歳
0324:         for ($age = 1; $age <= $MaxAge$age++) {
0325:             $items[$year][$age]['male'] = $items[$year - 1][$age - 1]['male'] * (1 - $items[$year][$age]['death_male']);
0326:             $items[$year][$age]['female'] = $items[$year - 1][$age - 1]['female'] * (1 - $items[$year][$age]['death_female']);
0327:         }
0328:     }
0329:     return $items;
0330: }

考察

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

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

余談

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

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

参考サイト

(この項おわり)
header