JavaScriptで分布関数と密度関数のグラフを描画する方法
はじめに
本ページでは、JavaScriptを使用して以下の確率分布について分布関数(CDF)と密度関数(PDF)を計算する方法を説明します。
- 正規分布
- t分布
- カイ二乗分布
- F分布
さらに、それらの関数をグラフ化する方法についても解説し、実用的なコード例を提供します。
正規分布の分布関数と密度関数
正規分布は連続分布の中で最もよく使われる分布で、平均 μ と分散 σ2 によって定義されます。
密度関数(PDF)の定義
function normalPDF(x, mu = 0, sigma = 1) {
const coeff = 1 / (Math.sqrt(2 * Math.PI) * sigma);
const exponent = -Math.pow(x - mu, 2) / (2 * Math.pow(sigma, 2));
return coeff * Math.exp(exponent);
}
分布関数(CDF)の近似
function normalCDF(x, mu = 0, sigma = 1) {
const z = (x - mu) / (Math.sqrt(2) * sigma);
const t = 1 / (1 + 0.3275911 * Math.abs(z));
const erf = 1 - (((((1.061405429 * t - 1.453152027) * t) + 1.421413741) * t - 0.284496736) * t + 0.254829592) * t * Math.exp(-z * z);
return z >= 0 ? (1 + erf) / 2 : (1 - erf) / 2;
}
例:正規分布のグラフを描画
以下は、正規分布のPDFを描画する例です。
const data = Array.from({ length: 100 }, (_, i) => -5 + i * 0.1);
const pdfValues = data.map(x => normalPDF(x));
console.log(pdfValues);
t分布の分布関数と密度関数
t分布は、母分散が未知の場合のサンプル平均の分布として重要です。
密度関数(PDF)の定義
function tPDF(x, v) {
const gamma = n => (n === 1) ? 1 : (n - 1) * gamma(n - 1);
const coeff = gamma((v + 1) / 2) / (Math.sqrt(v * Math.PI) * gamma(v / 2));
return coeff * Math.pow(1 + (x * x) / v, -(v + 1) / 2);
}
例:t分布のPDFを描画
const data = Array.from({ length: 100 }, (_, i) => -5 + i * 0.1);
const pdfValues = data.map(x => tPDF(x, 10)); // 自由度10
console.log(pdfValues);
カイ二乗分布の分布関数と密度関数
カイ二乗分布は、分散分析や適合度検定で使用される重要な分布です。
密度関数(PDF)の定義
function chiSquarePDF(x, k) {
if (x < 0) return 0;
const gamma = n => (n === 1) ? 1 : (n - 1) * gamma(n - 1);
const coeff = 1 / (Math.pow(2, k / 2) * gamma(k / 2));
return coeff * Math.pow(x, k / 2 - 1) * Math.exp(-x / 2);
}
F分布の分布関数と密度関数
F分布は、分散分析で使用される分布です。
密度関数(PDF)の定義
function fPDF(x, d1, d2) {
const gamma = n => (n === 1) ? 1 : (n - 1) * gamma(n - 1);
const numerator = gamma((d1 + d2) / 2) * Math.pow(d1 / d2, d1 / 2) * Math.pow(x, d1 / 2 - 1);
const denominator = gamma(d1 / 2) * gamma(d2 / 2) * Math.pow(1 + (d1 * x) / d2, (d1 + d2) / 2);
return numerator / denominator;
}
グラフ描画の実装方法
JavaScriptでグラフを描画するには、Chart.js や Plotly といったライブラリを使用すると便利です。
まとめ
本記事では、JavaScriptを使用して正規分布、t分布、カイ二乗分布、F分布の分布関数と密度関数を計算し、さらにグラフ化する方法を説明しました。これらの手法を活用すれば、統計的解析をWebアプリケーションに取り込むことが可能です。
正規分布の数式と実装
正規分布の確率密度関数(PDF)は以下の数式で定義されます:
\[ f(x; \mu, \sigma) = \frac{1}{\sqrt{2 \pi} \sigma} \exp\left(-\frac{(x – \mu)^2}{2 \sigma^2}\right) \]
ここで:
- \( \mu \) は平均
- \( \sigma \) は標準偏差
- \( x \) は確率変数
この数式をJavaScriptで実装すると以下のようになります:
function normalPDF(x, mu = 0, sigma = 1) {
const coeff = 1 / (Math.sqrt(2 * Math.PI) * sigma);
const exponent = -Math.pow(x - mu, 2) / (2 * Math.pow(sigma, 2));
return coeff * Math.exp(exponent);
}
プログラム内では、\(\sqrt{2 \pi} \sigma\) の計算を Math.sqrt(2 * Math.PI) * sigma
として実現し、指数関数部分 \(\exp\left(-\frac{(x – \mu)^2}{2 \sigma^2}\right)\) を Math.exp()
関数で実装しています。
t分布の数式と実装
t分布の確率密度関数(PDF)は以下の数式で定義されます:
\[ f(x; v) = \frac{\Gamma\left(\frac{v+1}{2}\right)}{\sqrt{v \pi} \Gamma\left(\frac{v}{2}\right)} \left(1 + \frac{x^2}{v}\right)^{-\frac{v+1}{2}} \]
ここで:
- \( v \) は自由度
- \( \Gamma \) はガンマ関数
この数式をJavaScriptで実装すると以下のようになります:
function tPDF(x, v) {
const gamma = n => (n === 1) ? 1 : (n - 1) * gamma(n - 1); // 簡易ガンマ関数
const coeff = gamma((v + 1) / 2) / (Math.sqrt(v * Math.PI) * gamma(v / 2));
return coeff * Math.pow(1 + (x * x) / v, -(v + 1) / 2);
}
プログラム内では、ガンマ関数 \(\Gamma\) を再帰的に計算しています。また、\(\left(1 + \frac{x^2}{v}\right)^{-\frac{v+1}{2}}\) の計算を Math.pow()
関数で表現しています。
カイ二乗分布の数式と実装
カイ二乗分布の確率密度関数(PDF)は以下の数式で定義されます:
\[ f(x; k) = \frac{1}{2^{k/2} \Gamma(k/2)} x^{k/2 – 1} e^{-x/2} \quad (x \geq 0) \]
ここで:
- \( k \) は自由度
- \( \Gamma \) はガンマ関数
この数式をJavaScriptで実装すると以下のようになります:
function chiSquarePDF(x, k) {
if (x < 0) return 0;
const gamma = n => (n === 1) ? 1 : (n - 1) * gamma(n - 1); // 簡易ガンマ関数
const coeff = 1 / (Math.pow(2, k / 2) * gamma(k / 2));
return coeff * Math.pow(x, k / 2 - 1) * Math.exp(-x / 2);
}
プログラム内では、\( x^{k/2 – 1} e^{-x/2} \) をそれぞれ Math.pow()
と Math.exp()
で計算し、負の \( x \) に対しては 0 を返すように条件分岐を加えています。
F分布の数式と実装
F分布の確率密度関数(PDF)は以下の数式で定義されます:
\[ f(x; d_1, d_2) = \frac{\Gamma\left(\frac{d_1 + d_2}{2}\right)}{\Gamma\left(\frac{d_1}{2}\right) \Gamma\left(\frac{d_2}{2}\right)} \left(\frac{d_1}{d_2}\right)^{d_1/2} x^{d_1/2 – 1} \left(1 + \frac{d_1}{d_2} x\right)^{-(d_1 + d_2)/2} \]
ここで:
- \( d_1 \), \( d_2 \) は自由度
この数式をJavaScriptで実装すると以下のようになります:
function fPDF(x, d1, d2) {
const gamma = n => (n === 1) ? 1 : (n - 1) * gamma(n - 1); // 簡易ガンマ関数
const numerator = gamma((d1 + d2) / 2) * Math.pow(d1 / d2, d1 / 2) * Math.pow(x, d1 / 2 - 1);
const denominator = gamma(d1 / 2) * gamma(d2 / 2) * Math.pow(1 + (d1 * x) / d2, (d1 + d2) / 2);
return numerator / denominator;
}