Frage

muß ich ein Diagramm mit einem optimierten y machen Achse Maximalwert.

Die aktuelle Methode Ich habe Diagramme machen verwendet einfach den maximalen Wert aller Graphen, teilt sie dann von zehn, und verwendet diese als Gitterlinien. Ich habe es nicht schreiben.

Update Hinweis: haben Diese Diagramme geändert. Sobald ich den Code, meine dynamische Diagramme fixiert zu arbeiten begann, diese Frage unsinnig machen (weil die Beispiele nicht mehr in ihnen Fehler hatte). Ich habe diese mit statischen Bildern aktualisiert, aber einige der Antworten refrence unterschiedliche Werte. Vergiss das nicht. Old Chart Es gab zwischen 12.003 und 14.003 eingehende Anrufe so weit im Februar. Informativ, aber hässlich.

Ich möchte Charts vermeiden, die wie ein Affe aussehen kam mit dem y -Achse Zahlen.

die Charts API Google verwenden hilft ein wenig, aber es ist noch nicht ganz das, was ich will. Google API-Diagramm Die Zahlen sind sauber, aber die Spitze des y-Wert ist immer der gleiche wie der Maximalwert auf der Karte. Diese Diagramm Skalen von 0 bis 1357. Ich brauche den richtigen Wert von 1400 berechnet haben, problematically .


Ich werfe in rbobby 's defanition einem' nice "Nummer hier, weil es sie so gut erklärt.

  • A "schön" -Nummer ist eine, die 3 oder weniger Nicht-Null-Ziffern (zB. 1230000)
  • A "nice" Anzahl der gleichen oder wenige Nicht-Null-Ziffern als Nullstellen hat (zB 1230 ist nicht schön, 1200 schön ist)
  • Die schönsten Zahlen sind diejenigen mit ein Vielfaches von 3 Nullen (z. B. „1000“, „1000000“)
  • Die zweiten netteste Zahlen sind onces mit multples von 3 Nullen plus 2 Nullen (z. B. "1500000", "1200")

Lösung

ich den Weg gefunden, um die Ergebnisse zu bekommen, dass ich eine modifizierte Version von Mark Ransom Idee mit will.

Faust, Mark Ransom Code bestimmt den optimalen Abstand zwischen Zecken, wenn die Anzahl der Ticks angegeben. Manchmal wird diese Zahl endet mehr als doppelt, was der höchste Wert auf der Karte ist, je nachdem, wie viele Gitterlinien Sie wollen.

Was ich tue, ist, dass ich Mark Code mit 5, Laufen 6, 7, 8, 9 und 10 Rasterlinien (Zecken), die von denen zu finden, ist die niedrigste. Mit einem Wert von 23, geht die Höhe des Diagramms bis 25, mit einer Gitterlinie bei 5, 10, 15, 20 und 25 mit einem Wert von 26, wobei die Höhe des Diagramms 30 ist, mit Rasterlinien 5, 10 , 15, 20, 25 und 30. Es ist den gleichen Abstand zwischen den Rasterlinien hat, aber es gibt mehr von ihnen.

Hier ist also die Schritte, um gerade zu kopieren, was Excel tut Charts alle Lust zu machen.

  1. Bump Vorübergehend des Diagramms höchsten Wert von etwa 5% bis (so dass es zwischen der Diagramm höchsten Punkt und der obere Teil der Diagrammfläche immer etwas Platz ist. Wir 99.9 wollen 120 aufrunden)
  2. Finden Sie die optimale Gitterlinie Platzierung für 5, 6, 7, 8, 9 und 10 Gitter Linien.
  3. Wählen Sie das niedrigste dieser Zahlen. Denken Sie daran, die Anzahl der Rasterlinien dauerte es, diesen Wert zu erhalten.
  4. Jetzt haben Sie die optimale Chart Höhe. Die Linien / bar wird nie gegen den oberen Rand des Diagramms Hintern und Sie haben die optimale Anzahl der Ticks.

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)
War es hilfreich?

Lösung

Dies ist aus einer früheren ähnlichen Frage:

Algorithmus für „nice“ Rasterlinie Abstände auf einem Diagramm

  

Ich habe dies getan, mit Art eines Brute   Force-Methode. Erstens, herauszufinden, die   maximale Anzahl der Tickmarken möglich   passen in den Raum. Teilen Sie die Gesamt   Bereich von Werten durch die Anzahl der   Zecken; dies ist das Minimum   Abstand der Zecke. jetzt berechnen   der Boden der Logarithmus zur Basis 10 zu   Holen Sie sich die Größe der Zecke, und   dividieren durch diesen Wert. Sie sollten beenden   mit etwas im Bereich von 1 bis   10. Einfach die runde Zahl größer als oder gleich den Wert wählen und   multiplizieren sie mit dem Logarithmus   früher berechnet. Dies ist dein   letzter Tick-Abstand.

     

Beispiel in 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

Andere Tipps

In der Vergangenheit habe ich dies getan, in einer Brute-Force-ish Art und Weise. Hier ist ein Stück von C ++ Code, der gut funktioniert ... aber für eine hartkodierte untere und obere Grenze (0 und 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];
}

Doch etwas in dem, was Sie gesagt haben gezwickt mich. Um schöne Achsnummern eine Definition von „schöner Zahl“ wählen würde helfen:

  • A "schön" -Nummer ist eine, die 3 oder weniger Nicht-Null-Ziffern (zB. 1230000)
  • A "nice" Anzahl der gleichen oder wenige Nicht-Null-Ziffern als Nullstellen hat (zB 1230 ist nicht schön, 1200 schön ist)
  • Die schönsten Zahlen sind diejenigen mit ein Vielfaches von 3 Nullen (z. B. „1000“, „1000000“)
  • Die zweiten netteste Zahlen sind onces mit multples von 3 Nullen plus 2 Nullen (z. B. "1500000", "1200")

Nicht sicher, ob die obige Definition „rechts“ ist oder tatsächlich hilfreich (aber mit der Definition in der Hand dann wird es eine einfachere Aufgabe, einen Algorithmus zu entwickeln).

Sie können auf zwei signifikante Zahlen aufrunden. Der folgende Pseudo-Code sollte funktionieren:

// maxValue is the largest value in your chart
magnitude = floor(log10(maxValue))
base = 10^(magnitude - 1)
chartHeight = ceiling(maxValue / base) * base

Wenn beispielsweise maxValue 1357 ist, dann ist Größenordnung 3 und Base 100.er Dividing 100, Aufrunden und mit 100 multipliziert hat das Ergebnis auf das nächste Vielfache von 100 Aufrunden, Abrunden, dh bis zu zwei signifikanten Zahlen. In diesem Fall ist das Ergebnis, wenn 1400 (1357 ⇒ 13.57 ⇒ 14 ⇒ 1400).

Eine leichte Verfeinerung und getestet ... (Werke für Bruchteile von Einheiten und nicht nur ganze Zahlen)

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);


    }

Wenn Sie 1400 an der Spitze wollen, wie etwa die letzten beiden Parameter auf 1400 eingestellt statt 1357:

alt text

Sie könnten div und mod verwenden. Zum Beispiel.

Angenommen, Sie haben Ihr Diagramm möchten in Schritten von 20 aufrunden (nur um es mehr eine beliebige Zahl als der typische „10“ -Wert).

Also ich würde davon ausgehen, dass 1, 11, 18 würden alle runden bis zu 20. Aber 21, 33, 38 würde auf 40 runden.

mit dem richtigen Wert zu kommen wie folgt vor:

Where divisor = your rounding increment.

divisor = 20
multiple = maxValue / divisor;  // Do an integer divide here. 
if (maxValue modulus divisor > 0)
   multiple++;

graphMax = multiple * maxValue;

So, jetzt wollen wir reelle Zahlen Plugin:

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;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top