Stacked Area Charts with negative & postive values

A discussion forum for JFreeChart (a 2D chart library for the Java platform).
Locked
spidertom
Posts: 3
Joined: Fri Dec 12, 2008 12:55 am

Stacked Area Charts with negative & postive values

Post by spidertom » Fri Dec 12, 2008 1:36 am

Hello, i am using jfreechart version 1.0.11 and i am having difficulty in creating a stacked area chart that defines areas that go from a positive value to a negative value over time. It's easier to explain in pictures.

Here is an example of where the chart is working fine. In the first point there is a red range, an yellow range, and a green range. The yellow range is defined between 23% and 25%, anything under 23% is red and anything about 25% is green. In the second point, the yellow range has changed, now anything from 5% to 10% is considered yellow. This all works perfectly if everything is positive. (you can ignore the data point at 0% in the chart)

[img]http%20://img238.imageshack.us/img238/740/oknc1.jpg[/img]

however when i change the second point to define the yellow range as between -10% to 5% i get the following.

[img]http%20://img339.imageshack.us/img339/9834/negativeyt5.jpg[/img]

i don't quite understand why it is doing this. Can anyone point me in the right direction?

rade
Posts: 7
Joined: Thu Dec 11, 2008 4:37 pm

Post by rade » Fri Dec 12, 2008 2:17 pm

if you are using XYPlot you should use StackedXYAreaRenderer2 instead of StackedXYAreaRenderer (which doesn't support negative values)

spidertom
Posts: 3
Joined: Fri Dec 12, 2008 12:55 am

Post by spidertom » Fri Dec 12, 2008 3:38 pm

I'm actually using a category plot. It seems as if the drawItem method in StackedAreaRenderer may not account for this type of scenario. Or perhaps i'm not using the dataset correctly. Is there something wrong with the following below

Code: Select all

dataset.addValue(-20,"lowerBound","Quarter 4 05");
dataset.addValue(23,"range1","Quarter 4 05");
dataset.addValue(2,"range2","Quarter 4 05");
dataset.addValue(10,"upperBound","Quarter 4 05");

dataset.addValue(-10,"range1","Quarter 1 06");
dataset.addValue(-20,"lowerBound","Quarter 1 06");
dataset.addValue(5,"range2","Quarter 1 06");
dataset.addValue(30,"upperBound","Quarter 1 06");
As i understand it, when building stacked areas the valued added to the dataset is cumulative away from 0.

So in the first grouping, we're creating an areas from 0 to -20, another area from 0 to 23, then from 23 to 25, and then from 25 to 35.

In the second grouping, the first area would go from 0 to -10, another from -10 to -20, and on the positive side from 0 to 5, and lastly from 5 to 35. Is this correct?

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Post by david.gilbert » Mon Dec 15, 2008 2:34 pm

I took a look at this, but I found myself making guesses at the nature of your data. Is it that you are trying to show the evolution of three related data bands through time? In that case, I think you might be stretching the stacked area renderer too far. A better (but still not ideal) approach would be to use a DeviationRenderer on an XYPlot...here's an example that I'll add to the JFreeChart demo collection:

Code: Select all

/* ---------------------------
 * DeviationRendererDemo3.java
 * ---------------------------
 * (C) Copyright 2008, by Object Refinery Limited.
 *
 */

package demo;

import java.awt.BasicStroke;
import java.awt.Color;
import javax.swing.JPanel;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.DeviationRenderer;
import org.jfree.data.time.Quarter;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.YIntervalSeries;
import org.jfree.data.xy.YIntervalSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;

/**
 * A demo of the {@link DeviationRenderer} class.  Here we overlay three
 * datasets to display the extent of three data bands through time.
 */
public class DeviationRendererDemo3 extends ApplicationFrame {

    /**
     * Creates a new demo.
     *
     * @param title  the frame title.
     */
    public DeviationRendererDemo3(String title) {
        super(title);
        JPanel chartPanel = createDemoPanel();
        chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
        setContentPane(chartPanel);
    }

    /**
     * Creates a sample dataset.
     *
     * @return a sample dataset.
     */
    private static XYDataset createDataset() {

        YIntervalSeries series1 = new YIntervalSeries("Band A");
        YIntervalSeries series2 = new YIntervalSeries("Band B");
        YIntervalSeries series3 = new YIntervalSeries("Band C");
        RegularTimePeriod t = new Quarter(1, 2005);
        double y1 = 0.0;
        for (int i = 0; i <= 12; i++) {
            y1 = y1 + (Math.random() - 0.50) * 15;
            series1.add(t.getMiddleMillisecond(), y1, y1 + 10, Math.max(50, y1 + 30.0));
            series2.add(t.getMiddleMillisecond(), y1, y1 - 10, y1 + 10);
            series3.add(t.getMiddleMillisecond(), y1, Math.min(-50.0, y1 - 30), y1 - 10);
            t = t.next();
        }

        YIntervalSeriesCollection dataset = new YIntervalSeriesCollection();
        dataset.addSeries(series1);
        dataset.addSeries(series2);
        dataset.addSeries(series3);

        return dataset;

    }

    /**
     * Creates a chart.
     *
     * @param dataset  the data for the chart.
     *
     * @return a chart.
     */
    private static JFreeChart createChart(XYDataset dataset) {

        // create the chart...
        JFreeChart chart = ChartFactory.createXYLineChart(
            "DeviationRenderer - Demo 3",      // chart title
            "X",                      // x axis label
            "Y",                      // y axis label
            dataset,                  // data
            PlotOrientation.VERTICAL,
            false,                     // include legend
            true,                     // tooltips
            false                     // urls
        );

        // get a reference to the plot for further customisation...
        XYPlot plot = (XYPlot) chart.getPlot();

        DeviationRenderer renderer = new DeviationRenderer(false, false);
        renderer.setSeriesStroke(0, new BasicStroke(3.0f, BasicStroke.CAP_ROUND,
                BasicStroke.JOIN_ROUND));
        renderer.setSeriesStroke(0, new BasicStroke(3.0f,
                BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        renderer.setSeriesStroke(1, new BasicStroke(3.0f,
                BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        renderer.setSeriesFillPaint(0, Color.red);
        renderer.setSeriesFillPaint(1, Color.orange);
        renderer.setSeriesFillPaint(2, Color.green);
        plot.setRenderer(renderer);

        DateAxis xAxis = new DateAxis("Date");
        xAxis.setLowerMargin(0.0);
        xAxis.setUpperMargin(0.0);
        plot.setDomainAxis(xAxis);

        // change the auto tick unit selection to integer units only...
        NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
        yAxis.setRange(-40.0, 40.0);
        yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

        ChartUtilities.applyCurrentTheme(chart);
        return chart;

    }

    /**
     * Creates a panel for the demo (used by SuperDemo.java).
     *
     * @return A panel.
     */
    public static JPanel createDemoPanel() {
        JFreeChart chart = createChart(createDataset());
        return new ChartPanel(chart);
    }

    /**
     * Starting point for the demonstration application.
     *
     * @param args  ignored.
     */
    public static void main(String[] args) {
        DeviationRendererDemo3 demo = new DeviationRendererDemo3(
                "JFreeChart : DeviationRendererDemo3.java");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }

}
Of course, you might have been trying to do something else, in which case you might have to explain it some more...
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

spidertom
Posts: 3
Joined: Fri Dec 12, 2008 12:55 am

Post by spidertom » Mon Dec 15, 2008 4:35 pm

yeah, although there can be X number of bands to chart, but that's shouldn't be a problem. To help understand what kind of data i'm working with thinking of a manufacturing plant with tolerance specifications (like six sigma). The bands being charted would represent acceptance thresholds. The DeviationRenderer looks very promising based off of the demo code you've given. I will give that a shot, thanks!

agscontact
Posts: 13
Joined: Mon Dec 01, 2008 4:31 am

to gilbert

Post by agscontact » Fri Dec 26, 2008 9:53 am

146.06 cat1 series1

3.67 cat2 series2


Gilbert...please check the stacked area ...its not proper.....

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Post by david.gilbert » Tue Dec 30, 2008 11:37 am

Checked...looks fine to me.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

Locked