Posted by: Zeeshan Amjad | September 21, 2009

Creating DotPlot in WPF using C#


Dot plot is a very simple but powerful graphical technique used in Statistics. With the help of Dot plot we can get quick idea about the distribution of the data as well as out liar in the data set.

Here we are going to create the dot plot in WPF with C#. To make a custom panel to draw at exact location. Let’s start with some small utility function that will helpful for us to draw a graph.

Here is our first function to draw a circle at specific location.

  1: private void DrawCircle(int x, int y)
  2: {
  3:     Ellipse ellipse = new Ellipse();
  4:     ellipse.Width = 10;
  5:     ellipse.Height = 10;
  6:     ellipse.Fill = Brushes.Blue;
  7:     Canvas.SetLeft(ellipse, x);
  8:     Canvas.SetTop(ellipse, y);
  9: 
 10:     canvas.Children.Add(ellipse);
 11: }
 12: 

Similarly here is a function to display text at specific location.

  1: private void DrawText(int x, int y, string text)
  2: {
  3:     TextBlock textBlock = new TextBlock();
  4:     textBlock.Text = text;
  5:     Canvas.SetLeft(textBlock, x);
  6:     Canvas.SetTop(textBlock, y);
  7: 
  8:     canvas.Children.Add(textBlock);
  9: }
 10: 

We have to calculate the frequency of each data point in the given data set. We create one class to store not only the data point, but also its frequency. Here is a simple class to store that information.

  1: public class FrequencyInfo
  2: {
  3:     public int dataPoint;
  4:     public int frequency;
  5: }
  6: 

Similarly we store the summary information of data points, such as maximum value, minimum value, maximum frequency etc in one more class.

  1: public class DataSummary
  2: {
  3:     public int MinimumNumber;
  4:     public int MaximumNumber;
  5:     public int MaximumFrequency;
  6: }
  7: 

Here is a  complete C# code to demonstrate the Dot Plot.

  1: using System;
  2: using System.Windows;
  3: using System.Windows.Media;
  4: using System.Windows.Controls;
  5: using System.Windows.Shapes;
  6: using System.Collections.Generic;
  7: 
  8: namespace DotPlot
  9: {
 10:     public class DataSummary
 11:     {
 12:         public int MinimumNumber;
 13:         public int MaximumNumber;
 14:         public int MaximumFrequency;
 15:     }
 16: 
 17:     public class FrequencyInfo
 18:     {
 19:         public int dataPoint;
 20:         public int frequency;
 21:     }
 22: 
 23:     public class DotPlotWindow : Window
 24:     {
 25:         private List<FrequencyInfo> FreqInfoList;
 26:         private DataSummary dataSummary;
 27:         Canvas canvas;
 28: 
 29:         public List<int> DataPoints
 30:         { get; set; }
 31: 
 32:         public DotPlotWindow()
 33:         {
 34:             Title = "Dot Plot";
 35:             Width = 600;
 36:             Height = 400;
 37:             WindowStyle = WindowStyle.ToolWindow;
 38:             ResizeMode = ResizeMode.NoResize;
 39: 
 40:             FreqInfoList = new List<FrequencyInfo>();
 41:             dataSummary = new DataSummary();
 42: 
 43:             canvas = new Canvas();
 44:             canvas.Background = Brushes.AliceBlue;
 45: 
 46:             Content = canvas;
 47:         }
 48: 
 49:         public void DrawGraph()
 50:         {
 51:             if (DataPoints != null)
 52:             {
 53:                 FreqInfoList.Clear();
 54:                 GetFrequencyInfo();
 55:                 GetSummary();
 56: 
 57:                 DrawHorizantalLine();
 58: 
 59:                 int range = dataSummary.MaximumNumber - dataSummary.MinimumNumber;
 60:                 int xdistance = (int)525 / range;
 61:                 int ydistance = 10;
 62:                 const int xstartPosition = 25;
 63:                 const int ystartPosition = 315;
 64: 
 65:                 int xpos = xstartPosition;                
 66: 
 67:                 for (int data = dataSummary.MinimumNumber;
 68:                     data <= dataSummary.MaximumNumber;
 69:                     data++)
 70:                 {
 71:                     int ypos = ystartPosition;
 72:                     DrawText(xpos, ypos + ydistance, data.ToString());
 73: 
 74:                     int pos = IsDataPresent(data);
 75: 
 76:                     if (pos != -1)
 77:                     {
 78:                         for (int i = 0; i < FreqInfoList[pos].frequency; i++)
 79:                         {
 80:                             DrawCircle(xpos, ypos);
 81:                             ypos -= ydistance;
 82:                         }
 83:                     }
 84:                     
 85:                     xpos += xdistance;
 86:                 }                
 87:             }
 88:         }
 89: 
 90:         private void DrawHorizantalLine()
 91:         {
 92:             Line line = new Line();
 93:             line.X1 = 25;
 94:             line.X2 = Width - 50;
 95:             line.Y1 = Height - 75;
 96:             line.Y2 = Height - 75;
 97:             line.Stroke = Brushes.Black;
 98: 
 99:             canvas.Children.Add(line);
100:         }
101: 
102:         private void DrawCircle(int x, int y)
103:         {
104:             Ellipse ellipse = new Ellipse();
105:             ellipse.Width = 10;
106:             ellipse.Height = 10;
107:             ellipse.Fill = Brushes.Blue;
108:             Canvas.SetLeft(ellipse, x);
109:             Canvas.SetTop(ellipse, y);
110: 
111:             canvas.Children.Add(ellipse);
112:         }
113: 
114:         private void DrawText(int x, int y, string text)
115:         {
116:             TextBlock textBlock = new TextBlock();
117:             textBlock.Text = text;
118:             Canvas.SetLeft(textBlock, x);
119:             Canvas.SetTop(textBlock, y);
120: 
121:             canvas.Children.Add(textBlock);
122:         }
123: 
124:         private int IsDataPresent(int data)
125:         {
126:             if (FreqInfoList != null)
127:             {
128:                 int count = FreqInfoList.Count;
129: 
130:                 for (int iIndex = 0; iIndex < count; iIndex++)
131:                 {
132:                     if (FreqInfoList[iIndex].dataPoint == data)
133:                         return iIndex;
134:                 }
135:             }
136: 
137:             return -1;
138:         }
139: 
140:         private void GetFrequencyInfo()
141:         {
142:             int count = DataPoints.Count;
143:             DataPoints.Sort();
144: 
145:             for (int iIndex = 0; iIndex < count; iIndex++)
146:             {
147:                 int dataPosition = IsDataPresent(DataPoints[iIndex]);
148: 
149:                 if (dataPosition == -1)
150:                 {
151:                     FrequencyInfo freqInfo = new FrequencyInfo();
152:                     freqInfo.dataPoint = DataPoints[iIndex];
153:                     freqInfo.frequency = 1;
154: 
155:                     FreqInfoList.Add(freqInfo);
156:                 }
157:                 else
158:                 {
159:                     FreqInfoList[dataPosition].frequency += 1;
160:                 }
161:             }                        
162:         }
163: 
164:         private void GetSummary()
165:         {
166:             dataSummary.MinimumNumber = FreqInfoList[0].dataPoint;
167:             dataSummary.MaximumNumber = FreqInfoList[0].dataPoint;
168: 
169:             foreach (FrequencyInfo fInfo in FreqInfoList)
170:             {
171:                 if (fInfo.dataPoint < dataSummary.MinimumNumber)
172:                     dataSummary.MinimumNumber = fInfo.dataPoint;
173: 
174:                 if (fInfo.dataPoint > dataSummary.MaximumNumber)
175:                     dataSummary.MaximumNumber = fInfo.dataPoint;
176: 
177:                 if (fInfo.frequency > dataSummary.MaximumFrequency)
178:                     dataSummary.MaximumFrequency = fInfo.frequency;
179:             }
180:         }
181:     }
182: 
183:     public class WpfDotPlot
184:     {
185:         [STAThread]
186:         public static void Main()
187:         {
188:             DotPlotWindow dpw = new DotPlotWindow();
189: 
190:             List<int> lst = new List<int>();
191: 
192:             Random random = new Random();
193: 
194:             for (int iIndex = 0; iIndex < 250; ++iIndex)
195:             {                
196:                 lst.Add(random.Next(10, 40));
197:             }
198: 
199:             dpw.DataPoints = lst;
200:             dpw.DrawGraph();
201: 
202:             Application app = new Application();
203:             app.Run(dpw);
204:         }
205:     }
206: }
207: 

This is not a professional level graph application. It just gives proof of concept that how can we make dot plot using the canvas panel.

Because we are generating the data point randomly, therefore its output is different every time we run this application. Here are two output of this program.

DotPlot_01

DotPlot_02

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: