お知らせ

ただいま、シンタックスハイライターの設定を見直しております。
プログラムが見にくくなっているページがありますが、ご容赦ください。

帯グラフをプログラムで描いてみたけど大変だった

グラフ

こんにちは。まだまだグラフを描き続けます。

小学5年生で学習するグラフとして、円グラフと帯グラフがあります。

前回は円グラフを描きましたが、今回は帯グラフを描くことにします。

ネットで検索する場合、「帯グラフ」で検索するよりも、「100%積み上げ棒グラフ」と探した方が見つかるような気がします。

Python + matplotlib で描く帯グラフ

まず、プログラムです。

import numpy
import matplotlib.pyplot

data = numpy.array( [ 
    [ 26033218, 82506016, 12468343 ],
    [ 22486239, 85903976, 14894595 ],
    [ 20013730, 87164721, 18260822 ],
    [ 18472499, 86219631, 22005152 ],
    [ 17521234, 84092414, 25672005 ],
    [ 16803444, 81031800, 29245685 ],
    [ 15886810, 76288736, 33465441 ] ] )
year = [ "1985年",  "1990年",  "1995年",  "2000年",  "2005年",  "2010年",  "2015年" ]
labels = [ "15歳未満", "15~64歳", "65歳以上" ]

normalized = data / data.sum( axis=1, keepdims=True )
cumulative = numpy.zeros(7)
tick = numpy.arange(7)

for k in range(3):
    matplotlib.pyplot.bar( tick, normalized[ :, k ], bottom=cumulative, label=labels[k] )
    cumulative += normalized[ :, k ]

matplotlib.pyplot.xticks( tick, year )
matplotlib.pyplot.ylim( ( 0, 1 ) )
matplotlib.pyplot.legend()
matplotlib.pyplot.show()

割合を求めるために合計を求めたり、とゴニョニョしなきゃいけないので、numpyを使ってしまいました。

それでも26行になってしまいました。(データを外部から読み込めば、もう少し短く見えるんですけどね・・・)

グラフです。

Python + matplotlib で描いた帯グラフ

R で描く棒グラフ

次は、Rです。かなり無理やりな感じです・・・

data = c(  
    26033218, 82506016, 12468343,
    22486239, 85903976, 14894595,
    20013730, 87164721, 18260822,
    18472499, 86219631, 22005152,
    17521234, 84092414, 25672005,
    16803444, 81031800, 29245685,
    15886810, 76288736, 33465441 )
m = matrix( data, nrow=3 )
year = c( "1985年",  "1990年",  "1995年",  "2000年",  "2005年",  "2010年",  "2015年" )
labels = c( "15歳未満", "15~64歳", "65歳以上" )
barplot( sweep( m, 2, 100/colSums(m), "*"), names.arg=year, legend=labels, main="人口構成比", ylim=c(0,100))
box(lty=1)
R で描いた帯グラフ

Chart.js で描く帯グラフ

ネットで検索したところ、プラグインを入れているサイトが比較的多く見られました。

プラグインを使わない方法を粘って探したところ、年ごとに総人口を求め、人口比を求めるという方法になりました。元サイトのデータは人口比ではありませんが、参考にしたサイトということでブログカードを貼っておきます。

それでは、参考サイトをもとに作成したプログラムです。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>人口構成比</title>
  </head>
  <body>
    <canvas id="stage"></canvas>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.js"></script>
    <script>
      var population = [];
      population[0] = [ 26033218, 82506016, 12468343 ];
      population[1] = [ 22486239, 85903976, 14894595 ];
      population[2] = [ 20013730, 87164721, 18260822 ];
      population[3] = [ 18472499, 86219631, 22005152 ];
      population[4] = [ 17521234, 84092414, 25672005 ];
      population[5] = [ 16803444, 81031800, 29245685 ];
      population[6] = [ 15886810, 76288736, 33465441 ];

      var total = [];
      for( var i=0; i<7; i++ ){
      	total[i] = 0;
      	for( var j=0; j<3; j++ ){
      	  total[i] += population[i][j];
        }
      }
 
      var ratio =[];
      for( var i=0; i<3; i++ ){
      	ratio[i] = [];
      	for( var j=0; j<7; j++ ){
      		ratio[i][j] = population[j][i] / total[j];
      	}
      }

      var mydata = {
      labels: [ "1985年", "1990年", "1995年", "2000年", "2005年", "2010年", "2015年" ],
      datasets: [
        { label: '15歳未満',
          data: ratio[0],
          backgroundColor: "green",
          hoverBackgroundColor: "lightgreen",
        },
        { label: '15~64歳',
          data: ratio[1],
          backgroundColor: "yellow",
          hoverBackgroundColor: "lightyellow",
        },
        { label: '65歳以上',
          data: ratio[2],
          backgroundColor: "red",
          hoverBackgroundColor: "lightpink",
        },
      ] };

      var options = {
        title: {    
          display: true,
          text: '人口構成比',
        },
        scales: {
            xAxes: [{
                stacked: true  // 積み上げの指定
            }],
            yAxes: [{
                stacked: true  //  積み上げの指定
            }]
        }
      };

      var canvas = document.getElementById('stage');
      var chart = new Chart(canvas, {
        type: 'bar',
        data: mydata,
        options: options
      });
    </script>
    <noscript>JavaScriptが利用できません。</noscript>
  </body>
</html>

上のプログラムで描いたグラフです。

Chart.js で描いた帯グラフ

データを流し込むだけでグラフが描けると思っていただけに、予想以上に大変でした。

比率の比較には円グラフよりはるかにわかりやすいと思うんですけどね・・・

今回はこれでおしまいにします。それでは、また。

この記事を書いた人
春日井 優

高校で情報科という教科を担当しています。以前は数学科も担当していました。(今でも数学科の教員免許状は有効です。)プログラムを覚えたのは、「ゲームセンターあらし」という漫画のキャラクターがBASICを解説する「こんにちはマイコン」を読んだことがきっかけでした。

Posted by kasugai