public void Test_LinearRegression_RandomXs() { int pointCount = 50; double actualSlope = 3; double actualOffset = 200; (double[] xs, double[] ys) = GetNoisyLinearData_RandomlySpaced(pointCount, actualSlope, actualOffset); // fit the random data with the linear regression model var model = new ScottPlot.Statistics.LinearRegressionLine(xs, ys); // plot to visually assess goodness of fit var plt = new ScottPlot.Plot(450, 300); plt.Title($"Y = {model.slope:0.0000}x + {model.offset:0.0}\nR² = {model.rSquared:0.0000}"); plt.AddScatterPoints(xs, ys); // ADD THIS BACK IN! //plt.PlotLine(model.slope, model.offset, (xs.Min(), xs.Max()), lineWidth: 2, label: "model", lineStyle: ScottPlot.LineStyle.Dash); //plt.PlotLine(actualSlope, actualOffset, (xs.Min(), xs.Max()), lineWidth: 2, label: "actual"); plt.Legend(); TestTools.SaveFig(plt); // ensure the fit is good Assert.AreEqual(actualSlope, model.slope, .5); Assert.AreEqual(actualOffset, model.offset, 10); }
public void GetCoefficients_FirstXNotZero_ResultEqualtoTI_84_Plus() { double[] x = new double[] { 1, 2, 3, 4, 5, 6, 7 }; double[] y = new double[] { 2, 2, 3, 3, 3.8, 4.2, 4 }; var reg = new ScottPlot.Statistics.LinearRegressionLine(x, y); Assert.AreEqual(0.4, reg.slope, 0.0001); Assert.AreEqual(1.5428, reg.offset, 0.0001); }
public void ExecuteRecipe(Plot plt) { // Create some linear but noisy data double[] ys = DataGen.NoisyLinear(null, pointCount: 100, noise: 30); double[] xs = DataGen.Consecutive(ys.Length); double x1 = xs[0]; double x2 = xs[xs.Length - 1]; // use the linear regression fitter to fit these data var model = new ScottPlot.Statistics.LinearRegressionLine(xs, ys); // plot the original data and add the regression line plt.Title($"Y = {model.slope:0.0000}x + {model.offset:0.0}\nR² = {model.rSquared:0.0000}"); plt.AddScatter(xs, ys, lineWidth: 0); plt.AddLine(model.slope, model.offset, (x1, x2), lineWidth: 2); }
private void CreateScatterAndFitRegression() { Random rand = new Random(); // generate linear data with noise double slope = rand.Next(-1000, 1000) / 100.0; double offset = rand.Next(-1000, 1000); int pointCount = rand.Next(50, 1000); double[] ys = ScottPlot.DataGen.NoisyLinear( rand: rand, pointCount: pointCount, slope: slope, offset: offset, noise: rand.Next(10, 500) ); // create matching X-axis ticks double pointSpacing = rand.Next(1, 1000) / 1000.0; double[] xs = ScottPlot.DataGen.Consecutive(ys.Length, spacing: pointSpacing); realLineLabel.Text = string.Format("Y = {0:0.00}x + {1:0.00} (n={2})", slope / pointSpacing, offset, pointCount); // plot data formsPlot1.plt.Clear(); formsPlot1.plt.PlotScatter(xs, ys, lineWidth: 0); formsPlot1.plt.AxisAuto(); // perform the linear regression var linreg = new ScottPlot.Statistics.LinearRegressionLine(xs, ys); double fittedSlope = linreg.slope; fittedLineLabel.Text = string.Format("Y = {0:0.00}x + {1:0.00}", fittedSlope, linreg.offset); // plot the linear regression line (as a scatter plot with just two points) double x1 = xs.First(); double x2 = xs.Last(); double y1 = linreg.GetValueAt(xs.First()); double y2 = linreg.GetValueAt(xs.Last()); formsPlot1.plt.PlotLine(x1, y1, x2, y2, lineWidth: 3, color: Color.Black); // force a redraw of the user control formsPlot1.Render(); }
public void Test_LinearRegression_EvenlySpacedXs() { Random rand = new Random(0); for (int i = 0; i < 1000; i++) { // create random data (double slope, double offset, double[] xs, double[] data) = GetRandomRegressionData(rand); // fit the random data with the linear regression model var model = new ScottPlot.Statistics.LinearRegressionLine(data, 0, 1); // ensure the model's coeffecients are similar to the real ones double slopeError = Math.Abs(slope - model.slope); double offsetError = Math.Abs(offset - model.offset); Assert.That(slopeError, Is.LessThan(.1)); Assert.That(offsetError, Is.LessThan(10)); } }
public void Render(Plot plt) { // Create some linear but noisy data Random rand = new Random(0); double[] ys = ScottPlot.DataGen.NoisyLinear(rand, pointCount: 100, noise: 30); double[] xs = ScottPlot.DataGen.Consecutive(ys.Length); double x1 = xs[0]; double x2 = xs[xs.Length - 1]; // use the linear regression fitter to fit these data var model = new ScottPlot.Statistics.LinearRegressionLine(xs, ys); double y1 = model.GetValueAt(x1); double y2 = model.GetValueAt(x2); // plot the original data and add the regression line plt.PlotScatter(xs, ys, lineWidth: 0, label: "original data"); plt.PlotLine(x1, y1, x2, y2, lineWidth: 3, label: "linear regression"); plt.Legend(); plt.Title(model.ToString()); }
private void formsPlot1_Load(object sender, EventArgs e) { // this is the plotting place - all in the Load // string tname1 = "WXROVER"; // string tname2 = "WXIN"; // int pointcount = 5000; // double[,] tempData; int cnt = 0; // double[] t1 = new double[Globals.pointcount]; // double[] t2 = new double[Globals.pointcount]; // a couple of local lists List <double> orgs = new List <double> { }; List <double> chks = new List <double> { }; classWXstnChk WXchk = new classWXstnChk(); //make an object WXck WXchk.cnxstring("192.168.1.15", "DAWES_SQL2008", "WeatherStation", "WeatherStation", "Esp32a.b."); //a constructor - no arguments //go get the data Globals.tempData = WXchk.getTemperatureData(Globals.pointcount, Globals.tname1, Globals.tname2); //this gets the data as an XY pair //there will be a lot of duplcates in this array. Lets remove the dupes - done in the SQL //for scotterplot to work, these need to be in two separate Arrays, so we seperate them out in //this loop and we might as well get rid of the empty slots //maybe this would also work // double [] tab1 = new double[tempData.Length]; for (int i = 0; i < pointcount - 1; i++) { if (Globals.tempData[i, 0] > 0) { t1[i] = tempData[i, 0]; t2[i] = tempData[i, 1]; t1qq[i] = tempData[i, 0]; t2qq[i] = tempData[i, 1]; //might as well put the data in the grid dgXY.Rows.Add(); try { dgXY.Rows[i].Cells["dgXYrecord"].Value = i.ToString(); //puts the record no on the dgXY dgXY.Rows[i].Cells["dgXYx"].Value = t1[i]; dgXY.Rows[i].Cells["dgXYy"].Value = t2[i]; } catch { } cnt += 1; } }//end of for loop // we have two arrays lets sort them to form a QQ plot Array.Sort(t1qq); Array.Sort(t2qq); // the arrays are declared a certain size and are now full of 0's //this will reduce them down to just data. // if there is no data in the arrays then cnt will = 0 if (cnt == 0) { MessageBox.Show("No Data in your selection.", "No data", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } Array.Resize(ref t1, cnt); Array.Resize(ref t2, cnt); cntG = cnt; // int aa = cnt; int ab = t2.GetLength(0); // create a Population object from the data var popt1 = new ScottPlot.Statistics.Population(t1); var popt2 = new ScottPlot.Statistics.Population(t2); // now lets fill the stats box lblT1.Text = tname1; lblT2.Text = tname2; lblMeanT1.Text = Math.Round(popt1.mean, 2).ToString(); lblMeanT2.Text = Math.Round(popt2.mean, 2).ToString(); lblMedT1.Text = Math.Round(popt1.median, 2).ToString(); lblMedT2.Text = Math.Round(popt2.median, 2).ToString(); lblQ3T1.Text = popt1.Q3.ToString(); lblq3table2.Text = popt1.Q3.ToString(); lblQ1t1.Text = popt1.Q1.ToString(); lblQ1T2.Text = popt2.Q1.ToString(); lblstderrT1.Text = Math.Round(popt1.stdErr, 2).ToString(); lblstderrT2.Text = Math.Round(popt2.stdErr, 2).ToString(); lblstdevT1.Text = Math.Round(popt1.stDev, 2).ToString(); lblstdevT2.Text = Math.Round(popt2.stDev, 2).ToString(); lblIQRt1.Text = Math.Round(popt1.IQR, 2).ToString(); lblIQRt2.Text = Math.Round(popt2.IQR, 2).ToString(); lblNtn1.Text = cnt.ToString(); //opt1.aa.ToString(); // lblNtn2.Text = ab.ToString(); // popt2.count.ToString(); //this gives us the regression line and the correlation coeficient var model = new ScottPlot.Statistics.LinearRegressionLine(t1, t2); string line = $"Y={model.slope:0.0000}X + {model.offset:0.0}"; lblLine.Text = line; lblCorrel.Text = $"R² = {model.rSquared:0.0000}"; formsPlot1.plt.Title($"ScarpWeather Temperature XY Plot"); formsPlot1.plt.XLabel(tname1); formsPlot1.plt.YLabel(tname2); //formsPlot1.plt.AxisAuto(horizontalMargin: 0, verticalMargin: 0.5); // xmin,xmax,ymin,ymax int axisMin, axisMax; axisMin = (int)popt1.min - 2; //get some data from the arrays //axisMin = 0; axisMax = (int)popt1.max + 2; formsPlot1.plt.Axis(axisMin, axisMax, axisMin, axisMax); //defines the min and max of the chart // formsPlot1.plt.Axis(15,40,15,40); formsPlot1.plt.Legend(); // got ot have this be we toggle it with hte context menu //this draws the scatter plot XYplotPoints = formsPlot1.plt.PlotScatter(t1, t2, Color.DarkCyan, lineWidth: 0, markerSize: 5, label: "XYData"); //draw the QQ plot QQplotPoints = formsPlot1.plt.PlotScatter(t1qq, t2qq, Color.DarkGreen, lineWidth: 0, markerSize: 5, label: "QQData"); QQplotPoints.visible = false; // draws the regresion line //if (plotRegression) regLine = formsPlot1.plt.PlotLine(model.slope, model.offset, (axisMin, axisMax), lineWidth: 2, label: "Regression", color: Color.BlueViolet); //plot a 45 degree line = X=Y XequalsYLine = formsPlot1.plt.PlotLine(1.0, 0.0, (0, 100), Color.Goldenrod, lineWidth: 2, label: "X=Y", lineStyle: ScottPlot.LineStyle.Dot); //uses the equation of the line to plot //the 10% error lines errorLineA = formsPlot1.plt.PlotLine(0, 0, 100.0 - 0.1 * 100, 100, color: Color.OrangeRed, lineWidth: 2, label: "10%error", lineStyle: ScottPlot.LineStyle.Dash); errorLineB = formsPlot1.plt.PlotLine(0, 0, 100, 100.0 - 0.1 * 100, color: Color.OrangeRed, lineWidth: 2, lineStyle: ScottPlot.LineStyle.Dash); formsPlot1.Render();//draw the chart on the PC screen }//end function
public void RenderPlot() { plotFrame.plt.Clear(); RefreshTitleAndAxis(false); bool containsDateAxis = false; foreach (PlotParameters curr in ((App)App.Current).GetSeries()) { if (curr.drawSettings.label == "") { curr.drawSettings.label = null;//Prevents it from showing up in the legend } if (curr.drawSettings.dateXAxis) { containsDateAxis = true; object timeUnit; object numTimeUnitsObj; curr.metaData.TryGetValue("timeUnit", out timeUnit); curr.metaData.TryGetValue("numTimeUnits", out numTimeUnitsObj); ScottPlot.Config.DateTimeUnit dateTimeUnit = (ScottPlot.Config.DateTimeUnit)timeUnit; int numTimeUnits = (int)numTimeUnitsObj; dateUnit = dateTimeUnit; dateUnitSpacing = numTimeUnits; if (dateTimeUnit == ScottPlot.Config.DateTimeUnit.Year)//Grid spacing of one year is currently unsupported -_- { plotFrame.plt.Grid(xSpacing: 12, xSpacingDateTimeUnit: ScottPlot.Config.DateTimeUnit.Month); } else { plotFrame.plt.Grid(xSpacing: numTimeUnits, xSpacingDateTimeUnit: dateTimeUnit); } plotFrame.plt.Ticks(dateTimeX: true, xTickRotation: 30, fontSize: 10); // Default fontSize is 12 } switch (curr.drawSettings.type) { case PlotType.scatter: double[] xsScatter = ((double[][])curr.data)[0]; double[] ysScatter = ((double[][])curr.data)[1]; if (logAxis) { ysScatter = ScottPlot.Tools.Log10(ysScatter); } if (!curr.hasErrorData) { plotFrame.plt.PlotScatterHighlight(xsScatter, ysScatter, curr.drawSettings.colour, curr.drawSettings.drawLine ? 1 : 0, label: curr.drawSettings.label, markerShape: curr.drawSettings.markerShape, highlightedColor: curr.drawSettings.colour); } else { double[] errorX = ((double[][])curr.errorData)[0]; double[] errorY = ((double[][])curr.errorData)[1]; plotFrame.plt.PlotScatterHighlight(xsScatter, ysScatter, curr.drawSettings.colour, curr.drawSettings.drawLine ? 1 : 0, label: curr.drawSettings.label, markerShape: curr.drawSettings.markerShape, errorX: errorX, errorY: errorY, highlightedColor: curr.drawSettings.colour); } if (curr.drawSettings.drawLinearRegression) { var model = new ScottPlot.Statistics.LinearRegressionLine(xsScatter, ysScatter); double x1 = xsScatter[0]; double x2 = xsScatter[xsScatter.Length - 1]; double y1 = model.GetValueAt(x1); double y2 = model.GetValueAt(x2); plotFrame.plt.PlotLine(x1, y1, x2, y2, lineWidth: 3, label: $"ŷ = {model.offset:f9} + {model.slope:f9}x"); } break; case PlotType.signal: object sampleRate = 100; curr.metaData.TryGetValue("sampleRate", out sampleRate); object xOffset = 0; curr.metaData.TryGetValue("xOffset", out xOffset); double[] data = (double[])curr.data; if (logAxis) { data = ScottPlot.Tools.Log10(data); } plotFrame.plt.PlotSignalConst(data, (double)sampleRate, (double)xOffset, color: curr.drawSettings.colour, lineWidth: curr.drawSettings.drawLine ? 1 : 0, label: curr.drawSettings.label, markerSize: 0); break; case PlotType.bar: double[] xsBar = ((double[][])curr.data)[0]; double[] ysBar = ((double[][])curr.data)[1]; if (logAxis) { ysBar = ScottPlot.Tools.Log10(ysBar); } if (!curr.hasErrorData) { plotFrame.plt.PlotBar(xsBar, ysBar, fillColor: curr.drawSettings.colour, outlineColor: curr.drawSettings.colour, errorColor: curr.drawSettings.colour, label: curr.drawSettings.label); } else { double[] errorY = ((double[])curr.errorData); plotFrame.plt.PlotBar(xsBar, ysBar, fillColor: curr.drawSettings.colour, outlineColor: curr.drawSettings.colour, errorColor: curr.drawSettings.colour, label: curr.drawSettings.label, errorY: errorY); } break; case PlotType.histogram: ScottPlot.Statistics.Histogram histogram = new ScottPlot.Statistics.Histogram((double[])curr.data); double[] yData = histogram.counts; switch (curr.drawSettings.histogramType) { case HistogramType.fraction | HistogramType.density: yData = histogram.countsFrac; break; case HistogramType.fraction | HistogramType.cumulative: yData = histogram.cumulativeFrac; break; case HistogramType.count | HistogramType.cumulative: yData = histogram.cumulativeCounts; break; } plotFrame.plt.PlotBar(histogram.bins, yData, fillColor: curr.drawSettings.colour, outlineColor: curr.drawSettings.colour, errorColor: curr.drawSettings.colour, label: curr.drawSettings.label); break; case PlotType.horizontal_line: double hLineData = (double)curr.data; plotFrame.plt.PlotHLine(hLineData, color: curr.drawSettings.colour, label: curr.drawSettings.label); break; case PlotType.vertical_line: double vLineData = (double)curr.data; plotFrame.plt.PlotVLine(vLineData, color: curr.drawSettings.colour, label: curr.drawSettings.label); break; case PlotType.horizontal_span: (double hSpanMin, double hSpanMax) = (ValueTuple <double, double>)curr.data; plotFrame.plt.PlotHSpan(hSpanMin, hSpanMax, color: curr.drawSettings.colour, label: curr.drawSettings.label); break; case PlotType.vertical_span: (double vSpanMin, double vSpanMax) = (ValueTuple <double, double>)curr.data; plotFrame.plt.PlotVSpan(vSpanMin, vSpanMax, color: curr.drawSettings.colour, label: curr.drawSettings.label); break; case PlotType.box_whisker: var plotObj = plotFrame.plt.PlotPopulations((ScottPlot.Statistics.Population)curr.data, label: curr.drawSettings.label); plotObj.boxStyle = PlottablePopulations.BoxStyle.BoxMedianQuartileOutlier; plotObj.displayDistributionCurve = false; break; case PlotType.function: var f = (Func <double, double?>)curr.data; plotFrame.plt.PlotFunction(f, label: curr.drawSettings.label, markerShape: MarkerShape.none, lineStyle: LineStyle.Dash); break; case PlotType.bar_grouped: var plotData = ((double[][])curr.data); string[] groupLabels = (string[])curr.metaData.GetValueOrDefault("group_names"); string[] seriesLabels = (string[])curr.metaData.GetValueOrDefault("series_names"); if (!curr.hasErrorData) { plotFrame.plt.PlotBarGroups(groupLabels, seriesLabels, plotData); } else { plotFrame.plt.PlotBarGroups(groupLabels, seriesLabels, plotData, (double[][])curr.errorData); } break; } } isDateAxis = containsDateAxis; plotFrame.plt.Legend(); (double highlightX, double highlightY) = (plotFrame.plt.Axis()[0], plotFrame.plt.Axis()[3]); foreach (var curr in rawPlottables) { if (curr != snappedCoordinates || showCoordinates) { plotFrame.plt.Add(curr);//Got axed when we cleared everything } } RenderFrame(); }