[JavaScript] Chart.jsで確率分布のシミュレーション表示 その2

2020年12月14日月曜日

Chart.js JavaScript

その1では、確率分布をシミュレーションするための発生頻度を求める関数を作成した。
今回は二項分布を生成して、Chart.jsでグラフに表示してみよう。

二項分布

前回作成したベルヌーイ分布関数を呼び出して、二項分布の乱数発生関数を作ろう。
// 確率pで1を、確率1-pで0を返す
function bernoulli(p) {
  return Math.random() <= p ? 1 : 0;
}
// 確率pで発生した事象の回数を返す
function binomial(p, n) {
  let m = 0;
  for (i = 0; i < n; i++) {
    m += bernoulli(p);
  }
  return m;
}

Chart.jsの散布図のためにx,y連想配列に変換

連想配列のままでは、Chart.jsの散布図では表示してくれないので、xとyをキーとするオブジェクトの配列に変換するユーティリティ関数を作成しておこう。
function xy_list(list) {
  let freq = [];
  for (const key of Object.keys(list)) {
      freq.push({ x:key, y:list[key] });
  }
  return freq;
}

Chart.jsを使って散布図を表示

Chart.jsを使って、確率0.5と0.2の二項分布を表示すると以下のようになる。

今回の散布図表示スクリプト

最後に、今回の散布図表示スクリプトを掲載。
<canvas id="binomialGraph"></canvas>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.js"></script>

<script type="text/javascript">
function bernoulli(p) {
  return Math.random() <= p ? 1 : 0;
}

function binomial(p, n) {
  let m = 0;
  for (i = 0; i < n; i++) {
    m += bernoulli(p);
  }
  return m;
}

function frequency(list) {
  let freq = [];
  for (const key of list) {
    if (freq[key] === undefined) freq[key] = 0;
    freq[key]++;
  }
  return freq;
}

function gen_random(func, n) {
  return (new Array(n)).fill().map((_, i) => func());
}

function freq10K(func) {
  return frequency(gen_random(func, 10000));
}

function xy_list(list) {
  let freq = [];
  for (const key of Object.keys(list)) {
      freq.push({ x:key, y:list[key] });
  }
  return freq;
}

  // 二項分布グラフ
  let binomialGraph = document.getElementById("binomialGraph");
  let bin_05_10 = xy_list(freq10K(() => binomial(0.5, 10)));
  let bin_02_10 = xy_list(freq10K(() => binomial(0.2, 10)));

  let binomialChart = new Chart(binomialGraph, {
    type: 'scatter', 
    data: { 
      datasets: [
        {
          label: 'bin(0.5, 10)',
          data: bin_05_10,
          backgroundColor: 'RGBA(225,0,0, 1)',
        }, 
        {
          label: 'bin(0.2, 10)',
          data: bin_02_10,
          backgroundColor: 'RGBA(0,225,0, 1)',
        }]
    },
    options:{
      title: {
        display: true,
          text: '二項分布'
      },
      scales: {
        xAxes: [{        
          scaleLabel: {             
            display: true,          
            labelString: '事象発生回数' 
          },
          ticks: {
            suggestedMin: 0,
            suggestedMax: 10,
            stepSize: 1,
            callback: function(value, index, values){
              return  value
            }
          }
        }],
        yAxes: [{        
          scaleLabel: {             
            display: true,          
            labelString: '頻度' 
          },
          ticks: {
            suggestedMax: 4000,
            suggestedMin: 0,
            stepSize: 500,
            callback: function(value, index, values){
              return  value
            }
          }
        }]
      }
    }
  });