目盛りの自動生成アルゴリズム比較

目盛りの自動生成アルゴリズム比較

D3.js、Recharts、EChartsの3つのグラフライブラリにおける目盛り生成アルゴリズムの実装方法を比較。読みやすさとデータカバレッジの両立方法を解説します。
2025.11.11

グラフの軸に表示する目盛り(ticks)は、どうやって決まっているのでしょうか?

「0 から 100 まで、5 つくらい目盛りを表示したい」という要求は単純に見えますが、実際には「読みやすい数値」「適切な間隔」「データ範囲のカバー」といった複数の要件のバランスを取る必要があります。

この記事では、目盛り生成アルゴリズムの観点から、主要なグラフライブラリ(D3.js、Recharts、ECharts)を比較します。

目盛り生成の難しさ

グラフの軸目盛りは、ただの数値の羅列ではありません。良い目盛りは以下の特徴を持っています。

  • 読みやすい数値: 5、10、100 のような切りの良い数
  • 適切な間隔: データの範囲を適切にカバーしている
  • 適度な密度: 多すぎず少なすぎない

しかし、これらの要件はしばしば矛盾します。

データの範囲がちょうどきりの良い数になることは稀です。例えば以下のようなケースがあります。

  • 売上データの範囲が ¥127〜¥2,847,293
  • 温度データの範囲が-3.7°C〜24.3°C
  • アクセス数の範囲が 127〜8,942

このような「半端な数値」をそのまま軸の範囲として使うと、読みやすい目盛りを生成するのが難しくなります。

例えば、min=3、max=47 の範囲で、読みやすい目盛りを 5 つくらい作りたい場合を考えてみましょう。10 刻みの目盛り[10, 20, 30, 40, 50]を作ると読みやすいですが、最小値 3 をカバーできません。一方、データの最小値 3 から最大値 47 までをきっちり含めると[3, 14, 25, 36, 47]のような半端な目盛りになってしまいます。

この問題を解決するため、多くのライブラリは「範囲の調整」という戦略を取ります。データ範囲を少し拡張して(3〜47 → 0〜50)、きれいな目盛りとデータのカバレッジを両立させるのです。

各ライブラリの比較

D3.js: プリミティブな API を提供

D3 は目盛り生成のためのプリミティブな API を提供しています。

scale.ticks(count)

指定された範囲内で、読みやすい目盛りを生成します。ただし、問題があります。

例えば、domain を [3, 47] として ticks(5) を呼ぶと、[10, 20, 30, 40] のような目盛りが生成されます。読みやすい数値(10 刻み)ですが、最小値 3 と最大値 47 が範囲外になってしまいます。

scale.nice()

この問題を解決する方法の 1 つとして、nice() で domain を拡張できます。[3, 47] を [0, 50] に拡張することで、ticks() が生成する目盛りが必ずデータ範囲をカバーするようにします。

ただし、nice() は必須ではありません。他にも解決方法があります。

  • domain を最初から [0, 50] のように手動で設定する
  • データの最小値・最大値にパディングを追加してから範囲を設定する
  • tickValues で目盛りを明示的に指定する

D3 は開発者に選択を委ねており、状況に応じて適切な方法を選べます。scale.nice().ticks() はその中でも便利な組み合わせの 1 つです。

Recharts: 厳密な目盛り数の遵守

Recharts は内部的に独自のアルゴリズム(getNiceTickValues)を使用しています。最初から範囲の拡張が組み込まれているため、D3 のnice()と同じような処理が自動的に行われます。

**重要な特徴として、Recharts は希望した目盛り数を厳密に守ります。**これは複合軸グラフ(左右に Y 軸がある)で便利です。左右の目盛り数が揃っていれば、グリッド線の高さも自動的に揃うためです。

D3 や ECharts は「5 つくらい」という目安として扱い、4 つや 6 つになることもありますが、Recharts は指定された数をできるだけ正確に守ろうとします。

ECharts: バランス重視

ECharts も範囲の拡張と読みやすい目盛りの生成を自動で行います。内部的にはintervalScaleNiceTicksという関数を使い、精度を保ちながらきれいな間隔を計算します。

Recharts と異なり、目盛り数を厳密に守ることはありません。

そのため、alignTicks を true にすると場合によっては次のように右Y軸の温度表示に中途半端な数値が出現します。

align-ticks-true

実際の挙動を比較する

例えば、min=3、max=47、希望目盛り数=5 のような「半端な範囲」を指定した場合、以下のような違いがあります。

ライブラリ 挙動
D3 (nice) 範囲を 0〜50 に拡張して、[0, 10, 20, 30, 40, 50]のような目盛りを生成
D3 (nice なし) [10, 20, 30, 40]のような目盛りを生成し、データ範囲をカバーできない
Recharts 自動的に範囲を調整して、データをカバーする目盛りを生成
ECharts 独自のインターバル計算により、バランスの取れた目盛りを生成

Recharts や ECharts は、このような範囲の調整が最初から組み込まれているため、ユーザーが意識しなくても正しく動作します。D3 は柔軟性が高い反面、nice()を明示的に呼ぶ必要があります。

可視化ツール

これらの違いを実際に体験できる比較ツールを作成しました。パラメータをリアルタイムで変更しながら、各ライブラリの目盛り生成を視覚的に比較できます。

tick-comparison

https://hbsnow-sandbox.github.io/tick-comparison/

実際に触ってみると、各ライブラリの特性がよくわかります。

まとめ

グラフの目盛り生成で最も重要なのは、データの範囲を適切にカバーしつつ、読みやすい目盛りを提供することです。

今回比較した目盛り生成アルゴリズムには、大きく2つのアプローチがありました。

目盛り数を柔軟に調整する(D3、ECharts)

読みやすさを最優先し、希望した目盛り数は目安として扱います。4つや6つになることもありますが、常にきれいな数値(10、20、50など)を生成できます。

目盛り数を厳密に守る(Recharts)

希望した目盛り数を必ず守ります。これにより、複合軸グラフで左右のY軸の目盛り数が一致し、グリッド線がきれいに揃います。一方で、状況によっては多少読みにくい数値になることもあります。

どちらのアプローチにも利点があり、用途によって使い分けることができます。

この記事をシェアする

FacebookHatena blogX

関連記事