Tyro
Tyro

Reputation: 103

Secondary domain axis narrower than primary

I have timeSeries containing number of visitors for a web page in two days and then referential timeSeries containing number of visitors for a web page in other two days. I successfully put these datasets into one chart, but it seems that secondary domain axis I added is much narrower and thus it is impossible to compare those values.

enter image description here

Can I set the width of those axes to be the same?

EDIT: I posted my method to create JFreeChart down below. There is 48 values for both datasets.

public JFreeChart HourChart(CampaignWatcher choosenWatcher) throws UnknownHostException {
    ArrayList<ArrayList<HourObject>> data = GetWatcherData(choosenWatcher);
    TimeSeries timeSeries = new TimeSeries("Number of visitors");
    TimeSeries timeSeriesRef = new TimeSeries("Referential number of visitors");


    for(int i = 0; i<data.get(0).size();i++) {

        timeSeries.add(new Hour(data.get(0).get(i).hour,data.get(0).get(i).day,data.get(0).get(i).month,data.get(0).get(i).year),data.get(0).get(i).logObjects.size());
    }

    if(choosenWatcher.compareWithRef){
        for(int i = 0; i<data.get(1).size();i++) {
            timeSeriesRef.add(new Hour(data.get(1).get(i).hour,data.get(1).get(i).day,data.get(1).get(i).month,data.get(1).get(i).year),data.get(1).get(i).logObjects.size());
        }
    }

    TimeSeriesCollection dataset = new TimeSeriesCollection();
    dataset.addSeries(timeSeries);

    JFreeChart timeChart = ChartFactory.createTimeSeriesChart(choosenWatcher.name,"Hours","Number of visitors",dataset);

    timeChart.setBackgroundPaint(Color.white);

    XYPlot plot = (XYPlot) timeChart.getPlot();
    plot.setBackgroundPaint(Color.WHITE);
    plot.setDomainGridlinePaint(Color.LIGHT_GRAY);
    plot.setRangeGridlinePaint(Color.LIGHT_GRAY);
    plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
    //plot.setDomainCrosshairVisible(true);
    //plot.setRangeCrosshairVisible(true);

    XYItemRenderer r = plot.getRenderer();
    if (r instanceof XYLineAndShapeRenderer) {
        XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) r;
        renderer.setDefaultLinesVisible(true);
        renderer.setDefaultShapesFilled(true);
        renderer.setDrawSeriesLineAsPath(true);
    }

    DateAxis axis = (DateAxis) plot.getDomainAxis();
    axis.setDateFormatOverride(new SimpleDateFormat("dd/MMM/yyyy HH"));

    DateAxis axisRef = new DateAxis("Referential hours");
    axisRef.setDateFormatOverride(new SimpleDateFormat("dd/MMM/yyyy HH"));


    plot.setDomainAxis(1, axisRef);

    plot.setDomainAxisLocation(1,AxisLocation.BOTTOM_OR_RIGHT);

    TimeSeriesCollection datasetRef = new TimeSeriesCollection();
    datasetRef.addSeries(timeSeriesRef);
    plot.setDataset(1,datasetRef);

    plot.mapDatasetToDomainAxis(1,1);
    plot.mapDatasetToRangeAxis(1,0);

    XYLineAndShapeRenderer renderer0 = new XYLineAndShapeRenderer();
    XYLineAndShapeRenderer renderer1 = new XYLineAndShapeRenderer();

    plot.setRenderer(0, renderer0);
    plot.setRenderer(1, renderer1);

    plot.getRendererForDataset(plot.getDataset(0)).setSeriesPaint(0, Color.red);
    plot.getRendererForDataset(plot.getDataset(1)).setSeriesPaint(0, Color.blue);

    plot.setDomainPannable(true);
    plot.setRangePannable(true);

    ValueAxis valAxis = plot.getRangeAxis();

    valAxis.setAutoRange(true);

    return timeChart;
}

Upvotes: 2

Views: 146

Answers (1)

trashgod
trashgod

Reputation: 205785

The comparison approach shown in your fragment appears sound, but I suspect that your unseen data has multiple, varying timestamps for a given hourly interval, which the DateAxis faithfully reports.

The variation below clears the smaller Calendar fields, as shown here, to synthesize a DAYS worth of data. The resulting Hour instances have matching hour fields in each series. The example also omits the ChartFactory to avoid the unwanted ChartTheme axis label font.

To get the result you want, you're going have to resample your data to have matching hour fields for each period that you add() to a TimeSeries.

image

import java.awt.Color;
import java.awt.EventQueue;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.swing.JFrame;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Hour;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;

/**
 * @see https://stackoverflow.com/a/55584636/230513
 * @see https://stackoverflow.com/q/55553082/230513
 */
public class HourTest {

    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd-MMM HH");
    private static final int DAYS = 1;

    private Calendar getCalendar() {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);return c;
    }

    private void display() {
        JFrame f = new JFrame("HourTest");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        TimeSeries timeSeries = new TimeSeries("Number of visitors");
        TimeSeries refSeries = new TimeSeries("Reference number of visitors");
        Calendar c1 = getCalendar();
        Calendar c2 = getCalendar();
        c2.add(Calendar.DAY_OF_YEAR, -DAYS);
        for (int i = 0; i < 24 * DAYS; i++) {
            timeSeries.add(new Hour(c1.getTime()), i + 2);
            c1.add(Calendar.HOUR, 1);
            refSeries.add(new Hour(c2.getTime()), i + 1);
            c2.add(Calendar.HOUR, 1);
        }
        TimeSeriesCollection dataset = new TimeSeriesCollection(timeSeries);
        TimeSeriesCollection refDataset = new TimeSeriesCollection(refSeries);
        NumberAxis valueAxis = new NumberAxis("Number of visitors");
        valueAxis.setAutoRangeIncludesZero(false);
        DateAxis timeAxis = new DateAxis("Hours");
        timeAxis.setDateFormatOverride(DATE_FORMAT);
        DateAxis refAxis = new DateAxis("Reference hours");
        refAxis.setDateFormatOverride(DATE_FORMAT);
        XYPlot plot = new XYPlot(dataset, timeAxis, valueAxis, null);
        plot.setBackgroundPaint(Color.WHITE);
        plot.setDomainGridlinePaint(Color.LIGHT_GRAY);
        plot.setRangeGridlinePaint(Color.LIGHT_GRAY);
        plot.setDomainAxis(1, refAxis);
        plot.setDomainAxisLocation(1, AxisLocation.BOTTOM_OR_RIGHT);
        plot.setDataset(1, refDataset);
        plot.mapDatasetToDomainAxis(1, 1);
        XYLineAndShapeRenderer renderer0 = new XYLineAndShapeRenderer();
        renderer0.setSeriesPaint(0, Color.red);
        XYLineAndShapeRenderer renderer1 = new XYLineAndShapeRenderer();
        renderer1.setSeriesPaint(0, Color.blue);
        plot.setRenderer(0, renderer0);
        plot.setRenderer(1, renderer1);
        plot.setDomainPannable(true);
        plot.setRangePannable(true);
        JFreeChart timeChart = new JFreeChart("Main stats", plot);
        timeChart.setBackgroundPaint(Color.white);

        f.add(new ChartPanel(timeChart));
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new HourTest()::display);
    }
}

Upvotes: 2

Related Questions