2012-07-09 3 views
0

나는 백분율, 통화 값 또는 일반 숫자 일 수있는 통계를 그래프로 나타냅니다.그래프 최대 반올림

그래프 컨트롤의 축의 최대 값을 데이터 세트의 최대 값보다 조금 더 좋은 원형 숫자로 설정해야합니다. (그래프 컨트롤의 기본값은 내가 원하는 것이 아닙니다.)

두 가지 참고 사항 : 나는 축 최대 설정

  1. 값은 최소 5 % (이 더 나은 위 이하) 데이터 세트의 최대 값 이상이어야한다.

  2. 저는 Y 축 위에 4 개의 수평선이 있습니다. 그래서 이상적으로 Y 축 최대있을 4.

샘플 데이터가 좋게 분할한다 :이 경우

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

220 %가 최대 값으로 허용 될 수있다.

$3500161, $1825223, $1671232, $110112 

이 경우 $ 3680000는 괜찮을 수 있습니다. 또는 3700000 달러라고 생각합니다.

누구나 좋은 공식을 제안 할 수 있습니까? 5 % 이익률은 10 %로 변경 될 수있는 것처럼, 설정을 조정해야 할 수도 있고, 나는 당신의 첫번째 쿼리 사용을 위해 5

+0

왜이 레이블이 SQL입니까? 그래프를 생성하는 데 사용되는 C# 코드에서이 작업을 수행합니다. –

+0

sql 태그가 제거되었습니다. – Sean

답변

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_value 및 수학 분 주어진 Axis의 초기화에서 계산 min_value. 최대 값은 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
,617를 산출 계산
+0

그래, 나는 그것이 내가 수학을 완전히 지키지 않지만 내가 필요로하는 것 인 것을 생각한다! 약간 간격을 줄이기 위해 약간 수정해야 할 것입니다. 하지만 고마워! – Sean

0

에 4 개 개의 수평 라인을 변경해야 할 수도 있습니다 :

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 축의 최소/최대 간격을 정확히 1/4로 설정합니다 (사용자가 4를 지정한 경우). 그러므로 4로 나뉘는 숫자를 찾을 필요가 있습니다. "멋지게"- 그 부분은 내가 스스로해야만합니다 (자동 생성 된 선택이 싫다면). – Sean

0

먼저 (그래프 상단)/(최대 데이터 지점)의 범위를 결정해야합니다. 당신은 이것을 1.05로 밑줄 친다. 합리적인 상한은 1.1 또는 1.15 일 수 있습니다. 범위가 넓을수록 그래프 상단에 빈 공간이 더 많이 나타날 수 있지만 숫자가 더 좋을 수 있습니다. 또는 먼저 "niceness"기준을 선택한 다음 위의 비율이 최소 1.05 이상인 가장 작은 숫자를 선택하면됩니다.

또한 해당 하한을 느슨하게하면 (예 : 1.02 또는 1.0으로 낮춤) 간격의 "양호 함"을 향상시킬 수 있습니다.

편집 : 댓글에 대한 응답입니다.

좋은 최대 크기를 찾으려면해야 할 일은 최대 값 + 여백을 취해 간격 수로 나누고 가장 가까운 "nice"값으로 반올림하고 간격. "nice"의 합리적인 정의는 "10^(floor(log_10(max value)) - 2)의 배수"일 수 있습니다. 깔끔함을 느슨하게 정의하면 맨 위에 여백이 줄어 듭니다.

+1

내가 5 %라고 말한 이유는 바 라벨이 바 위에 올 수있는 충분한 공간을 확보해야하기 때문입니다. 그렇지 않으면 컨트롤이 막대 위에 놓습니다. 따라서 5-10 % 범위에 있어야합니다. 사실, 나는 단지 5 %를 정확히 시도했는데 충분하지 않습니다 (그냥!). 그래도 그 위에 멋진 라운드 번호를 얻는 방법을 아직 모르겠다. – Sean

+0

답글로 응답. –