从图表中的文件生成趋势线
我希望能够从文件夹中获取.csv
文件并将其绘制在图表中。
目前,我只是保存文件并显示如下的单个曲线:
RunTest函数:
public List<Tuple> runTest() { _dpg = new Root(this, "english", false); _dpg.Init(); var filename = "Dpg10Export_" + DateTime.Now.ToString("yyyyMMdd_HHmm") + ".csv"; List<Tuple> results = new List<Tuple>(); 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(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
这些值产生的曲线如下所示:
单击“获取波形”按钮时,将生成上面的曲线。 但是,我想显示已生成的所有曲线,以及趋势线 。 我怎么做到这一点?
void BindData(List<Tuple> 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> 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
文件中的信息以生成曲线,并基于这些文件创建趋势线。
标记为重复:该答案是关于直线的,这些值可以在曲线中波动。
有很多方法可以解决您问题中的大多数问题。
让我只解决与计算多个系列的平均值有关的实际问题,即不处理使用CSV文件中的数据创建系列。
有一个内置的类可以做各种高级数学,包括财务和统计 ,但我没有找到一个有助于创建一个以上系列的平均线/曲线。
所以让我们自己做吧..
第一个问题是,为了计算平均值,我们不仅需要数据,而且数据(即它们的x值)必须分组为“箱” ,我们希望从中获得平均值。
除非数据已经按这样分组,例如因为每天每个系列有一个值,我们需要创建这样的组。
让我们先收集我们想要处理的所有系列中的所有积分; 你可能需要调整循环以包括你的系列..:
var allPoints = new List (); 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 / group的值。 我选择了10箱。
所以我们最好得到x值的总范围并除以我们想要的箱数...:
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);
我将平均点放在箱子中心。
这是一个例子:
关于这个例子的几点说明:
平均线没有显示真正的“趋势”,因为我的数据几乎是随机的。
我已经将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
的非常低值,以certificate它将如何降低其箱中的平均值。 为了使图表仍然很好地以正常的数据范围为中心,我将一个ScaleBreakStyle
添加到y轴:
chartGraphic.ChartAreas[0].AxisY.ScaleBreakStyle.BreakLineStyle = BreakLineStyle.Wave; chartGraphic.ChartAreas[0].AxisY.ScaleBreakStyle.Enabled = true;