从图表中的文件生成趋势线 [英] generate a trendline from files in a chart

查看:64
本文介绍了从图表中的文件生成趋势线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望能够从文件夹中提取 .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>>结果=新List< Tuple< double,double>>();

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

使用(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);

项=测量值。LI_inc_Values[i + 1];
var电感=(float)Convert.ToDouble(item);

var line = current.ToString()+; +电感.ToString()+;;

fileStream.WriteLine(line);
currentList.Add(current);
电感List.Add(电感);
结果。添加(新元组< double,double>(电流,电感));
if(i == 0 ||(i + 1)%32 == 0)
{
Console.WriteLine((i + 1)+: + line);
}
}
}
返回结果;
}

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



0.22 | 0,44



0,32 | 0,54



0,44 | 0,65



这些值会产生如下所示的曲线:





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

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

foreach(结果中的变量i)
{
series1.Points.AddXY(i.Item2,i.Item1);
}

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

私人无效getWaveformBtn_Click(对象发送者,EventArgs e)
{
Dpg10Client.Dpg10Settings settings = new Dpg10Client.Dpg10Settings();
Dpg10Instrument hej =新的Dpg10Instrument(设置);
List< Tuple< double,double>>结果= hej.runTest();
双倍电流,电感;

foreach(结果中为var i)
{
current = i.Item1;
电感= i.Item2;
textBoxWaveformInput.Text + = current.ToString()+电感.ToString();
}
BindData(结果);
}

TL; DR



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



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

解决方案

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



我只处理实际上与计算多个系列的平均值有关的一个,即不会处理创建带有数据来自CSV文件。



有一个内置的类可以执行各种高级数学运算,



该示例的一些注意事项:



由于我的数据几乎是随机的,所以平均行不显示真实的趋势。



我向所有系列添加了 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;


I want to be able to fetch .csv files from a folder and plot them up in a chart.

Currently, I'm just saving the files and displaying an individual curve like this:

RunTest function:

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;
}

This code produces a csv-file that looks something like this:

0,22 | 0,44

0,32 | 0,54

0,44 | 0,65

And those values produce a curve that looks like this:

When you click on the "get Waveform" button, the curve above is generated. However, I want to display all the curves that has been generated, and a trendline as well. How would I achieve this?

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

Parse the information from the CSV files to generate curves, and create a trendline based on those files.

Marked as duplicate: That answer is regarding a straight line, these values can fluctuate in a curve.

解决方案

There are many ways to solve most of the various problems in your question.

Let me tackle only the one that actually has to do with calculating an average from multiple series, i.e. will not deal with creating a Series with data from a CSV file.

There is a built-in class that can do all sorts of advanced math, both financial and statistical, but I didn't find one that will help in creating an average line/curve over more than one series.

So let's do it ourselves..

The first issue is that to calculate averages we need not just data but the data, that is their x-values, must be grouped into 'bins' from which we want to get the averages.

Unless the data already are grouped like that, e.g. because they have one value per series per day, we need to create such groups.

Let's first collect all the points from all series we want to handle; you may need to adapt the loop to include just your set of series..:

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);
}

Next we need to decide on a bin range/size, that is a value that determines which x-values shall fall into the same bin/group. I chose to have 10 bins.

So we best get the total range of the x-values and divide by the number of bins we want..:

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

Next we do the actual math; for this we order our points, group them and select the average for each grouped set..:

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();

Now we can add them to a new series to display the averages in the bins:

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

I center the average point in the bins.

Here is an example:

A few notes on the example:

The average line doesn't show a real 'trend' because my data are pretty much random.

I have added Markers to all series to make the DataPoints stand out from the lines. Here it is how I did it for the averages series:

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

I have added a StripLine to show the bins. Here is how:

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);

I have also set one point to have a really low value of -300 to demonstrate how this will pull down the average in its bin. To keep the chart still nicely centered on the normal range of data I have added a ScaleBreakStyle to the y-axis:

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

这篇关于从图表中的文件生成趋势线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆