複数の指標を1本のスコアにまとめる仕事は、見た目ほど単純ではありません。
「配信の同時視聴者数」と「メディアに出た記事の本数」を足したい、という場面を考えてみてください。前者は数万単位で動き、後者は0本から数本の間に収まります。そのまま足せば、前者がすべてを決めてしまう。重みで調整しようにも、そもそも単位が揃っていません。
ゲームタイトルの熱量を、配信・検索・記事・コミュニティなど10種類以上の公開データから合成しているダッシュボードがあります。その設計の考え方を材料に、単位の違う指標をどう1つの物差しに載せるかを整理します(公開情報は2026年9月時点)。
→ 10種類以上の公開データを合成したゲーム熱量スコアの GameAxiz
1. まず「その日の中での位置」に直す
最初の一手は、各指標を同じ範囲に写すことです。このダッシュボードでは、系列ごとにその日の全タイトル中の最大値を基準にして0〜100へ直しています。
// 系列ごとに、その日の最大値を 100 とする
function toRelative(value: number, dayMax: number): number {
if (dayMax <= 0 || value <= 0) return 0;
return Math.min(100, (value / dayMax) * 100);
}
この時点でスコアの意味が決まります。結果は絶対量ではなく、その日の顔ぶれの中での相対的な位置です。サイト側もこの点を明記していて、0〜100は「絶対的な人気を表すものではない」と断っています。
相対化の代償は、日をまたいだ比較が素直にできなくなることです。昨日の70と今日の70は、比べている相手が違います。変化を追うなら、スコアそのものより「1週間前との差」のように差分として扱うほうが扱いやすくなります。
2. 線形のままだと、下位が全部0に潰れる
上の関数には問題があります。視聴者数やレビュー数のような量は、上位と下位で桁が3つも4つも違います。
最大値が100万のとき、1,000の値は線形だと0.1点です。ランキングの大半が0点付近に貼り付き、中位の差がまったく見えなくなります。
こういう桁違いの差がつく量は対数に写すのが定石です。
function toRelativeLog(value: number, dayMax: number): number {
if (dayMax <= 0 || value <= 0) return 0;
return (Math.log10(1 + value) / Math.log10(1 + dayMax)) * 100;
}
1 + を入れているのは、値が1以下のときに負の対数が出ないようにするためです。これで最大100万に対して1,000は約50点になり、中位のタイトル同士の違いが目に見える幅で出てきます。
3. ただし、小さい整数を対数にすると逆に壊れる
では全部対数にすればいいかというと、そうはいきません。
記事の本数や大会の数のような小さな整数を対数に写すと、今度は1本あるだけで大きな点が付きます。最大が5本の日に1本は、対数だと4割近い点数になります。「1本出た」と「5本出た」の差が、実感よりずっと小さく見えてしまう。
そこで指標ごとに尺度を宣言します。
type Scale = "log" | "linear";
type Signal = { key: string; scale: Scale; weight: number };
function normalize(v: number, max: number, scale: Scale): number {
return scale === "log" ? toRelativeLog(v, max) : toRelative(v, max);
}
判断の基準は「その量の分布が何桁にまたがるか」です。
| 量の性質 | 例 | 尺度 |
|---|---|---|
| 桁違いに開く | 同時視聴者数、再生数、レビュー数 | 対数 |
| 小さな整数に収まる | 記事本数、大会の件数 | 線形 |
4. ストックとフローを混ぜない
もう1つの落とし穴は、性質の違う量を同じ鍋に入れることです。
Steamのレビュー数やコミュニティの参加者数は、長い時間をかけて積み上がった量(ストック)です。一方、今日の配信視聴者数や今週の記事本数はいま起きていること(フロー)です。
ストックを熱量と同列に混ぜると、発売から何年も経った大型タイトルが、何も起きていない日でも上位に居座ります。「いま熱いもの」を見たいのに、「これまで大きかったもの」が答えとして返ってくるわけです。
このダッシュボードでは、ストックを「規模」として別枠にまとめ、総合スコアへは小さく効かせる形を取っています。規模を無視はしないが、日々の動きを覆い隠さない、というバランスです。
const flow = weighted(flowSignals); // 配信・検索・記事など
const stock = weighted(stockSignals); // レビュー数・コミュニティ規模など
const total = mix(flow, stock); // stock 側の比重は小さくとる
なお、この「規模」をそのまま売上と読むのは誤りです。サイトでも、販売規模はSteamのレビュー数を基にした推定であり、家庭用ゲーム機の売上は含まないと明記されています。指標の名前が読み手の期待とずれるときは、画面の上で但し書きを添えるのが誠実だと思います。
5. 地域ごとに別々に合成する
最後に、合成を1回で済ませない理由です。
国内で話題でも海外では静か、あるいはその逆、というタイトルは珍しくありません。両方をまとめて平均すると、偏りの大きいタイトルほど中くらいの点数に丸められ、特徴が消えます。
そこで重みのセットを地域ごとに持ち、国内スコアと海外スコアを別々に算出します。公開されている説明では、国内側は日本語版Wikipediaの閲覧数と国内メディアの記事本数が中心、海外側はTwitchの視聴者数と英語版Wikipediaが中心です。
詳細ページでは、総合・国内・海外の3つを並べ、どの指標が押し上げているかも表示しています。合成した数字を出すなら、分解した姿も一緒に出す。単一のスコアに対する疑問のほとんどは、内訳が見えるだけで解消します。
まとめ
- 単位の違う指標は、まず系列ごとに同じ範囲(0〜100)へ写す。結果は相対値になる
- 桁違いに開く量は対数、小さな整数は線形。指標ごとに尺度を宣言する
- 積み上がった量(ストック)は別枠にし、日々の動き(フロー)を隠さない比重で混ぜる
- 偏りそのものに意味があるなら、平均せずに軸を分けて合成する
- 合成スコアには内訳を添える
どれも個別には地味な判断ですが、1つでも抜けると「見た目はそれらしいのに、誰の実感とも合わない数字」ができあがります。
本ページはプロモーションが含まれています


Top comments (0)