Home > Computer Science, Controls > MS Chart Part 3 (Combining Different Chart-Types)

MS Chart Part 3 (Combining Different Chart-Types)

Sometimes you may need to combine two or more different Chart-Types. In this article we go through the stages of creating a composite MS Chart. In this project we make a Pareto function to show how to combine two different chart types in a single ChartArea.

Pareto chart: A Pareto chart, named after Vilfredo Pareto, is a type of chart that contains both bars and a line graph, where individual values are represented in descending order by bars, and the cumulative total is represented by the line (In probability distribution there are two ways to display distribution in chart, PMF (Probability Mass Function) and CDF (Cumulative Distribution Function) that can be used to display both in a single area).
The purpose of the Pareto chart is to highlight the most important among a (typically large) set of factors. In quality control, it often represents the most common sources of defects, the highest occurring type of defect, or the most frequent reasons for customer complaints, and so on. Wilkinson (2006) devised an algorithm for producing statistically-based acceptance limits (similar to confidence intervals) for each bar in the Pareto chart. The Pareto chart is one of the seven basic tools of quality control.

After a short introduction to Pareto Chart, lets start the development by starting a new project from scratch. (The reference is Microsoft MSChart sample project)

Pareto MS Chart

Pareto Chart

ASPX File:

<asp:Chart ID="Chart1" runat="server" Width="412px" Height="296px" BorderlineDashStyle="Solid" Palette="BrightPastel" BackSecondaryColor="White" BackGradientStyle="TopBottom" BorderWidth="2" BackColor="WhiteSmoke" BorderColor="26, 59, 105">

<Legends>

<asp:Legend Enabled="False" IsTextAutoFit="False" Name="Default" BackColor="Transparent" Font="Trebuchet MS, 8.25pt, style=Bold">

</asp:Legend>

</Legends>

<BorderSkin SkinStyle="Emboss"></BorderSkin>

<Series>

<asp:Series Name="Default" BorderColor="180, 26, 59, 105">

</asp:Series>

</Series>

<ChartAreas>

<asp:ChartArea Name="ChartArea1" BorderColor="64, 64, 64, 64" BackSecondaryColor="White" BackColor="Gainsboro" ShadowColor="Transparent" BackGradientStyle="TopBottom">

<AxisY2 IsLabelAutoFit="False" Interval="25">

<LabelStyle Font="Trebuchet MS, 8.25pt, style=Bold" />

</AxisY2>

<AxisY LineColor="64, 64, 64, 64">

<LabelStyle Font="Trebuchet MS, 8.25pt, style=Bold" />

<MajorGrid LineColor="64, 64, 64, 64" />

</AxisY>

<AxisX LineColor="64, 64, 64, 64">

<LabelStyle Font="Trebuchet MS, 8.25pt, style=Bold" />

<MajorGrid LineColor="64, 64, 64, 64" />

</AxisX>

</asp:ChartArea>

</ChartAreas>

</asp:Chart>

In the first section there is only one chart type added to the ChartArea which is a Column Chart namely Default. We add the second chart in the code behind later. I also set some of the appearance properties in asp tag to make it look better.

Code Behind:

protected void Page_Load(object sender, EventArgs e)

{

AfterLoad();

}

private void RandomData(Series series, int numOfPoints)

{

Random rand;

// Use a number to calculate a starting value for

// the pseudo-random number sequence

rand = new Random(5);

// Generate random Y values

for (int point = 0; point < numOfPoints; point++)

{

series.Points.AddY(rand.Next(49) + 1);

}

}

public void AfterLoad()

{

// Number of data points

int numOfPoints = 5;

// Generate rundom data

RandomData(Chart1.Series["Default"], numOfPoints);

// Make Pareto Chart

MakeParetoChart(Chart1, "Default", "Pareto");

// Set chart types for output data

Chart1.Series["Pareto"].ChartType = SeriesChartType.Line;

// set the markers for each point of the Pareto Line

Chart1.Series["Pareto"].IsValueShownAsLabel = true;

Chart1.Series["Pareto"].MarkerColor = Color.Red;

Chart1.Series["Pareto"].MarkerBorderColor = Color.MidnightBlue;

Chart1.Series["Pareto"].MarkerStyle = MarkerStyle.Circle;

Chart1.Series["Pareto"].MarkerSize = 8;

Chart1.Series["Pareto"].LabelFormat = "0.#";  // format with one decimal and leading zero

// Set Color of line Pareto chart

Chart1.Series["Pareto"].Color = Color.FromArgb(252, 180, 65);

}

void MakeParetoChart(Chart chart, string srcSeriesName, string destSeriesName)

{

// get name of the ChartAre of the source series

string strChartArea = chart.Series[srcSeriesName].ChartArea;

// ensure that the source series is a column chart type

chart.Series[srcSeriesName].ChartType = SeriesChartType.Column;

// sort the data in all series by their values in descending order

chart.DataManipulator.Sort(PointSortOrder.Descending, srcSeriesName);

// find the total of all points in the source series

double total = 0.0;

foreach (DataPoint pt in chart.Series[srcSeriesName].Points)

total += pt.YValues[0];

// set the max value on the primary axis to total

chart.ChartAreas[strChartArea].AxisY.Maximum = total;

// create the destination series and add it to the chart

Series destSeries = new Series(destSeriesName);

chart.Series.Add(destSeries);

// ensure that the destination series is either a Line or Spline chart type

destSeries.ChartType = SeriesChartType.Line;

destSeries.BorderWidth = 3;

// assign the series to the same chart area as the column chart is assigned

destSeries.ChartArea = chart.Series[srcSeriesName].ChartArea;

// assign this series to use the secondary axis and set it maximum to be 100%

destSeries.YAxisType = AxisType.Secondary;

chart.ChartAreas[strChartArea].AxisY2.Maximum = 100;

// locale specific percentage format with no decimals

chart.ChartAreas[strChartArea].AxisY2.LabelStyle.Format = "P0";

// turn off the end point values of the primary X axis

chart.ChartAreas[strChartArea].AxisX.LabelStyle.IsEndLabelVisible = false;

double percentage = 0.0;

foreach (DataPoint pt in chart.Series[srcSeriesName].Points)

{

percentage += (pt.YValues[0] / total * 100.0);

destSeries.Points.Add(Math.Round(percentage, 2));

}

}

There isn’t any specific chart type for Pareto; we should make it as a combination of two different chart types called Column and Line which is done in the code behind as described below.

Random():

This function is responsible to make 5 random values between 0 to maximum 49 which is called repeatedly in different sections of the project.

 

AfterLoad():

This method is called in Page_Load event handler which is responsible to handle the whole process. Firstly, it sets 5 random values to Default series which is a column chart type. Next, it calls MakeParetoChart()   (which is described later)to create a second line chart, then, it sets some appearance properties to the new generated series.

MakeParetoChart():

This method is responsible to add the second series called Pareto to the chart area. This series is a line chart for the pareto.

And yes it is over. Hope you found it interesting.
I am looking forward to reading your comments bout this post.

Advertisements
  1. December 21, 2011 at 12:08 pm

    Thank you for this example which has no compiler errors. However, I am confused how to tie it to real data which I’m pulling from SQL database. On your example the only place I see where any data is coming from is the RandomData module which leads me to believe the chart should change every time I run it; however it has the same data. So, instead of just rambling, my question is how do I integrate my real data?

    • December 23, 2011 at 3:51 pm

      That’s great that u find it useful and thanks a lot for your kind remarks.
      I haven’t test it with Datasource property, but the way that I know to add data from a Dataset or any other data sources is to do it explicitly in a loop.
      For instance, have a loop on all rows of a table in a Dataset, then, add the column’s data to the chart.

      Same as:
      DataSet ds = //Get it from database
      for (int count = 0; count < ds.Tables[0].Rows.Count; count++)
      {
      series.Points.AddY(Convert.ToInt32(ds.Tables[0].Rows[count]["Your Column Name"]));
      }

      • December 24, 2011 at 3:20 pm

        The SQL Data Source query is just a “count” query: SELECT HowMalDesig, COUNT(HowMalDesig) AS CntHowMal FROM JRAMS WHERE (WhenDscvr = ‘C’ OR WhenDscvr = ‘D’) AND (MDS = @MDS) GROUP BY MDS, HowMalDesig ORDER BY COUNT(HowMalDesig) DESC. The field names depict the count of “how aircraft parts malfunctioned” in the maintenance history of a particular aircraft. I commented out the guts of your RandomData module and replaced with:

        DataView dv = (DataView)SDS_SelectedJRAMS_PRD.Select(DataSourceSelectArguments.Empty);
        foreach (DataRowView drv in dv)
        {
        series.Points.AddY(drv[“CntHowMal”].ToString());
        }

        That’s all there was to it. Again, thanks so much for posting this. I’m new to .Net Chart control and no telling how long it would have taken me to figure out how to do the Pareto chart since Pareto is not listed as a chart choice.

  2. December 21, 2011 at 1:20 pm

    Nevermind, I got it all figured out and it works beautifully! Thank you so much for taking the time to make this example.

  3. December 24, 2011 at 4:48 pm

    My pleasure. Hope to see you here again 😉

  4. December 29, 2011 at 2:32 pm

    Hey, I need to ask you one last question but it would be easiest to show you. Is there a way I can upload/send you two jpg files?

    In case not, I’ll try to explain: Your method causes the labels of the X axis to contain the sequential count of points; e.g. 1, 2, 3, 4, 5…(to last number). It should contain the field name of each item counted; e.g. (number of defects in) wheels, drive train, engine, transmission, etc. I’ve run the program in debug several times trying to figure out where to restore the field name but no luck so far. Please solve. Thanks!

    • December 29, 2011 at 5:46 pm

      Well, my email is hs_sarshar@yahoo.com, don’t hesitate, send email whenever you like, it’s my pleasure to answer my respected blog readers .
      What I got is that you want to add text to your axises, this is the solution that I use:

      MSChart.Series[“Series1”].Points[i].AxisLabel = “”;

      It adds label to each point of your chart.
      I hope it helps you.

      • December 30, 2011 at 3:47 pm

        That solved it. Thanks!

  5. February 4, 2014 at 10:13 pm

    Hi! I have a problem when a I use XY points labels in different series chart type because the column labels points overlaps the line labels points. Do you know any solution?
    These are my results…
    http://es.tinypic.com/r/25z321g/8
    http://es.tinypic.com/r/wlyp3o/8

  1. No trackbacks yet.

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

%d bloggers like this: