Answered by:
How to smooth a noisy Line Graph in C# charting?
Question

Answers

There are a virtually infinite number of filtering methods for smoothing data. It all depends on what you're after. A moving average can do a lot of good; replace each point by the average of the 5 points in its neighborhood. Butterworth and Chebyshev filters are both good at clearing out highfrequency data, which will tend to smooth out the results. If you just have a few wild points, it can be easier just to scan through your data and toss out the odd points.
https://www.centerspace.net/tag/ciirfiltering
However, you do need to understand that the data you get back no longer accurately represents the derivative of your input data. If your input is noisy, then maybe you should be showing the user a noisy plot.
Tim Roberts  Driver MVP Emeritus  Providenza & Boekelheide, Inc.
 Marked as answer by Magesh85 Wednesday, October 9, 2019 9:18 AM
All replies


There are a virtually infinite number of filtering methods for smoothing data. It all depends on what you're after. A moving average can do a lot of good; replace each point by the average of the 5 points in its neighborhood. Butterworth and Chebyshev filters are both good at clearing out highfrequency data, which will tend to smooth out the results. If you just have a few wild points, it can be easier just to scan through your data and toss out the odd points.
https://www.centerspace.net/tag/ciirfiltering
However, you do need to understand that the data you get back no longer accurately represents the derivative of your input data. If your input is noisy, then maybe you should be showing the user a noisy plot.
Tim Roberts  Driver MVP Emeritus  Providenza & Boekelheide, Inc.
 Marked as answer by Magesh85 Wednesday, October 9, 2019 9:18 AM

Hi Magesh85,
Thank you for posting here.
For your question, you want to smooth a noisy Line Graph in C# charting.
I suggest you use Ramer–Douglas–Peucker algorithm to reduce number of points.
I use the algorithm to make a test on my side, and you can refer it.
Here’s the code.
Form1:
List<int> lt = new List<int>(); List<int> lt2 = new List<int>(); List<Point> points = new List<Point>() { new Point(){ year = 1990,value = 100 }, new Point(){ year = 1991,value = 200 } // Add data ... }; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { fillChart(); } private void fillChart() { var series = new Series("Data"); for(int i=0;i<points.Count;i++) { lt.Add(points[i].year); lt2.Add(points[i].value); } series.Points.DataBindXY(lt,lt2); chart1.Series.Add(series); series.ChartType = SeriesChartType.Line; } private void button1_Click(object sender, EventArgs e) { lt.Clear(); lt2.Clear(); chart1.Series.Clear(); List<Point> po = Utility.DouglasPeuckerReduction(points, Convert.ToDouble(numericUpDown1.Value)); for (int i = 0; i < po.Count; i++) { lt.Add(po[i].year); lt2.Add(po[i].value); } var series = new Series("Data"); series.Points.DataBindXY(lt, lt2); chart1.Series.Add(series); series.ChartType = SeriesChartType.Line; }
Point Class:
public class Point { public int year { get; set; } public int value { get; set; } }
Utility Class:
public class Utility { public static List<Point> DouglasPeuckerReduction(List<Point> Points, Double Tolerance) { if (Points == null  Points.Count < 3) return Points; Int32 firstPoint = 0; Int32 lastPoint = Points.Count  1; List<Int32> pointIndexsToKeep = new List<Int32>(); pointIndexsToKeep.Add(firstPoint); pointIndexsToKeep.Add(lastPoint); while (Points[firstPoint].Equals(Points[lastPoint])) { lastPoint; } DouglasPeuckerReduction(Points, firstPoint, lastPoint, Tolerance, ref pointIndexsToKeep); List<Point> returnPoints = new List<Point>(); pointIndexsToKeep.Sort(); foreach (Int32 index in pointIndexsToKeep) { returnPoints.Add(Points[index]); } return returnPoints; } private static void DouglasPeuckerReduction(List<Point> points, Int32 firstPoint, Int32 lastPoint, Double tolerance, ref List<Int32> pointIndexsToKeep) { Double maxDistance = 0; Int32 indexFarthest = 0; for (Int32 index = firstPoint; index < lastPoint; index++) { Double distance = PerpendicularDistance(points[firstPoint], points[lastPoint], points[index]); if (distance > maxDistance) { maxDistance = distance; indexFarthest = index; } } if (maxDistance > tolerance && indexFarthest != 0) { pointIndexsToKeep.Add(indexFarthest); DouglasPeuckerReduction(points, firstPoint, indexFarthest, tolerance, ref pointIndexsToKeep); DouglasPeuckerReduction(points, indexFarthest, lastPoint, tolerance, ref pointIndexsToKeep); } } public static Double PerpendicularDistance(Point Point1, Point Point2, Point Point) { Double area = Math.Abs(.5 * (Point1.year * Point2.value + Point2.year * Point.value + Point.year * Point1.value  Point2.year * Point1.value  Point.year * Point2.value  Point1.year * Point.value)); Double bottom = Math.Sqrt(Math.Pow(Point1.year  Point2.year, 2) + Math.Pow(Point1.value  Point2.value, 2)); Double height = area / bottom * 2; return height; } }
Original value：
The lower the value of numericUpDown1, the closer the points are to the original points:
The higher the value of numericUpDown1, the more points will be deleted by the algorithm:
Hope it can help you.
Best Regards,
Xingyu Zhao
MSDN Community Support
Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.