質問
最適化された y 軸の最大値でチャートを作成する必要があります。
チャートを作成する現在の方法は、すべてのグラフの最大値を使用し、それを10で割ってグリッド線として使用します。書きませんでした。
更新注:これらのグラフは変更されています。コードを修正するとすぐに、動的グラフが機能し始め、この質問は無意味になりました(例にエラーが含まれなくなったため)。これらを静的な画像で更新しましたが、いくつかの答えは異なる値を参照しています。心に留めておきます。 これまで2月に12003〜14003の着信がありました。有益であるがbutい。
猿が y 軸の数字を思いついたように見えるチャートを避けたい。
Google charts APIを使用することは少し役立ちますが、それでもまだ私が望むものではありません。 数字はきれいですが、y値の上部は常にチャートの最大値と同じです。このチャートは、0から1357にスケールします。1400の適切な値を計算する必要があります。問題なく。
私は rbobby の「いいね」の誤解を投げかけています'それはとてもよく説明しているからです。
- 「いいね」数字は、ゼロ以下の数字が3つ以下の数字(例:1230000)
- 「いいね」数値はゼロ桁と同じか、またはゼロ以外の桁が少ない(たとえば、1230は良くない、1200はいい)
- 最も良い数は、3つのゼロの倍数を持つものです(例:「1,000」、「1,000,000」)
- 2番目に良い数字は、3つのゼロと2つのゼロのマルチプルである1回です(例:「1,500,000」、「1,200」)
解決策
Mark Ransomのアイデアの修正版を使用して、必要な結果を得る方法を見つけました。
最初に、Mark Ransomのコードは、ティック数が与えられたときに、ティック間の最適な間隔を決定します。必要なグリッド線の数によっては、この数値がグラフの最高値の2倍を超えることもあります。
私がやっていることは、マークのコードを5、6、7、8、9、10のグリッド線(目盛り)で実行して、どれが最も低いかを見つけることです。値が23の場合、チャートの高さは25になり、グリッド線は5、10、15、20、および25になります。値が26の場合、チャートの高さは30になり、グリッド線は5、10になります、15、20、25、および30。グリッド線の間隔は同じですが、さらに多くのグリッド線があります。
だから、ここではExcelがグラフをすべて洗練したものにするためのコピーを作成する手順を示します。
- チャートの最高値を一時的に約5%上げます(チャートの最高点とチャート領域の上部の間に常にスペースがあります。99.9を120に切り上げます)
- 最適なグリッド線の配置を見つける 5、6、7、8、9、および10グリッド用 行。
- これらの数字の中で最も小さいものを選びます。その値を得るためにかかったグリッド線の数を覚えておいてください。
- これで最適なチャートの高さが得られました。線/棒がチャートの上部に突き当たることはなく、ティックの最適数があります。
PHP:
function roundUp($maxValue){
$optiMax = $maxValue * 2;
for ($i = 5; $i <= 10; $i++){
$tmpMaxValue = bestTick($maxValue,$i);
if (($optiMax > $tmpMaxValue) and ($tmpMaxValue > ($maxValue + $maxValue * 0.05))){
$optiMax = $tmpMaxValue;
$optiTicks = $i;
}
}
return $optiMax;
}
function bestTick($maxValue, $mostTicks){
$minimum = $maxValue / $mostTicks;
$magnitude = pow(10,floor(log($minimum) / log(10)));
$residual = $minimum / $magnitude;
if ($residual > 5){
$tick = 10 * $magnitude;
} elseif ($residual > 2) {
$tick = 5 * $magnitude;
} elseif ($residual > 1){
$tick = 2 * $magnitude;
} else {
$tick = $magnitude;
}
return ($tick * $mostTicks);
}
Python:
import math
def BestTick(largest, mostticks):
minimum = largest / mostticks
magnitude = 10 ** math.floor(math.log(minimum) / math.log(10))
residual = minimum / magnitude
if residual > 5:
tick = 10 * magnitude
elif residual > 2:
tick = 5 * magnitude
elif residual > 1:
tick = 2 * magnitude
else:
tick = magnitude
return tick
value = int(input(""))
optMax = value * 2
for i in range(5,11):
maxValue = BestTick(value,i) * i
print maxValue
if (optMax > maxValue) and (maxValue > value + (value*.05)):
optMax = maxValue
optTicks = i
print "\nTest Value: " + str(value + (value * .05)) + "\n\nChart Height: " + str(optMax) + " Ticks: " + str(optTicks)
解決
これは以前の同様の質問からのものです:
&quot; nice&quot;のアルゴリズムグラフ上のグリッド線間隔
私はこれをある種の野bru人でやった 力メソッド。まず、 目盛りの最大数 スペースに収まります。合計を割ります の数による値の範囲 ダニ;これは最小です 目盛りの間隔。計算する 10を底とする対数の底 ティックの大きさを取得し、 この値で除算します。終了する必要があります 1から 10.値以上のラウンド数を選択し、 対数を掛けます 以前に計算された。これはあなたの 最終ティック間隔。
Pythonの例:
import math
def BestTick(largest, mostticks):
minimum = largest / mostticks
magnitude = 10 ** math.floor(math.log(minimum) / math.log(10))
residual = minimum / magnitude
if residual > 5:
tick = 10 * magnitude
elif residual > 2:
tick = 5 * magnitude
elif residual > 1:
tick = 2 * magnitude
else:
tick = magnitude
return tick
他のヒント
過去には、これを総当たり的な方法で行ってきました。これはうまく機能するC ++コードの塊です...ただし、ハードコードされた下限と上限(0と5000):
int PickYUnits()
{
int MinSize[8] = {20, 20, 20, 20, 20, 20, 20, 20};
int ItemsPerUnit[8] = {5, 10, 20, 25, 50, 100, 250, 500};
int ItemLimits[8] = {20, 50, 100, 250, 500, 1000, 2500, 5000};
int MaxNumUnits = 8;
double PixelsPerY;
int PixelsPerAxis;
int Units;
//
// Figure out the max from the dataset
// - Min is always 0 for a bar chart
//
m_MinY = 0;
m_MaxY = -9999999;
m_TotalY = 0;
for (int j = 0; j < m_DataPoints.GetSize(); j++) {
if (m_DataPoints[j].m_y > m_MaxY) {
m_MaxY = m_DataPoints[j].m_y;
}
m_TotalY += m_DataPoints[j].m_y;
}
//
// Give some space at the top
//
m_MaxY = m_MaxY + 1;
//
// Figure out the size of the range
//
double yRange = (m_MaxY - m_MinY);
//
// Pick the initial size
//
Units = MaxNumUnits;
for (int k = 0; k < MaxNumUnits; k++)
{
if (yRange < ItemLimits[k])
{
Units = k;
break;
}
}
//
// Adjust it upwards based on the space available
//
PixelsPerY = m_rcGraph.Height() / yRange;
PixelsPerAxis = (int)(PixelsPerY * ItemsPerUnit[Units]);
while (PixelsPerAxis < MinSize[Units]){
Units += 1;
PixelsPerAxis = (int)(PixelsPerY * ItemsPerUnit[Units]);
if (Units == 5)
break;
}
return ItemsPerUnit[Units];
}
しかし、あなたが言ったことの中の何かが私を微調整しました。素敵な軸番号を選択するには、「素敵な番号」の定義を使用します。役立つでしょう:
- 「いいね」数字は、ゼロ以下の数字が3つ以下の数字(例:1230000)
- 「いいね」数値はゼロ桁と同じか、またはゼロ以外の桁が少ない(たとえば、1230は良くない、1200はいい)
- 最も良い数は、3つのゼロの倍数を持つものです(例:「1,000」、「1,000,000」)
- 2番目に良い数字は、3個のゼロと2個のゼロの複数で構成される1回です(例:「1,500,000」、「1,200」)
上記の定義が「正しい」かどうかわからないまたは実際に役立ちます(ただし、定義が手元にあれば、アルゴリズムを考案するのがより簡単なタスクになります)。
2つの有効数字まで切り上げることができます。次の擬似コードが機能するはずです:
// maxValue is the largest value in your chart
magnitude = floor(log10(maxValue))
base = 10^(magnitude - 1)
chartHeight = ceiling(maxValue / base) * base
たとえば、 maxValue
が1357の場合、大きさは3、底は100です。100で除算、切り上げ、100を乗算すると、100の次の倍数に切り上げられます。 、つまり、2つの有効数字に切り上げます。この場合、1400(1357&#8658; 13.57&#8658; 14&#8658; 1400)の場合の結果。
わずかな改良とテスト...(整数だけでなく、単位の小数でも機能します)
public void testNumbers() {
double test = 0.20000;
double multiple = 1;
int scale = 0;
String[] prefix = new String[]{"", "m", "u", "n"};
while (Math.log10(test) < 0) {
multiple = multiple * 1000;
test = test * 1000;
scale++;
}
double tick;
double minimum = test / 10;
double magnitude = 100000000;
while (minimum <= magnitude){
magnitude = magnitude / 10;
}
double residual = test / (magnitude * 10);
if (residual > 5) {
tick = 10 * magnitude;
} else if (residual > 2) {
tick = 5 * magnitude;
} else if (residual > 1) {
tick = 2 * magnitude;
} else {
tick = magnitude;
}
double curAmt = 0;
int ticks = (int) Math.ceil(test / tick);
for (int ix = 0; ix < ticks; ix++) {
curAmt += tick;
BigDecimal bigDecimal = new BigDecimal(curAmt);
bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP);
System.out.println(bigDecimal.stripTrailingZeros().toPlainString() + prefix[scale] + "s");
}
System.out.println("Value = " + test + prefix[scale] + "s");
System.out.println("Tick = " + tick + prefix[scale] + "s");
System.out.println("Ticks = " + ticks);
System.out.println("Scale = " + multiple + " : " + scale);
}
上部に1400が必要な場合は、最後の2つのパラメーターを1357ではなく1400に調整してください。
divおよびmodを使用できます。たとえば。
グラフを20単位で切り上げたいとしましょう(通常の「10」の値よりも任意の数にするため)。
したがって、1、11、18はすべて20に切り上げられますが、21、33、38は40に切り上げられます。
正しい値を見つけるには、次の手順を実行します。
Where divisor = your rounding increment.
divisor = 20
multiple = maxValue / divisor; // Do an integer divide here.
if (maxValue modulus divisor > 0)
multiple++;
graphMax = multiple * maxValue;
それでは、実数をプラグインしましょう:
divisor = 20; multiple = 33 / 20; (integer divide) so multiple = 1 if (33 modulus 20 > 0) (it is.. it equals 13) multiple++; so multiple = 2; graphMax = multiple (2) * maxValue (20); graphMax = 40;