There are many cases when the data to be plotted must be analyzed considering multiple variables, for example you might want to track sales of multiple products in multiple regions and encompassing multiple years. Let’s assume our data layer looks like this
public class ProductSalesInfo
{
public double Sales { get; set; }
public string Region { get; set; }
public DateTime Date { get; set; }
public string Product { get; set; }
public int Year
{
get { return Date.Year; }
}
public int Month
{
get { return Date.Month; }
}
public string MonthName
{
get { return Date.ToString("MMM"); }
}
}
We have added some helper properties (Year, Month and MonthName) as these will help us setting up our bindings. Our first approach to the problem includes using the crosstab data transform to make sure Chart FX plots one series per each unique combination of variables.
<cfx:Chart Gallery="Line" x:Name="chart1" Style="{x:Static cfxMotifs:Basic.Style}">
<cfx:Chart.DataTransforms>
<cfxData:CrosstabTransform x:Name="crosstab1"
RowPath="Month" ColumnPath="Region,Product,Year"
ValuePath="Sales" />
</cfx:Chart.DataTransforms>
</cfx:Chart>
As promised, we got a series per variable combination but it would be very difficult to detect trends in this picture, what we need is to layout multiple panes in such a way that each column in our grid represents a region and each row represents a product. Although we include a GridPanePanel as a way to layout multiple panes inside the chart, it has no knowledge about the nature of the data so it will just calculate a “round” number of rows and columns to accommodate the total number of panes. Also note that we do not sell ABC Widgets in Asia but if we want to create a matrix we will need to make sure we account for this.
To help in this common scenario we have added some properties to CrosstabTransform, the most important one is a Boolean property called JoinOnColumns, when set to true, Crosstab will make sure that the series combinations are such that they can be easily plotted in a matrix, so it will add fake series where needed and also make sure that the ordering of the series is always the same. Crosstab also exposes a Dimensions property that allows you to query for each dimension found in the data, i.e. you can get a list of all the regions, products and years in your dataset.
This chart will give you a better way to spot trends for a particular product or region. The labels for the columns and rows were achieved querying the Crosstab Dimensions on the DataBound chart event and using the GridPanePanel ColumnDefinitions and RowDefinitions collections. We have also removed the gridlines to reduce clutter. We have also hidden the series from the legend box and created a couple of custom legend items that show our third series dimension (year).
In this sample there is a potential problem, crosstab goes through the data and each time it finds a new Row (in this case a new Month) it adds it to a list but it will not order this list by default, this means that if the first element in your data is a sale in March this will become the first “row” so the X axis will show the months out of order, although you could maybe workaround this by making sure your data is ordered by month we have added a SortRows property that will take care of this for you, this also means we have made a Sorted property obsolete and replaced it with a hopefully more descriptive name SortColumns.
Additionally we have added a RowIDPath property which allows you to sort your rows using the Month index but show the Month Name in your axis.
<cfx:Chart.DataTransforms>
<cfxData:CrosstabTransform x:Name="crosstab1"
RowIDPath="Month" RowPath="MonthName" SortRows="True"
ColumnPath="Region,Product,Year" JoinOnColumns="True"
ValuePath="Sales" />
</cfx:Chart.DataTransforms>
At this point we have taken care of the X axis which now shows friendlier month abbreviations and will be ordered by month index regardless of the order in the data but we have manipulated our random data to show another issue, sales of “ABC Widget” are in the thousands while “Contoso Tool” sales are in the hundreds and because we are using a single Y axis it is very hard to note any trends in the lower row.
This issue can be solved in two ways, first you could use a different Y axis per row, this will still allow you to focus on a product and compare different regions using the same axis while making sure that each products gets its own Y axis.
Alternatively, you could decide that you want to have a different axis per pane, this will make same-row comparisons more difficult but might be helpful if a product sales varies widely by region. Instead of totally hiding the Y axis we will show only the min and max labels inside the plot area.
We hope this post along with the changes we have made to the crosstab transform will help you create charts where users can analyze the data more effectively, note that you need Chart FX build 3504 or later. The code used to configure these charts was not included in the text of the post to keep it to a manageable size but it is provided as an attachment.
JuanC