グラフの一方の軸が対数スケールになっているグラフを「片対数グラフ (semilog graph)」といいます。極端に範囲の広いデータを扱うことができます。Chart.js でも片対数グラフを描画することができます。
リスト : 片対数グラフ <div style="width:600px; background-color: white"> <canvas id="mychart0"></canvas> </div> <script> const ctx0 = document.getElementById('mychart0'); new Chart(ctx0, { type: 'line', data: { labels: [0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4], datasets: [{ label: 'y = 10 ** x', data: [1, 3.162278, 10, 31.62278, 100, 316.2278, 1000, 3162.278, 10000], }] }, options: { scales: { y: { type: 'logarithmic' } } } }); </script>
積み上げ棒グラフとは同じ項目内のデータを上に積み上げたグラフのことです。次の表を見てください。
: 2010 2015 2020 2025 ---+--------------------- A : 10 15 20 25 B : 20 15 15 10 C : 10 15 15 20
たとえば、ある会社の主力商品 A, B, C の売上高だとしましょう。これを棒グラフで表すと次のようになります。
リスト : 棒グラフ <div style="width:600px; background-color: white"> <canvas id="mychart1"></canvas> </div> <script> const ctx1 = document.getElementById('mychart1'); new Chart(ctx1, { type: 'bar', data: { labels: ['2010', '2015', '2020', '2025'], datasets: [ { label: '# A', data: [10, 15, 20, 25], }, { label: '# B', data: [20, 15, 15, 10], }, { label: '# C', data: [10, 15, 15, 20], }] }, options: { } }); </script>
単純な棒グラフの場合、個々の商品の売上高の推移はわかりますが、A, B, C の合計値は明確ではありません。これを積み上げ棒グラフで表すと、次のようになります。
合計値でみると、売上高は右肩上がりであることが一目でわかります。
リスト : 積み上げ棒グラフ <div style="width:600px; background-color: white"> <canvas id="mychart2"></canvas> </div> <script> const ctx2 = document.getElementById('mychart2'); new Chart(ctx2, { type: 'bar', data: { labels: ['2010', '2015', '2020', '2025'], datasets: [ { label: '# A', data: [10, 15, 20, 25], }, { label: '# B', data: [20, 15, 15, 10], }, { label: '# C', data: [10, 15, 15, 20], }] }, options: { scales: { x: {stacked: true}, y: {stacked: true} } } }); </script>
棒グラフ (bar chart) において、options のプロパティ indexAxis に 'y' をセットすると、棒グラフが水平方向に描画されます。
リスト : 横棒グラフ (1) <div style="width:600px; background-color: white"> <canvas id="mychart8"></canvas> </div> <script> const ctx8 = document.getElementById('mychart8'); new Chart(ctx8, { type: 'bar', data: { labels: ['130-135', '135-140', '140-145', '145-150', '150-155', '155-160', '160-165', '165-170'], datasets: [{ label: '# 度数', data: [1, 6, 12, 25, 32, 17, 6, 1], borderWidth: 1, categoryPercentage: 0.9 }] }, options: { indexAxis: 'y', scales: { x: { beginAtZero: true }, } } }); </script>
y 軸にプロパティ reverse: true をセットすると、ラベルの順番を反転させることができます。
リスト : 横棒グラフ (2) <div style="width:600px; background-color: white"> <canvas id="mychart9"></canvas> </div> <script> const ctx9 = document.getElementById('mychart9'); new Chart(ctx9, { type: 'bar', data: { labels: ['130-135', '135-140', '140-145', '145-150', '150-155', '155-160', '160-165', '165-170'], datasets: [{ label: '# 度数', data: [1, 6, 12, 25, 32, 17, 6, 1], borderWidth: 1, categoryPercentage: 0.9 }] }, options: { indexAxis: 'y', scales: { x: { beginAtZero: true }, y: { reverse: true, }, } } }); </script>
同様に、indexAxis: 'y' を指定すると、積み上げ棒グラフも水平方向に描画することができます。
リスト : 横棒グラフ (3) <div style="width:600px; background-color: white"> <canvas id="mychart10"></canvas> </div> <script> const ctx10 = document.getElementById('mychart10'); new Chart(ctx10, { type: 'bar', data: { labels: ['2010', '2015', '2020', '2025'], datasets: [ { label: '# A', data: [10, 15, 20, 25], }, { label: '# B', data: [20, 15, 15, 10], }, { label: '# C', data: [10, 15, 15, 20], }] }, options: { indexAxis: 'y', scales: { x: { stacked: true, beginAtZero: true }, y: {stacked: true} } } }); </script>
2 つのグラフを描画するとき、それらの値が大きく異なると、同一スケールではわかりにくくなります。この場合、左側の y 軸だけではなく、右側の y 軸にもスケールを設定すると便利です。たとえば、2024 年度東京都月別平均気温と降水量 を折れ線グラフで表してみましょう。
リスト : 複数軸 <div style="width:600px; background-color: white"> <canvas id="mychart11"></canvas> </div> <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js"></script> <script> const ctx11 = document.getElementById('mychart11'); new Chart(ctx11, { type: 'line', data: { labels: ['2024-01', '2024-02', '2024-03', '2024-04', '2024-05', '2024-06', '2024-07', '2024-08', '2024-09', '2024-10', '2024-11', '2024-12'], datasets: [ { label: '降水量', data: [36, 78.5, 188.5, 115.5, 201.5, 350.0, 206.5, 381.0, 111.5, 174.5, 82.0, 0.5] }, { label: '平均気温', data: [7.1, 8.0, 9.6, 17.1, 20.0, 23.1, 28.7, 29.0, 26.6, 20.6, 13.7, 8.1], yAxisID: 'y2', },], }, options: { scales: { x: { type: 'time', time: { unit: 'month' } }, y: { title: { display: true, text: '降水量 (mm)', }, beginAtZero: true }, y2: { title: { display: true, text: '平均気温 (℃)', }, position: 'right', min: 0, max: 40 }, } } }); </script>
次は降水量を棒グラフに変更してみましょう。2 種類以上の異なるチャートを表示するグラフを「複合チャート (Mixed chart)」といいます。
リスト : 複合チャート <div style="width:600px; background-color: white"> <canvas id="mychart12"></canvas> </div> <script> const ctx12 = document.getElementById('mychart12'); new Chart(ctx12, { data: { labels: ['2024-01', '2024-02', '2024-03', '2024-04', '2024-05', '2024-06', '2024-07', '2024-08', '2024-09', '2024-10', '2024-11', '2024-12'], datasets: [ { type: 'bar', label: '降水量', data: [36, 78.5, 188.5, 115.5, 201.5, 350.0, 206.5, 381.0, 111.5, 174.5, 82.0, 0.5] }, { type: 'line', label: '平均気温', data: [7.1, 8.0, 9.6, 17.1, 20.0, 23.1, 28.7, 29.0, 26.6, 20.6, 13.7, 8.1], yAxisID: 'y2', },], }, options: { scales: { x: { type: 'time', time: { unit: 'month' } }, y: { title: { display: true, text: '降水量 (mm)', }, beginAtZero: true }, y2: { title: { display: true, text: '平均気温 (℃)', }, position: 'right', min: 0, max: 40 }, } } }); </script>
折れ線グラフ (line chart) において、プロパティ fill を true に設定すると、x 軸と折れ線グラフの間を塗りつぶします。fill に 'end' を指定すると、折れ線グラフと画面の上端 (end) の間を塗りつぶします。'start' を指定すると画面の下端と折れ線グラフの間を塗りつぶします。
リスト : 折れ線グラフの塗りつぶし <div style="width:600px; background-color: white"> <canvas id="mychart3"></canvas> </div> <script> let xs = []; for (let i = -2; i <= 2; i += 0.25) xs.push(i); const ctx3 = document.getElementById('mychart3'); new Chart(ctx3, { type: 'line', data: { labels: xs, datasets: [{ label: 'y = x**2 - 1', data: xs.map(x => x ** 2 - 1), fill: true }, { label: 'y = x**3 - 4x', data: xs.map(x => x ** 3 - 4*x), fill: 'end' }, { label: 'y = x**4 - 6x**2 + 4', data: xs.map(x => x ** 4 - 6 * x**2 + 4), fill: 'start' }] }, options: { lineTension: 0.4 } }); </script>
リスト : 折れ線グラフの塗りつぶし (2) <div style="width:600px; background-color: white"> <canvas id="mychart4"></canvas> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js"></script> <script> const ctx = document.getElementById('mychart4'); new Chart(ctx4, { type: 'line', data: { labels: xs, datasets: [{ label: 'y = x**2 - 1', data: xs.map(x => x ** 2 - 1), fill: 2 }, { label: 'y = x**3 - 4x', data: xs.map(x => x ** 3 - 4*x), }, { label: 'y = x**4 - 6x**2 + 4', data: xs.map(x => x ** 4 - 6 * x**2 + 4), }] }, options: { lineTension: 0.4 } }); </script>
グラフのタイトルは options.plugins のプロパティ title で指定します。
リスト : タイトル <div style="width:600px; background-color: white"> <canvas id="mychart13"></canvas> </div> <script> const ctx13 = document.getElementById('mychart13'); new Chart(ctx13, { type: 'bar', data: { labels: ['2024-01', '2024-02', '2024-03', '2024-04', '2024-05', '2024-06', '2024-07', '2024-08', '2024-09', '2024-10', '2024-11', '2024-12'], datasets: [ { label: '降水量', data: [36, 78.5, 188.5, 115.5, 201.5, 350.0, 206.5, 381.0, 111.5, 174.5, 82.0, 0.5], }], }, options: { plugins: { title: { display: true, text: '2024 年度東京都降水量', font: { size: 16, } }, }, scales: { x: { type: 'time', time: { unit: 'month' } }, y: { beginAtZero: true, }, } } }); </script>
凡例の詳細は options.plugins のプロパティ legend で指定します。
リスト : 凡例 <div style="width:600px; background-color: white"> <canvas id="mychart14"></canvas> </div> <script> const ctx14 = document.getElementById('mychart14'); new Chart(ctx14, { type: 'bar', data: { labels: ['2024-01', '2024-02', '2024-03', '2024-04', '2024-05', '2024-06', '2024-07', '2024-08', '2024-09', '2024-10', '2024-11', '2024-12'], datasets: [ { label: '降水量', data: [36, 78.5, 188.5, 115.5, 201.5, 350.0, 206.5, 381.0, 111.5, 174.5, 82.0, 0.5], }], }, options: { plugins: { title: { display: true, text: '2024 年度東京都降水量', font: { size: 16, }, position: 'bottom', }, legend: { position: 'bottom', }, }, scales: { x: { type: 'time', time: { unit: 'month' } }, y: { beginAtZero: true, }, } } }); </script>
次の式で表される確率分布を「正規分布」といいます。
これを平均 \(\mu\)、分散 \(\sigma^2\) の正規分布といい、\(N(\mu, \sigma^2)\) と略記します。特に、\(N(0, 1)\) を「標準正規分布」といいます。正規分布は次の図に示すような釣鐘状の曲線 (ベル・カープ) になります。
リスト : 正規分布 (1) <div style="width:600px; background-color: white"> <canvas id="mychart5"></canvas> </div> <script> function norm(x, m, s2) { return (1 / Math.sqrt(2 * Math.PI * s2)) * Math.exp(- ((x - m) ** 2) / (2 * s2)); } let xs1 = []; for (let i = -5; i <= 5; i += 0.25) xs1.push(i); const ctx5 = document.getElementById('mychart5'); new Chart(ctx5, { type: 'line', data: { labels: xs1, datasets: [ { label: 'N(0, 1)', data: xs1.map(x => norm(x, 0, 1)), }, { label: 'N(1, 2)', data: xs1.map(x => norm(x, 1, 2)), }, { label: 'N(-2, 0.5)', data: xs1.map(x => norm(x, -2, 0.5)), }, ] }, options: { radius: 0, lineTension: 0.4 } }); </script>
青線が N(0, 1)、赤線が N(1, 2)、黄線が N(-2. 0.5) です。正規分布は、平均値のデータが一番多く、分散の値が小さいほど平均値にデータが集まるので、ベル・カーブの頂点が高くなります。分散の値が大きくなると、ベル・カーブの頂点は低くなり裾野が広がります。ようするに、分散の値だけで正規分布の形が決まるわけです。
正規分布の場合、\(-\sigma \lt x \lt \sigma\) の確率が 68.26 % で、\(-2\sigma \lt x \lt 2\sigma\) の確率が 95.44 % になります。したがって、下図のように標準正規分布では \(-1 \lt x \lt 1\) の確率が 68.26 % で、\(-2 \lt x \lt 2\) の確率が 95.44 % になります。
リスト : 正規分布 (2) <div style="width:600px; background-color: white"> <canvas id="mychart6"></canvas> </div> <script> const ctx6 = document.getElementById('mychart6'); new Chart(ctx6, { type: 'line', data: { labels: xs1, datasets: [ { label: 'N(0, 1)', data: xs1.map(function(x) { if (x <= -1 || x >= 1) { return norm(x, 0, 1); } else { return null; } }), }, { label: 'N(0, 1)', data: xs1.map(function(x) { if (x >= -1 && x <= 1) { return norm(x, 0, 1); } else { return null; } }), fill: true }, ]}, options: { radius: 0, lineTension: 0.4 } }); </script>
リスト : 正規分布 (3) <div style="width:600px; background-color: white"> <canvas id="mychart7"></canvas> </div> <script> const ctx7 = document.getElementById('mychart7'); new Chart(ctx7, { type: 'line', data: { labels: xs1, datasets: [ { label: 'N(0, 1)', data: xs1.map(function(x) { if (x <= -2 || x >= 2) { return norm(x, 0, 1); } else { return NaN; } }), }, { label: 'N(0, 1)', data: xs1.map(function(x) { if (x >= -2 && x <= 2) { return norm(x, 0, 1); } else { return undefined; } }), fill: true }, ]}, options: { radius: 0, lineTension: 0.4 } }); </script>