質問
軸の最小値と最大値を計算するためのまともなアルゴリズムを持っている人はいますか?
特定のデータ項目セットのグラフを作成するときに、アルゴリズムを指定できるようにしたいと考えています。
- セット内の最大 (y) 値
- セット内の最小 (y) 値
- 軸上に表示される目盛りの数
- オプションの値 しなければならない チェックマークとして表示されます (例:+ve および -ve 値を表示する場合はゼロ)
アルゴリズムは返されるはずです
- 軸の最大値
- 軸の最小値 (ただし、これは最大の間隔サイズとティック数から推測できます)
- 間隔のサイズ
目盛りは一定の間隔である必要があり、「適切な」サイズである必要があります (例:1、3、5、場合によっては 2.5 も可能ですが、それ以上のシグニチャーはありません)。
オプションの値の存在によりこれは歪められますが、その値がないと、最大の項目は上の 2 つの目盛りの間に表示され、最小値は下の 2 つの目盛りの間に表示されます。
これは言語に依存しない質問ですが、C#/.NET ライブラリがあれば、それは素晴らしいことになります ;)
解決
私はjQueryを使ってきました 浮く グラフライブラリ。これはオープンソースであり、軸/ティックの生成を非常にうまく実行します。コードを見て、そこからいくつかのアイデアを抜粋することをお勧めします。
他のヒント
OK、これがアプリケーションの 1 つについて私が思いついたものです。オプションの値は常に 0 であるため、これはあなたが言及した「オプションの値」シナリオを扱っていないことに注意してください。しかし、変更するのは難しくないはずです。
データは系列に継続的に追加されるため、追加された各データ ポイントを検査することで y 値の範囲を最新に保つだけです。これは非常に安価で、追跡も簡単です。最小値と最大値が等しい場合は特殊な場合があります。間隔 0 は、マーカーを描画しないことを示します。
この解決策は、指数乗数の任意の分数を少し厄介な方法で処理する点を除けば、上記の Andrew の提案と似ています。
最後に、このサンプルは C# で作成されています。それが役に立てば幸い。
private float GetYMarkerSpacing()
{
YValueRange range = m_ScrollableCanvas.
TimelineCanvas.DataModel.CurrentYRange;
if ( range.RealMinimum == range.RealMaximum )
{
return 0;
}
float absolute = Math.Max(
Math.Abs( range.RealMinimum ),
Math.Abs( range.RealMaximum ) ),
spacing = 0;
for ( int power = 0; power < 39; ++power )
{
float temp = ( float ) Math.Pow( 10, power );
if ( temp <= absolute )
{
spacing = temp;
}
else if ( temp / 2 <= absolute )
{
spacing = temp / 2;
break;
}
else if ( temp / 2.5 <= absolute )
{
spacing = temp / 2.5F;
break;
}
else if ( temp / 4 <= absolute )
{
spacing = temp / 4;
break;
}
else if ( temp / 5 <= absolute )
{
spacing = temp / 5;
break;
}
else
{
break;
}
}
return spacing;
}
以下をお勧めします。
- 視覚的に魅力的な主行の最小数を設定します。これは、提示するデータの性質と作成するプロットのサイズによって異なりますが、7 はかなり適切な数です。
- 1、2、5、10 などの数列に基づいて指数と乗数を選択します。これにより、少なくとも最小限の主行数が得られます。(すなわち。(最大-最小)/(スケール x 10^指数) >= minimum_tick_marks)
- 範囲内に収まる指数と乗数の最小の整数倍を見つけます。これが最初の大きなティックになります。残りのティックはこれから派生します。
これは、データの任意のスケーリングを可能にするアプリケーションに使用され、うまく機能すると思われました。