如何在折线图中使辅助Y轴依赖于主Y轴

时间:2015-12-01 15:38:48

标签: c# winforms charts

我对c#很陌生,真的需要完成这项工作。我知道如何将辅助y轴添加到折线图中,但在我的问题中它有点不同。 。我有一个已经有一个x轴和一个y轴的图表。 x轴表示$words = isset($_GET["search"])?trim($_GET["search"], ' '):''; // $words will be set to an empty string in case the search param is not set. ,y轴是与DateTime相关的一些整数值。数据源是一个填充了SQL的阅读器的数据集。我需要在图表中添加第二个y轴,它显示与第一个y轴的每个值相关的系列中有多少个数据点。语言是C#。 以下是代码和结果图像:

DateTime

It shows customLabled with no values!

1 个答案:

答案 0 :(得分:1)

我花了一段时间才明白你想要什么,但我想这可能就是这样:

enter image description here

如果你了解CustomLabels,那就不是很难了。

  • 您计算总和
  • 您将两个y轴同步到相同的比例
  • 您将自定义标签的总和放在正确的位置

此功能可为数据的每个值添加辅助Y-AxisCustomLabels,以显示该值的计数。

当然,这只适用于不同值。我的代码假定integer值,但我想您也可以将其调整为decimals。请注意,它不适用于floatsdoubles!您必须扩展求和代码以设置类似Dictionary<float, int>的内容,而不是简单的array ..

void addSumSeries(Chart chart, Series s)
{
    ChartArea CA = chart1.ChartAreas[0];       // short name

    CA.AxisY2.Enabled = AxisEnabled.True;      // turn on secondary y-axis
    CA.AxisY2.MajorGrid.Enabled = false;       // no grid lines
    CA.AxisY2.MinorTickMark.Enabled = true;    // show tick marks
    CA.AxisY2.Maximum = CA.AxisY.Maximum;      // synch display scale

    // find the maximum value; we'll show all values from 0 to sMax
    int sMax = (int) s.Points.Select(x => x.YValues[0]).Max<double>();  
    double[] sums = new double[sMax + 1];

    for (int i = 0; i < s.Points.Count; i++ )      // loop over data
    {
        int val = (int) s.Points[i].YValues[0];    // get value
        sums[val] += 1;                            // count values
    }

    // now create custom labels: each shows the count..
    // ..and is placed in the middle between the last and the next value
    for (int i = 0; i < sums.Length; i++)
    {
        CustomLabel cl = new CustomLabel();
        cl.Text = sums[i].ToString("###0"); // to get that right you'd need special spaces
        cl.FromPosition = i - 0.5;
        cl.ToPosition = i + 0.5;
        CA.AxisY2.CustomLabels.Add(cl);
    }
}

以下是我设置测试数据的方法:

private void button7_Click(object sender, EventArgs e)
{
    chart1.ChartAreas.Clear();
    chart1.Series.Clear();
    ChartArea CA = chart1.ChartAreas.Add("CA");
    Series S1 = chart1.Series.Add("S1");
    S1.ChartType = SeriesChartType.Point;

    DateTime now = DateTime.Now.Date;
    CA.AxisX.Minimum = now.AddHours(-12).ToOADate();
    CA.AxisY.Maximum = 16;
    // create a few test data with values 1-15
    // every couple of days
    Random R = new Random(1);
    for (int i = 0; i < 150; i++)
    {
        DateTime dt = now.AddDays(R.Next(4)+i);
        S1.Points.AddXY(dt, R.Next(16) );
    }

    // call the function that adds the counting axis:
    addSumSeries(chart1, S1);
}

请注意,在添加(或更改)数据点后,需要进行此计算!

当然它也适用于折线图,但是,至少对我的数据来说,这看起来更酷......

<强>更新

对于数据绑定图表,Points为空。所以我们必须从数据源计算总和。

以下是一些行;他们使用DataTable dt

// convert to a list of rows:
List<DataRow> query = dt.AsEnumerable().ToList();

int sMax = (int)query.Select(x => (int)(x[1])).Max<int>();  // find the maximum value

double[] sums = new double[sMax + 1];
for (int i = 0; i < query.Count(); i++)      // loop over data
    {
        int val = (int)(query[i]["ttkh"]);    // get value
        sums[val] += 1;                       // count values
}

观察图像我应该警告你,计算总和的方式可能会产生多达500个不同的值,每个值都有一个CustomLabel!如果这太过分了,你就不得不考虑变化;也许你可以在10左右的值范围内创建组。

以下是一个例子:

使用变量int groupSize = 10或任何适合您的变量,您可以将求和代码更改为:

 sums[val / groupSize] += 1;     

以及自定义标签的定位和标签:

cl.Text = sums[i].ToString(groupSize * i + " - " +  (groupSize * (i +1) - 1) +  ":  ###0");
cl.FromPosition = i * groupSize - 0.5;
cl.ToPosition = i * groupSize + 0.5;

enter image description here

对于未绑定的图表,您可以为每个ToolTip添加DataPoint,显示Y-Value和相应的计数;但是,对于数据绑定图表,这似乎不可能,只支持ToolTips级别的Series。这些仅限于使用a few keywords,不能按点设置。