- テーマの整理:「統計情報生成」とは何か
- 基本コンセプト:「平均だけでは見えない“バラつき”や“偏り”を数値化する」
- ユーティリティ 1:基本統計情報(平均・分散・標準偏差・中央値)
- 例題 1:安定している配列とバラついている配列を比べる
- ユーティリティ 2:オブジェクト配列から「特定フィールドの統計情報」を作る
- ユーティリティ 3:パーセンタイル(上位何%のラインか)を計算する
- ユーティリティ 4:統計情報生成を「業務サマリー」に組み込む
- 統計情報生成ユーティリティで意識してほしい重要ポイント
- 手を動かして「統計情報生成」の感覚をつかむ
- まとめ:統計情報生成ユーティリティで「配列の性格を、数字で語れるようにする」
テーマの整理:「統計情報生成」とは何か
ここでの「統計情報生成」は、配列に入っている数値データから、もう一歩踏み込んだ“統計的な指標”を計算するユーティリティのことです。 サマリー生成が「合計・平均・最大・最小」だとしたら、統計情報生成はそこからさらに、
分散・標準偏差(どれくらいバラついているか) 中央値(極端な値に引っ張られない代表値) パーセンタイル(上位何%のラインか)
などを計算して、「データの性格」をより深く理解するための道具です。
業務では、例えば「売上の安定度」「工数のバラつき」「レスポンス時間の偏り」などを知りたいときに使います。
基本コンセプト:「平均だけでは見えない“バラつき”や“偏り”を数値化する」
なぜ統計情報が必要なのか
平均だけを見ると、こんな落とし穴があります。
売上が「100, 100, 100, 100, 100」でも平均は 100。 売上が「0, 0, 0, 0, 500」でも平均は 100。
でも、前者は「安定している」、後者は「ほぼゼロで、たまにドカン」ですよね。 この違いを表現してくれるのが、分散・標準偏差・中央値などの統計情報です。
統計情報生成ユーティリティは、 「配列の中身が、安定しているのか、バラついているのか、偏っているのか」を数値で教えてくれる」役割を持ちます。
ユーティリティ 1:基本統計情報(平均・分散・標準偏差・中央値)
実装:basicStats
まずは、数値配列に対して「基本的な統計情報」をまとめて計算するユーティリティです。
function basicStats(values) {
if (!Array.isArray(values) || values.length === 0) {
return {
count: 0,
mean: 0,
variance: 0,
stddev: 0,
median: null,
};
}
const nums = values.filter(
(v) => typeof v === "number" && !Number.isNaN(v)
);
const count = nums.length;
if (count === 0) {
return {
count: 0,
mean: 0,
variance: 0,
stddev: 0,
median: null,
};
}
const sum = nums.reduce((acc, v) => acc + v, 0);
const mean = sum / count;
const sqDiffSum = nums.reduce((acc, v) => {
const diff = v - mean;
return acc + diff * diff;
}, 0);
const variance = sqDiffSum / count;
const stddev = Math.sqrt(variance);
const sorted = [...nums].sort((a, b) => a - b);
let median;
if (count % 2 === 1) {
median = sorted[(count - 1) / 2];
} else {
const mid1 = sorted[count / 2 - 1];
const mid2 = sorted[count / 2];
median = (mid1 + mid2) / 2;
}
return {
count,
mean,
variance,
stddev,
median,
};
}
JavaScript重要ポイントをかみ砕いて説明
まず、配列かどうか・空かどうかをチェックし、空なら「全部 0・中央値は null」を返します。 values から「数値だけ」を取り出して nums にします(文字列や NaN は無視)。
mean(平均)は、sum / count で計算します。 variance(分散)は、「各値と平均の差」を二乗して足し合わせ、それを count で割っています。 stddev(標準偏差)は、分散の平方根です。
median(中央値)は、ソートした配列から「真ん中の値」を取ります。 要素数が奇数なら真ん中の 1 つ、偶数なら真ん中 2 つの平均です。
これで、「配列の基本的な統計情報」が一発で手に入ります。
例題 1:安定している配列とバラついている配列を比べる
const stable = [100, 100, 100, 100, 100];
const unstable = [0, 0, 0, 0, 500];
console.log("stable:", basicStats(stable));
console.log("unstable:", basicStats(unstable));
JavaScriptイメージとしては、こうなります。
stable の結果は、 mean ≒ 100 stddev ≒ 0(ほぼバラつきなし)
unstable の結果は、 mean ≒ 100 stddev がかなり大きい(バラつきが大きい)
ここでのポイントは、「平均は同じでも、標準偏差が全然違う」というところです。 これによって、「このデータは安定しているのか、たまにドカンなのか」が分かります。
ユーティリティ 2:オブジェクト配列から「特定フィールドの統計情報」を作る
シナリオ
売上配列から「amount の統計情報」を作りたい。 レスポンス時間配列から「duration の統計情報」を作りたい。
実装:fieldStats
function fieldStats(records, field) {
if (!Array.isArray(records) || records.length === 0) {
return basicStats([]);
}
const values = records
.map((r) => r[field])
.filter((v) => typeof v === "number" && !Number.isNaN(v));
return basicStats(values);
}
JavaScript重要ポイントをかみ砕いて説明
records が配列でない・空配列なら basicStats([]) を返します。 指定フィールド field の値だけを取り出し、数値でないものや NaN をフィルタしています。 最後は basicStats に渡して、統計情報を作っています。
これで、「オブジェクト配列の特定フィールドに対する統計情報」が簡単に作れます。
例題 2:売上配列から amount の統計情報を作る
const sales = [
{ id: 1, store: "A", amount: 100 },
{ id: 2, store: "A", amount: 200 },
{ id: 3, store: "B", amount: 150 },
];
const amountStats = fieldStats(sales, "amount");
console.log(amountStats);
JavaScript出力イメージはこうなります。
{
count: 3,
mean: 150,
variance: 1666.666...,
stddev: 40.82...,
median: 150
}
JavaScriptここでのポイントは、
平均 150 中央値 150 標準偏差はそこそこ(100〜200 の範囲でほどほどにバラついている)
というところです。
ユーティリティ 3:パーセンタイル(上位何%のラインか)を計算する
シナリオ
レスポンス時間の配列から「90 パーセンタイル(P90)」を知りたい。 「この値以下なら、全体の 90%が収まっている」というラインを知りたい。
実装:percentile
function percentile(values, p) {
if (!Array.isArray(values) || values.length === 0) {
return null;
}
const nums = values
.filter((v) => typeof v === "number" && !Number.isNaN(v))
.sort((a, b) => a - b);
const count = nums.length;
if (count === 0) {
return null;
}
const clampedP = Math.min(Math.max(p, 0), 100);
const rank = (clampedP / 100) * (count - 1);
const lowerIndex = Math.floor(rank);
const upperIndex = Math.ceil(rank);
if (lowerIndex === upperIndex) {
return nums[lowerIndex];
}
const weight = rank - lowerIndex;
return nums[lowerIndex] * (1 - weight) + nums[upperIndex] * weight;
}
JavaScript重要ポイントをかみ砕いて説明
values から数値だけを取り出し、昇順にソートします。 p は 0〜100 のパーセンテージで、範囲外なら 0〜100 に丸めます。 rank は「何番目の位置か」を小数で表したものです。 lowerIndex と upperIndex の間を線形補間して、パーセンタイル値を求めています。
これで、「P50(中央値)」「P90」「P95」などを柔軟に計算できます。
例題 3:レスポンス時間の P90 を計算する
const responseTimes = [100, 120, 130, 200, 300, 400, 500];
const p90 = percentile(responseTimes, 90);
const p50 = percentile(responseTimes, 50);
console.log("P50:", p50);
console.log("P90:", p90);
JavaScriptイメージとしては、
P50 は「真ん中あたりの値」 P90 は「全体の 90%がこの値以下に収まるライン」
になります。
ここでのポイントは、「平均ではなく、パーセンタイルで“ほとんどのユーザーがどのくらいの値を見ているか”を知る」ことです。 レスポンス時間や処理時間の評価では、平均よりも P90・P95 がよく使われます。
ユーティリティ 4:統計情報生成を「業務サマリー」に組み込む
シナリオ
売上ダッシュボードで、「合計・平均」に加えて「標準偏差・中央値」も出したい。 レスポンス監視画面で、「平均・P90・P95」を出したい。
統計情報をまとめたオブジェクトを返す
例えば、売上配列に対してこんなユーティリティを作れます。
function salesStatsSummary(sales) {
const amountStats = fieldStats(sales, "amount");
const amounts = sales
.map((s) => s.amount)
.filter((v) => typeof v === "number" && !Number.isNaN(v));
const p90 = percentile(amounts, 90);
const p50 = percentile(amounts, 50);
return {
amount: amountStats,
p50,
p90,
};
}
JavaScript使い方はこうです。
const sales = [
{ id: 1, store: "A", amount: 100 },
{ id: 2, store: "A", amount: 200 },
{ id: 3, store: "B", amount: 150 },
];
console.log(salesStatsSummary(sales));
JavaScriptここでのポイントは、
「統計情報生成ユーティリティ」を組み合わせて、 業務でそのまま使える「統計サマリーオブジェクト」を作っていることです。
統計情報生成ユーティリティで意識してほしい重要ポイント
「平均だけでは足りない」という感覚を持つ
統計情報生成の一番大事なポイントは、 「平均だけではデータの性格は分からない」という感覚を持つことです。
標準偏差で「バラつき」を見る。 中央値で「極端な値に引っ張られない代表値」を見る。 パーセンタイルで「ほとんどのケースがどこに収まっているか」を見る。
初心者のうちは、
まずは basicStats の mean・stddev・median 次に percentile の P90・P95
くらいから触ってみると、 「データの見え方」が一気に変わります。
「統計情報は“判断の材料”になる」
統計情報生成ユーティリティは、 単なる数字遊びではなく、「業務の判断の材料」を作るためのものです。
売上が安定しているか。 工数が偏っていないか。 レスポンスが一部のユーザーだけ極端に遅くなっていないか。
こういう問いに答えるために、 統計情報を配列から自動で生成しておくと、 「感覚」ではなく「数字」で話ができるようになります。
手を動かして「統計情報生成」の感覚をつかむ
次のコードを実行して、
基本統計情報 フィールド統計情報 パーセンタイル
を一気に体感してみてください。
function basicStats(values) {
if (!Array.isArray(values) || values.length === 0) {
return { count: 0, mean: 0, variance: 0, stddev: 0, median: null };
}
const nums = values.filter(
(v) => typeof v === "number" && !Number.isNaN(v)
);
const count = nums.length;
if (count === 0) {
return { count: 0, mean: 0, variance: 0, stddev: 0, median: null };
}
const sum = nums.reduce((acc, v) => acc + v, 0);
const mean = sum / count;
const sqDiffSum = nums.reduce((acc, v) => {
const diff = v - mean;
return acc + diff * diff;
}, 0);
const variance = sqDiffSum / count;
const stddev = Math.sqrt(variance);
const sorted = [...nums].sort((a, b) => a - b);
let median;
if (count % 2 === 1) {
median = sorted[(count - 1) / 2];
} else {
const mid1 = sorted[count / 2 - 1];
const mid2 = sorted[count / 2];
median = (mid1 + mid2) / 2;
}
return { count, mean, variance, stddev, median };
}
function fieldStats(records, field) {
if (!Array.isArray(records) || records.length === 0) {
return basicStats([]);
}
const values = records
.map((r) => r[field])
.filter((v) => typeof v === "number" && !Number.isNaN(v));
return basicStats(values);
}
function percentile(values, p) {
if (!Array.isArray(values) || values.length === 0) {
return null;
}
const nums = values
.filter((v) => typeof v === "number" && !Number.isNaN(v))
.sort((a, b) => a - b);
const count = nums.length;
if (count === 0) {
return null;
}
const clampedP = Math.min(Math.max(p, 0), 100);
const rank = (clampedP / 100) * (count - 1);
const lowerIndex = Math.floor(rank);
const upperIndex = Math.ceil(rank);
if (lowerIndex === upperIndex) {
return nums[lowerIndex];
}
const weight = rank - lowerIndex;
return nums[lowerIndex] * (1 - weight) + nums[upperIndex] * weight;
}
function demo() {
const sales = [
{ id: 1, store: "A", amount: 100 },
{ id: 2, store: "A", amount: 200 },
{ id: 3, store: "B", amount: 150 },
];
console.log("=== basicStats (amounts) ===");
console.log(basicStats(sales.map((s) => s.amount)));
console.log("=== fieldStats (amount) ===");
console.log(fieldStats(sales, "amount"));
const responseTimes = [100, 120, 130, 200, 300, 400, 500];
console.log("=== percentile (P50, P90) ===");
console.log("P50:", percentile(responseTimes, 50));
console.log("P90:", percentile(responseTimes, 90));
}
demo();
JavaScriptまとめ:統計情報生成ユーティリティで「配列の性格を、数字で語れるようにする」
統計情報生成は、 「配列の性格(安定・バラつき・偏り)を、平均だけでなく統計指標で語れるようにするためのユーティリティ」です。
プロジェクトに例えば次のような形で置いておくイメージです。
export function basicStats(values) { ... }
export function fieldStats(records, field) { ... }
export function percentile(values, p) { ... }
JavaScriptそして、
ダッシュボード、 監視画面、 レポート、
など、「データの質を評価したい場面」で必ずこの統計情報生成を通す。
こう決めておくと、 「なんとなく」ではなく「数字で」データを語れるようになり、 業務の判断が一段クリアになります。
平均だけじゃ、もったいない。 統計情報で、配列の“性格”まで見に行きましょう。
