1

我正在绘制一些统计数据,这些统计数据可以是百分比、货币价值或纯数字。

我需要将图形控件轴的最大值设置为一个不错的整数,略高于数据集中的最大值。(图形控件的默认值不是我想要的)。

有两点需要注意:

  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。

4

3 回答 3

1

这是我用来创建图形轴的代码。

/// <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_min和中的值x_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
于 2012-07-09T18:49:58.977 回答
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.

对于第二点,我想你可以用短轴/长轴交错和偏移属性来解决这个问题。

于 2012-07-09T15:03:59.290 回答
0

首先,您需要确定(图顶部)/(最大数据点)的范围。您将下限设为 1.05;合理的上限可能是 1.1 或 1.15。范围越宽,图表顶部可能出现的空白空间越多,但数字可能越“好”。或者,您可以先选择“niceness”标准,然后选择上述比率至少为 1.05 的最小的足够好的数字。

您还可以通过放松下限来提高间隔的“舒适度”,例如将其降低到 1.02 甚至 1.0。

编辑:回应评论。

要找到一个好的最大尺寸,您必须做的是取最大值加上边距,将其除以间隔数,向上舍入到最接近的“合适”值,然后乘以间隔数。“nice”的合理定义可能是“multiple of 10^(floor(log_10(max value)) - 2)”。对“nice”更宽松的定义将(平均)在顶部给您带来更少的额外利润。

于 2012-07-09T15:06:54.837 回答