2012-07-09 31 views
0

我正在繪製一些統計數據,可以是百分比,貨幣值或普通數字。向上舍入爲圖最大

我需要將圖形控件軸的最大值設置爲一個漂亮的圓形數字,稍微高於數據集中的最大值。 (圖形控件的默認值不是我想要的)。

有兩點需要注意:

  1. 我爲軸線的最大設定值應該是至少5%的數據集的最大值(高於此越少越好)以上。

  2. 我在0 Y軸上方有4條水平線;因此理想地在Y軸最大應由4.

樣本數據很好地劃分可能是:

200%, 100%, 100%, 100%, 75%, 50%, 9% 

在這種情況下,220%將是作爲最大值可以接受的。

$3500161, $1825223, $1671232, $110112 

在這種情況下,3680000美元可能沒問題。或者我想是3700000美元。

任何人都可以提出一個很好的公式嗎?我可能需要調整設置,比如5%的保證金可能會更改爲10%,否則我可能需要4條水平線更改爲5

+0

這是爲什麼標記爲SQL?您可以在用於生成圖形的C#代碼中執行此操作。 – 2012-07-09 14:41:52

+0

已刪除sql標記 – Sean 2012-07-09 15:01:55

回答

0

這是我用來創建圖形軸的代碼。

/// <summary> 
/// Axis scales a min/max value appropriately for the purpose of graphs 
/// <remarks>Code taken and modified from http://peltiertech.com/WordPress/calculate-nice-axis-scales-in-excel-vba/</remarks> 
/// </summary> 
public struct Axis 
{ 
    public readonly float min_value; 
    public readonly float max_value; 
    public readonly float major_step; 
    public readonly float minor_step; 
    public readonly int major_count; 
    public readonly int minor_count; 

    /// <summary> 
    /// Initialize Axis from range of values. 
    /// </summary> 
    /// <param name="x_min">Low end of range to be included</param> 
    /// <param name="x_max">High end of range to be included</param> 
    public Axis(float x_min, float x_max) 
    { 
     //Check if the max and min are the same 
     if(x_min==x_max) 
     { 
      x_max*=1.01f; 
      x_min/=1.01f; 
     } 
     //Check if dMax is bigger than dMin - swap them if not 
     if(x_max<x_min) 
     { 
      float temp = x_min; 
      x_min = x_max; 
      x_max = temp; 
     } 

     //Make dMax a little bigger and dMin a little smaller (by 1% of their difference) 
     float delta=(x_max-x_min)/2; 
     float x_mid=(x_max+x_min)/2; 

     x_max=x_mid+1.01f*delta; 
     x_min=x_mid-1.01f*delta; 

     //What if they are both 0? 
     if(x_max==0&&x_min==0) 
     { 
      x_max=1; 
     } 

     //This bit rounds the maximum and minimum values to reasonable values 
     //to chart. If not done, the axis numbers will look very silly 
     //Find the range of values covered 
     double pwr=Math.Log(x_max-x_min)/Math.Log(10); 
     double scl=Math.Pow(10, pwr-Math.Floor(pwr)); 
     //Find the scaling factor 
     if(scl>0&&scl<=2.5) 
     { 
      major_step=0.2f; 
      minor_step=0.05f; 
     } 
     else if(scl>2.5&&scl<5) 
     { 
      major_step=0.5f; 
      minor_step=0.1f; 
     } 
     else if(scl>5&&scl<7.5) 
     { 
      major_step=1f; 
      minor_step=0.2f; 
     } 
     else 
     { 
      major_step=2f; 
      minor_step=0.5f; 
     } 
     this.major_step=(float)(Math.Pow(10, Math.Floor(pwr))*major_step); 
     this.minor_step=(float)(Math.Pow(10, Math.Floor(pwr))*minor_step); 
     this.major_count=(int)Math.Ceiling((x_max-x_min)/major_step); 
     this.minor_count=(int)Math.Ceiling((x_max-x_min)/minor_step); 
     int i_1=(int)Math.Floor(x_min/major_step); 
     int i_2=(int)Math.Ceiling(x_max/major_step); 
     this.min_value=i_1*major_step; 
     this.max_value=i_2*major_step; 
    } 
    public float[] MajorRange 
    { 
     get 
     { 
      float[] res=new float[major_count+1]; 
      for(int i=0; i<res.Length; i++) 
      { 
       res[i]=min_value+major_step*i; 
      } 
      return res; 
     } 
    } 
    public float[] MinorRange 
    { 
     get 
     { 
      float[] res=new float[minor_count+1]; 
      for(int i=0; i<res.Length; i++) 
      { 
       res[i]=min_value+minor_step*i; 
      } 
      return res; 
     } 
    } 
} 

您可以在漂亮的max_valuemin_value從初始化計算Axis給出的數學分鐘。最大。值在x_minx_max

實施例:

  1. new Axis(0,3500161)計算max_value = 4000000.0
  2. new Axis(0,1825223)計算max_value = 2000000.0
  3. new Axis(0,1671232)計算max_value = 1800000.0
  4. new Axis(0, 110112)計算max_value = 120000.0
+0

是的,我認爲這大致是我需要的,儘管我沒有完全遵循數學呢!我將不得不稍微修改一下以減少差距。但是,謝謝! – Sean 2012-07-10 07:36:14

0

對於您的第一次查詢中使用:

DataView data = new DataView(dt); 
string strTarget = dt.Compute("MAX(target)", string.Empty).ToString();// target is your column name. 
int tTarget = int.Parse(strTarget.Equals("") ? "0" : strTarget); // Just in case if your string is empty. 
myChart.ChartAreas[0].AxisY.Maximum = myChart.ChartAreas[0].AxisY2.Maximum = Math.Ceiling(tTarget * 1.1); // This will give a 10% plus to max value. 

對於第二點,我想你可以用小/長軸交錯和偏移屬性來解決這個問題。

+0

圖表控件將自動將Y軸的最小值/最大值之間的間距設置爲恰好四分之一(如果指定爲4)。因此需要找到一個4分「很好」的數字 - 這部分我必須自己做(如果我不喜歡他們自動生成的選擇)。 – Sean 2012-07-09 17:22:23

0

首先,您需要決定(圖頂部)/(最大數據點)的範圍。你有這個下限爲1.05;合理的上限可能是1.1或1.15。範圍越寬,圖表頂部可能出現的空白空間越多,但數字可能會更好。或者,你可以先選擇一個「不錯」標準,然後在上述比率至少爲1.05的情況下選擇最小的足夠好的數字。

您還可以通過鬆開該下限來提高間隔的「好」,例如將其降低到1.02甚至1.0。

編輯:在迴應評論。

要找到一個好的最大尺寸,你需要做的是把你的最大值加上保證金,除以間隔的數量,把它向上舍入到最接近的「好」值,再乘以間隔。 「nice」的合理定義可能是「10^(floor(log_10(max value)) - 2)的倍數」。對nice的寬鬆定義會給你(平均)更少的額外保證金。

+1

我說5%的原因是因爲它應該爲酒吧標籤留出足夠的空間來放在酒吧上方。否則,控制器將其置於條上。所以它需要在5-10%的範圍內。事實上,我剛剛嘗試了5%,這還不夠(只是!)。仍然不知道如何獲得上面那個不錯的回合數,雖然... – Sean 2012-07-09 17:24:20

+0

在回答。 – 2012-07-09 18:10:25