Вторичная доменная ось уже первичной - PullRequest
2 голосов
/ 06 апреля 2019

У меня есть timeSeries, содержащие количество посетителей веб-страницы за два дня, а затем ссылочные timeSeries, содержащие количество посетителей веб-страницы за другие два дня.Я успешно поместил эти наборы данных в одну диаграмму, но кажется, что добавленная мной ось вторичного домена намного уже, и поэтому невозможно сравнить эти значения.

enter image description here

Могу ли я установить одинаковую ширину этих осей?

РЕДАКТИРОВАТЬ: я разместил свой метод для создания JFreeChart внизу.Для обоих наборов данных имеется 48 значений.

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;
}

1 Ответ

2 голосов
/ 09 апреля 2019

Сравнительный подход, показанный в вашем фрагменте, выглядит здравым, но я подозреваю, что у вашего невидимого data есть несколько переменных времени для данного часового интервала, о которых DateAxis точно сообщает.

Вариант ниже очищает меньшие поля Calendar, как показано здесь , чтобы синтезировать данные DAYS. Полученные экземпляры Hour имеют соответствующие часовые поля в каждой серии. В этом примере также пропущен ChartFactory, чтобы избежать нежелательного ChartTheme шрифта метки оси.

Чтобы получить желаемый результат, вам нужно будет повторно сэмплировать свой data, чтобы иметь соответствующие поля часов для каждого period, который вы add() до 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);
    }
}
...