根据图表中的文件生成趋势线

时间:2018-07-10 09:35:53

标签: c# winforms charts

我希望能够从文件夹中提取.csv个文件并将其绘制在图表中。

当前,我只是保存文件并显示单个曲线,如下所示:

RunTest函数:

public List<Tuple<double,double>> runTest()
{
    _dpg = new Root(this, "english", false);
    _dpg.Init();
    var filename = "Dpg10Export_" + DateTime.Now.ToString("yyyyMMdd_HHmm") + ".csv";
    List<Tuple<double, double>> results = new List<Tuple<double, double>>();

    var measurement = new Measurement();
    var resultCode = RunMeasurement(60, 1000, 2200, ref measurement, null /* TODO: ref ProgressBar? */);

    using (var fileStream = new StreamWriter(filename))
    {
        var count = measurement.I_inc_Values.Count;

        for (var i = 0; i < count; i++)
        {
            var item = measurement.I_inc_Values[i + 1];
            var current = (float)Convert.ToDouble(item);

            item = measurement.LI_inc_Values[i + 1];
            var inductance = (float)Convert.ToDouble(item);

            var line = current.ToString() + ";" + inductance.ToString() + ";";

            fileStream.WriteLine(line); 
            currentList.Add(current);
            inductanceList.Add(inductance);
            results.Add(new Tuple<double, double>(current,inductance));
            if (i == 0 || (i + 1) % 32 == 0)
            {
                Console.WriteLine((i + 1) + ": " + line);
            }
        }
    }
    return results;
}

此代码将生成一个如下所示的csv文件:

0,22 | 0,44

0,32 | 0,54

0,44 | 0,65

这些值产生一条看起来像这样的曲线:

image

单击“获取波形”按钮时,将生成上面的曲线。但是,我想显示所有已生成的曲线以及趋势线。我将如何实现?

void BindData(List<Tuple<double,double>> results)
{
    chart.Series.Clear();
    var series1 = new System.Windows.Forms.DataVisualization.Charting.Series
    {
        Name = "curr/induc",
        Color = System.Drawing.Color.Green,
        IsVisibleInLegend = true,
        IsXValueIndexed = true,
        ChartType = SeriesChartType.Line                
    };

    foreach (var i in results)
    {
        series1.Points.AddXY(i.Item2,i.Item1);
    }

    chart.Invalidate();
    chart.Series.Add(series1);
}

private void getWaveformBtn_Click(object sender, EventArgs e)
{
    Dpg10Client.Dpg10Settings settings  = new Dpg10Client.Dpg10Settings();
    Dpg10Instrument hej                 = new Dpg10Instrument(settings);
    List<Tuple<double,double>> results  = hej.runTest();
    double current, inductance;

    foreach(var i in results)
    {
        current = i.Item1;
        inductance = i.Item2;
        textBoxWaveformInput.Text += current.ToString() + inductance.ToString();
    }
    BindData(results);         
}

TL; DR

解析来自CSV文件的信息以生成曲线,并基于这些文件创建趋势线。

标记为重复:该答案是关于一条直线的,这些值可能会在曲线中波动。

1 个答案:

答案 0 :(得分:2)

有很多方法可以解决问题中的大多数问题。

让我只处理实际上与计算多个系列的平均值有关的一个问题,即不会处理使用CSV文件中的数据创建系列。

有一个内置的类可以执行financialstatistical的各种高级数学,但是我没有找到一个可以帮助创建平均线/曲线的类。一个以上的系列。

所以让我们自己做吧。

第一个问题是,要计算平均值,我们不仅需要数据,还必须将数据(即x值)分组“ bins” 中,我们想要得到平均值。

除非已经将数据进行了分组,例如因为它们每天每个系列只有一个值,所以我们需要创建这样的组。

让我们首先收集我们要处理的所有系列中的所有点;您可能需要调整循环以仅包含系列序列。.

var allPoints = new List <DataPoint>();
for (int s = 0; s < 3; s++)  // I know I have created these three series
{
    Series ser = chartGraphic.Series["S" + (s+1)];
    allPoints.AddRange(ser.Points);
}

接下来,我们需要确定bin范围/大小,即确定哪些x值应属于同一bin /组的值。我选择有10个垃圾箱。

因此,我们最好获得x值的总范围,然后除以所需的bin数。.

double xmax = allPoints.Max(x => x.XValue);
double xmin = allPoints.Min(x => x.XValue);
int bins = 10;
double groupSize = (xmax - xmin) / (bins - 1);

接下来,我们进行实际的数学计算;为此,我们订购我们的积分,对其进行分组,并为每个分组集选择平均值。.

var grouped = allPoints
                .OrderBy(x => x.XValue)
                .GroupBy(x => groupSize * (int)(x.XValue /groupSize ))
                .Select(x => new { xval = x.Key, yavg = x.Average(y => y.YValues[0]) })
                .ToList();

现在,我们可以将它们添加到新系列中,以在箱中显示平均值:

 foreach (var kv in grouped) avgSeries.Points.AddXY(kv.xval + groupSize/2f, kv.yavg);

我将平均点放在垃圾箱的中心。

这里是一个例子:

enter image description here

该示例的一些注意事项:

平均行并没有显示出真正的“趋势”,因为我的数据几乎是随机的。

我已将Markers添加到所有系列中,以使DataPoints脱颖而出。这是我为平均值系列所做的操作:

avgSeries.MarkerStyle = MarkerStyle.Cross;
avgSeries.MarkerSize = 7;
avgSeries.BorderWidth = 2;

我添加了StripLine来显示垃圾箱。方法如下:

StripLine sl = new StripLine();
sl.BackColor = Color.FromArgb(44,155,155,222);
sl.StripWidth = groupSize;
sl.Interval = groupSize * 2;
sl.IntervalOffset = chartGraphic.ChartAreas[0].AxisX.IntervalOffset;
chartGraphic.ChartAreas[0].AxisX.StripLines.Add(sl);

我还设置了一个极低值-300的点,以说明这将如何拉低bin中的平均值。为了使图表仍以正常数据范围为中心,我在y轴上添加了ScaleBreakStyle

chartGraphic.ChartAreas[0].AxisY.ScaleBreakStyle.BreakLineStyle = BreakLineStyle.Wave;
chartGraphic.ChartAreas[0].AxisY.ScaleBreakStyle.Enabled = true;