How to: Stack several Column Series

This how-to guide shows you how to display your data using several column series which are cumulatively stacked on top of each other. Cumulatively stacked series can be particularly useful for representing data in part to whole relationships, or when you wish to display the whole using a non-ratio unit of measure, but also wish to provide some sense of the relative size of its parts.

In order to create the stacked ColumnSeries, you will need to do the following:

  1. Create a DataAdapter containing your data points.
  2. Create several ColumnSeries, give them your data and set their stacking token to a CumulativeStackingToken which you will also create.
  3. Add the series to the chart.

Creating a Column Series

Within the onCreate method of an Activity, first add a check for savedInstanceState == null:

Java

if (savedInstanceState == null) {

}

C# - Note that the Xamarin generated code uses the name ‘bundle’ for the saved instance state variable

if (bundle == null) {
}

You only want to set the chart up the first time the Activity is created; savedInstanceState will be null in this case. By using a ChartFragment the chart will be retained over configuration changes, such as when the device is rotated.

Now, inside the if statement you just added, create several DataAdapters and add some data to them:

Java

DataAdapter<String, Double> da1 = new SimpleDataAdapter<String, Double>();
da1.add(new DataPoint<String, Double>("q1", 1.0));
da1.add(new DataPoint<String, Double>("q2", 3.0));
da1.add(new DataPoint<String, Double>("q3", 4.5));
da1.add(new DataPoint<String, Double>("q4", -2.5));

DataAdapter<String, Double> da2 = new SimpleDataAdapter<String, Double>();
da2.add(new DataPoint<String, Double>("q1", 1.5));
da2.add(new DataPoint<String, Double>("q2", 3.6));
da2.add(new DataPoint<String, Double>("q3", 5.5));
da2.add(new DataPoint<String, Double>("q4", -3.5));

DataAdapter<String, Double> da3 = new SimpleDataAdapter<String, Double>();
da3.add(new DataPoint<String, Double>("q1", 1.57));
da3.add(new DataPoint<String, Double>("q2", 10.6));
da3.add(new DataPoint<String, Double>("q3", 45.5));
da3.add(new DataPoint<String, Double>("q4", -13.5));

DataAdapter<String, Double> da4 = new SimpleDataAdapter<String, Double>();
da4.add(new DataPoint<String, Double>("q1", 2.57));
da4.add(new DataPoint<String, Double>("q2", 7.6));
da4.add(new DataPoint<String, Double>("q3", 28.5));
da4.add(new DataPoint<String, Double>("q4", -17.5));

C# - Note that the DataAdapter and DataPoint are not generic in the C# code. The Xamarin bindings will perform casting to the internally used Java classes for common types such as String and double, but not DateTime. We provide a static DateUtils class to do this conversion.

DataAdapter da1 = new SimpleDataAdapter();
da1.Add(new DataPoint("q1", 1.0));
da1.Add(new DataPoint("q2", 3.0));
da1.Add(new DataPoint("q3", 4.5));
da1.Add(new DataPoint("q4", -2.5));

DataAdapter da2 = new SimpleDataAdapter();
da2.Add(new DataPoint("q1", 1.5));
da2.Add(new DataPoint("q2", 3.6));
da2.Add(new DataPoint("q3", 5.5));
da2.Add(new DataPoint("q4", -3.5));

DataAdapter da3 = new SimpleDataAdapter();
da3.Add(new DataPoint("q1", 1.57));
da3.Add(new DataPoint("q2", 10.6));
da3.Add(new DataPoint("q3", 45.5));
da3.Add(new DataPoint("q4", -13.5));

DataAdapter da4 = new SimpleDataAdapter();
da4.Add(new DataPoint("q1", 2.57));
da4.Add(new DataPoint("q2", 7.6));
da4.Add(new DataPoint("q3", 28.5));
da4.Add(new DataPoint("q4", -17.5));

Finally, create several ColumnSeries and give the DataAdapters to them, then set the StackingToken for each Series and add the Series to the chart.

Note: The StackingToken plays a crucial role in the stacking process. Any series of the same Cartesian type which share the same, valid StackingToken are considered part of the same stacking group. The type of StackingToken determines the type of stacking behavior any affected series will adopt. All CartesianSeries types support overlapped stacking, whereas LineSeries, ColumnSeries and BarSeries also support cumulative stacking.

Members of a cumulative stacking group will have their data points stacked on top of one another. The order in which they are stacked is equal to the order in which the Series were added to the chart. CartesianSeries are given an initial default, unique stacking token which identifies the Series as unstacked. Similarly, setting a stacked series’ stacking token to a new, unique token which is only applied to that series, effectively unstacks it.

Note that for any cumulatively stacked ColumnSeries or BarSeries, all offsets must either be positive or negative - for example: Two ColumnSeries are stacked. Both series have yValues for xValues of 3 and 4. The first series has a yValue of 2 for x=3 and -1 for x=4. The second series has yValues of 7 for x=3 and -3 for x==4. This is OK, whereas if the second series had a yValue of 2 for x=4, that stack would contain both positive and negative offsets and could produce strange effects.

Any cumulatively stacked LineSeries should have its data values all positive or all negative, regardless of ordinal, otherwise unusual results may be observed.

Note also that if your Series are cumulatively stacked, their values should be sorted - with respect to the xAxis in the case of a ColumnSeries or LineSeries and with respect to the yAxis in the case of a BarSeries.

Java

ColumnSeries series1 = new ColumnSeries();
series1.setDataAdapter(da1);
series1.setTitle(getString(R.string.series_1_title));

ColumnSeries series2 = new ColumnSeries();
series2.setDataAdapter(da2);
series2.setTitle(getString(R.string.series_2_title));

ColumnSeries series3 = new ColumnSeries();
series3.setDataAdapter(da3);
series3.setTitle(getString(R.string.series_3_title));

ColumnSeries series4 = new ColumnSeries();
series4.setDataAdapter(da4);
series4.setTitle(getString(R.string.series_4_title));

final StackingToken stackingToken = StackingToken.newCumulativeStackingToken();

series1.setStackingToken(stackingToken);
shinobiChart.addSeries(series1);
series2.setStackingToken(stackingToken);
shinobiChart.addSeries(series2);
series3.setStackingToken(stackingToken);
shinobiChart.addSeries(series3);
series4.setStackingToken(stackingToken);
shinobiChart.addSeries(series4);

C#

StackingToken stackingToken = StackingToken.NewCumulativeStackingToken();

ColumnSeries series1 = new ColumnSeries() { StackingToken = stackingToken, DataAdapter = da1, Title = GetString(Resource.String.series_1_title) };
ColumnSeries series2 = new ColumnSeries() { StackingToken = stackingToken, DataAdapter = da2, Title = GetString(Resource.String.series_2_title) };
ColumnSeries series3 = new ColumnSeries() { StackingToken = stackingToken, DataAdapter = da3, Title = GetString(Resource.String.series_3_title) };
ColumnSeries series4 = new ColumnSeries() { StackingToken = stackingToken, DataAdapter = da4, Title = GetString(Resource.String.series_4_title) };

This is all that is required to set up a cumulatively stacked ColumnSeries. BarSeries and LineSeries series types can also be stacked in a similar manner.

Running the application will give you the following chart:

Stacked column series

See related code sample: Column Series Stacking Sample, in the samples/column-series-stacking folder of your product download (Xamarin.Android/samples/ColumnSeriesStacking if you’re using Xamarin.Android).