سؤال

كنت بحاجة لجعل الرسم البياني مع الأمثل y محور القيمة القصوى.

الطريقة الحالية لدي من صنع الخرائط ببساطة يستخدم أقصى قيمة جميع الرسوم البيانية ، ثم يقسم بعشرة, و يستخدم هذا مثل خطوط الشبكة.أنا لم أكتب ذلك.

تحديث ملاحظة: هذه الرسوم البيانية قد تغيرت.في أقرب وقت كما كنت ثابت رمز بلدي الرسوم البيانية ديناميكية بدأت العمل ، مما يجعل هذا السؤال لا معنى لها (لأن الأمثلة لم يعد لديه أي أخطاء فيها).لقد تم تحديث هذه مع صور ثابتة ، ولكن بعض الإجابات مراجع قيم مختلفة.والحفاظ على ذلك في الاعتبار.Old Chart كانت هناك بين 12003 و 14003 المكالمات الواردة حتى الآن في شباط / فبراير.بالمعلومات ، ولكن القبيح.

أود أن تجنب الرسوم البيانية التي تبدو مثل القرد جاء مع y-محور الأعداد.

باستخدام الرسوم البيانية جوجل API يساعد قليلا, لكنه لا يزال ليس تماما ما أريد.Google API Chart الأرقام هي نظيفة ، ولكن أعلى قيمة y دائما نفس القيمة القصوى على الرسم البياني.هذا المخطط جداول من 0 إلى 1357.أنا بحاجة إلى أن يكون حساب القيمة الصحيحة من عام 1400 ، إشكالية.


أنا رمي في rbobby's defanition من 'جميلة' عدد هنا لأنه يوضح ذلك جيدا.

  • "الجميل" رقم واحد هو أن لديه 3 أو أقل غير الصفر أرقام (على سبيل المثال.1230000)
  • "الجميل" عدد له نفس أو بضع غير الصفر الأرقام من صفر أرقام (على سبيل المثال 1230 ليست لطيفة, 1200 جميل)
  • اجمل الأرقام هي تلك مع مضاعفات 3 أصفار (على سبيل المثال."1,000", "1,000,000")
  • الثانية اجمل الأرقام onces مع multples من 3 أصفار زائد 2 الأصفار (على سبيل المثال."1,500,000", "1,200")

الحل

New Chart

لقد وجدت طريقة للحصول على النتائج التي أريد باستخدام نسخة معدلة من علامة فدية فكرة.

قبضة مارك فدية قانون يحدد تباعد الأمثل بين القراد عندما تعطى عدد من القراد.في بعض الأحيان هذا العدد ينتهي به الأمر إلى أكثر من ضعف ما أعلى قيمة على الرسم البياني ، اعتمادا على كيفية العديد من خطوط الشبكة التي تريدها.

ما أفعله هو أنني تشغيل مارك البرمجية 5, 6, 7, 8, 9, و 10 خطوط الشبكة (القراد) للعثور على من هو أدنى.بقيمة 23, ارتفاع الرسم البياني يذهب إلى 25 مع خط الشبكة في 5, 10, 15, 20, 25.بقيمة 26, الرسم البياني ارتفاع 30 ، مع خطوط الشبكة في 5, 10, 15, 20, 25, و 30.أنه يحتوي على نفس التباعد بين خطوط الشبكة ، ولكن هناك المزيد منها.

حتى هنا خطوات فقط عن نسخ ما Excel لجعل الرسوم البيانية عن الهوى.

  1. مؤقتا يرفعه الرسم البياني أعلى قيمة بنحو 5% (حيث أن هناك دائما بعض المساحة بين الرسم البياني أعلى نقطة و الجزء العلوي من الرسم البياني المنطقة.نريد 99.9 الجولة ما يصل الى 120)
  2. البحث الأمثل خط الشبكة التنسيب بالنسبة 5, 6, 7, 8, 9, و 10 الشبكة الخطوط.
  3. انتقاء أدنى من تلك الأرقام.تذكر عدد من خطوط الشبكة استغرق للحصول على تلك القيمة.
  4. الآن لديك الأمثل الارتفاع المخطط.خطوط/شريط لن بعقب ضد الجزء العلوي من الرسم البياني لديك العدد الأمثل من القراد.

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

بايثون:

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)
هل كانت مفيدة؟

المحلول

هذا من سابقة مماثلة السؤال:

خوارزمية "لطيفة" خط الشبكة فترات على الرسم البياني

لقد فعلت هذا مع نوع من الوحشية قوة الأسلوب.أولا معرفة أقصى عدد من علامات التجزئة يمكنك تناسب مساحة.تقسيم مجموع مجموعة من القيم من قبل عدد من القراد;هذا هو الحد الأدنى تباعد من القراد.حساب الآن الكلمة اللوغاريتم قاعدة 10 الحصول على حجم من القراد ، القسمة على هذه القيمة.يجب أن ينتهي شيء في النطاق من 1 إلى 10.ببساطة اختيار الجولة عدد أكبر من أو يساوي قيمة ، اضربها اللوغاريتم تحسب في وقت سابق.هذا هو الخاص بك النهائي القراد تباعد.

على سبيل المثال في بايثون:

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")
  • الثانية اجمل الأرقام onces مع multples من 3 أصفار زائد 2 الأصفار (على سبيل المثال."1,500,000", "1,200")

لست متأكدا إذا كان التعريف الوارد أعلاه هو "الحق" أو في الواقع مفيدة (ولكن مع التعريف الوارد في اليد ومن ثم يصبح من أبسط مهمة وضع خوارزمية).

هل يمكن أن يصل إلى اثنين من الشخصيات الهامة.التالية شبة الكود يجب أن تعمل:

// 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 ، أيالقبض على اثنين من الشخصيات الهامة.في هذه الحالة, نتيجة إذا 1400 (1357 ⇒ 13.57 ⇒ 14 ⇒ 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 في الجزء العلوي ، عن كيفية ضبط المعلمات الماضيين إلى 1400 بدلا من 1357:

alt text

هل يمكن استخدام div وزارة الدفاع.على سبيل المثال.

دعونا نقول كنت تريد الرسم البياني الخاص بك إلى الجولة قبل الزيادات من 20 (فقط لجعله أكثر أكثر عدد التعسفي من نموذجي "10" value).

لذلك أود أن نفترض أن 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;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top