ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  Using Chart.Side and Chart.Stack with Unevenly Distributed Data
Posted by Robert on Feb-16-2012 06:58
Hi,

I am trying to create a bar chart with multiple data series side by side or stacked.

According to ChartDirector documentation you can only have one x values series per Layer.

When using Chart.Side and Chart.Stack. I have to add all my data sets on to the same
BarLayer and as expected with unevenly distributed data some bars are appearing on the
incorrect positions on x-axis.

Is there a way to solve this problem?

Kind Regards

Robert

  Re: Using Chart.Side and Chart.Stack with Unevenly Distributed Data
Posted by Peter Kwan on Feb-17-2012 00:27
Hi Robert,

Are you using setXData to specify the x-position of the bars? In this case, the bars should always be located in the x-position your code specified. Is this not the case?

For example, suppose you want the bars to be located at x = 0.5, 2, 4, 7. Then you can use this array as the x-coordinates (pass the array to setXData).

Now if you want to add a bar to all or some of these x positions, just put the data value at these array positions, with the remaining array positions filled with Chart.NoValue. For example, if you want to put bars at x = 0.5 and 4, please use the following array {myDataValue0, Chart.NoValue, myDataValue1, Chart.NoValue}.

Note that for unevenly spaced bar chart, there is no well-accepted way to determine the width of the bars (or the width of a bar cluster in a Multi-Bar chart). For example, for the case of x = 0.5132512, 2.123598, 4.16214, 7.8365, should the bar width be 1.5 units, 2 units, 3 units, 1 unit or other units? ChartDirector will try to guess what is the width, which may or may not fit the nature of your application. So it is suggested your code explicitily supply the bar width using BarLayer.setBarWidth. Also, for unevenly spaced bar chart, it is suggested you disable "indenting" by using BarLayer.setIndent, and explicitly provide the axis margins using Axis.setMargin to ensure the bars staying within the plot area.

(If your bars are at x = 1, 2, 3, 4, and the axis is from 1 to 4, then half of the the first bar will be outside the plot area. It is because the x = 1 point, which is the center of the bar, will be at the left edge of the plot area, so only the right half of the bar will be within the plot area. To solve that problem, if there is a bar layer, ChartDirector by default will automatically use the "BarLayer.setIndent" mechanism to add margins to the axis scale. However, as explained above, with unevenly spaced bars, there is no well-accepted way to determine the bar width, so the automatically margin added by ChartDirector may not fit your application's need. Therefore it is suggested your code explicitly add the margin to fit the nature of your application.)

Instead of using evenly spaced bars, if your bars are not really randomly spaced, but are "periodically spaced with some missing positions", we suggest you use a normal bar layer (which assumes equally spaced bars) without setXData. The missing positions can be filled with Chart.NoValue. In this way, ChartDirector should be able to determine the appropriate bar width and axis margin.

Hope this can help.

Regards
Peter Kwan

  Re: Using Chart.Side and Chart.Stack with Unevenly Distributed Data
Posted by Robert on Feb-17-2012 05:56
Hi Peter,

Thanks for your reply.

Yes I am using setXData(Date) to specify the position of the bar and the bars are
"periodically spaced with some missing positions". It worked perfectly when there is only one
data set on the layer. When I am trying to add a second data set to the same (Stack or
Side) bar layer and if there are some gaps in the data, the bar will appear on incorrect date
on x-axis.

It seems a bit strange when ChartDirector can accept multiple sets of y-axis values per
layer but only one set of x-axis values. Is this a limitation or am I missing something?

At the moment I am going with the filling gaps with Chart.NoValue approach (which in my
case is a pain in the butt!).

Kind Regards

Robert

  Re: Using Chart.Side and Chart.Stack with Unevenly Distributed Data
Posted by Peter Kwan on Feb-17-2012 23:46
Hi Robert,

The main reason of putting multiple data series in the same layer (instead of one data series per layer) is to combine the data series in some ways. In a bar layer, they may be stacked or "grouped". In a box-whisker layer, they may be combined into a special symbol, etc..

To meaningfully combine the data, the corresponding data values must shared exactly the same x-coordinate. The one x data series per layer is just a structure to guarantee the data sets must share the same x-coordinates.

If the data come from a database table, in many cases it is easier to get the data into the structure required by ChartDirector in one SQL query, than to use different x coordinates for different data series (which usually means multiple SQL queries). Basically, the SQL query can be designed so that it returns all the required x coordinates in one column, and each data series in a separate column (with empty cells filled with 0 or a value of your choice.) An example is like:

http://www.mssqlserver.com/faq/development-crosstab.asp

If your data are "periodically spaced with some missing positions", instead of using SQL query, you can use the following method to generate the data arrays (in Java):

//This is the number of elements
int cdStartTime = Chart.CTime(startTime);
int noOfElements = (Chart.CTime(endTime) - cdStartTime) / durationBetweenPointsInSeconds + 1;

//Fill your original data arrays with NoValue
double[] myData = new double[noOfElements];
Array.fill(myData, Chart.NoValue);
for (int i = 0; i < myOriginalData.length; ++i)
    myData[(Chart.CTime(myOriginalTime[i]) - cdStartTime) / durationBetweenPointsInSeconds] = myOriginalData[i];

... repeat the above if your have other data series ...

Then you may add the layer using:

BarLayer layer = c.addBarLayer2(Chart.Stack);
layer.setXData(startTime, endTime);
layer.addDataSet(myData, ...);
.....

Hope this can help.

Regards
Peter Kwan

  Re: Using Chart.Side and Chart.Stack with Unevenly Distributed Data
Posted by Robert on Feb-20-2012 07:04
To meaningfully combine the data, the corresponding data values must shared exactly the
same x-coordinate. The one x data series per layer is just a structure to guarantee the
data sets must share the same x-coordinates.

Hi Peter,

Totally agree and y-axis sharing on grouped data sets is working perfectly by allowing you
to add multiple y value data sets to the same layer.  I would expect the same could be
done on x-axis too? The main difference between y-axis and x-axis is the type of the data
(by default double on y and date on x).

Thanks for the code btw.

Kind Regards

Robert

  Re: Using Chart.Side and Chart.Stack with Unevenly Distributed Data
Posted by Peter Kwan on Feb-21-2012 00:39
Hi Robert,

The x-axis and y-axis are just names. In ChartDirector, the x-axis can be horizontal or vertical (use swapXY if you need to have the x-axis vertical), and can be on the bottom, top, left or right side of the plot area. So it means any of the side of the plot area can be the shared axis. No matter which side you choose to use, that side must be configured to be called the x-axis.

The x-axis does not have a default data type. It can be numeric, date/time or just names (eg. you can use names of countries on the x-axis). The y-axis also can be numeric, date/time or just names similar to the x-axis. However, for strongly typed languages (such as .NET or Java), the ChartDirector API only accepts "double[]" as the data type for y-data. To use dates as y-data, one would need to convert the Date[] to double[] using Chart.CTime.

Hope this can help.

Regards
Peter Kwan