具有多个类别的箱线图的 JFreeChart 缩放

发布于 2024-11-26 08:36:52 字数 3328 浏览 1 评论 0原文

我目前正在开发一个基于 java 的项目,使用 JFreeChart 来显示箱线图。

我的问题是如何显示包含大约 20 个类别和 5 个以上系列的 CategoryDataset 的箱线图的图表。

目前,如果未设置 ChartPanel 的首选大小,图例、标签和注释是可读的,但箱线图太小。或者设置 ChartPanel 的大小,以便箱线图具有可接受的大小,但图例、标签和注释会水平拉伸。

我的问题是,如何在不缩放图表的图例、轴标签和注释的情况下正确缩放箱线图?是否可以在不缩放图表所有元素的情况下缩放绘图?

代码示例

import java.awt.Color;
import java.awt.Dimension;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import javax.swing.JFrame;
import javax.swing.JScrollPane;

import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.renderer.category.BoxAndWhiskerRenderer;
import org.jfree.data.statistics.DefaultBoxAndWhiskerCategoryDataset;


public class StretchedBoxAndWhiskerExample{

DefaultBoxAndWhiskerCategoryDataset dataset;
JFreeChart chart;
ChartPanel chartPanel;
JFrame frame;
JScrollPane scrollPane;

public StretchedBoxAndWhiskerExample() {
    createCategoryBoxplot();

    frame = new JFrame();
    scrollPane = new JScrollPane(chartPanel);
    scrollPane.setPreferredSize(new Dimension(800,700));
    scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
    frame.add(scrollPane);
    frame.pack();
    frame.setVisible(true);
}

private void createCategoryBoxplot(){   
    dataset = createCategoryDataset();
    CategoryAxis xAxis = new CategoryAxis("");
    NumberAxis yAxis = new NumberAxis("Score");

    BoxAndWhiskerRenderer renderer = new BoxAndWhiskerRenderer();
    CategoryPlot plot = new CategoryPlot(dataset, xAxis, yAxis, renderer);
    createJFreeChart(plot,"Test");

    // Design
    renderer.setFillBox(false);
    renderer.setMeanVisible(false);

    chart.setBackgroundPaint(Color.white); 
    plot.setBackgroundPaint(Color.lightGray); 
    plot.setDomainGridlinePaint(Color.white); 
    plot.setDomainGridlinesVisible(true); 
    plot.setRangeGridlinePaint(Color.white);
    plot.getRangeAxis().setRange(-10.5, 10.5);


    chartPanel = new ChartPanel(chart);
    chartPanel.setPreferredSize(new Dimension(3250,600));
}

private DefaultBoxAndWhiskerCategoryDataset createCategoryDataset() {

    dataset = new DefaultBoxAndWhiskerCategoryDataset();
    ArrayList<Double> values = createSampleData();
    ArrayList<String> categories = createSampleCategories();
    for (int i=0;i<=5;i++){
        for (String category : categories){
            dataset.add(values,i,category);
        }
    }
    return dataset;
}


private ArrayList<String> createSampleCategories() {
    ArrayList<String> tmp = new ArrayList<String>();
    for (int i=0;i<=20;i++){
        tmp.add("Category"+i);
    }
    return tmp;
}

private ArrayList<Double> createSampleData() {
    ArrayList<Double> tmp = new ArrayList<Double>();
    for (int i=0;i<10;i++){
        tmp.add(5.0);
        tmp.add(7.0);
        tmp.add(2.0);
        tmp.add(4.0);
    }
    return tmp;
}

private void createJFreeChart(CategoryPlot plot, String title){
    chart = new JFreeChart(title, plot);
}

public static void main(String[] args) throws IOException { 
    StretchedBoxAndWhiskerExample demo = new StretchedBoxAndWhiskerExample();

}
}

i am currently working on a java-based project using JFreeChart to display boxplots.

My Problem is how to display a chart containing boxplots for a CategoryDataset with about 20 Categories and 5+ Series.

Currently if the preferred size of the ChartPanel is not set, the Legend, Labels and Annotations are readable but the Boxplots are too small. Or the size of the ChartPanel is set so that the Boxplots have an acceptable size but then the legend, labels and annotations are horizontally stretched.

My question is, how to correctly scale the boxplots without scaling the legend, axis Labels and annotations of the Chart? Is it possible to scale the Plot without scaling all the elements of the Chart?

Code Example

import java.awt.Color;
import java.awt.Dimension;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import javax.swing.JFrame;
import javax.swing.JScrollPane;

import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.renderer.category.BoxAndWhiskerRenderer;
import org.jfree.data.statistics.DefaultBoxAndWhiskerCategoryDataset;


public class StretchedBoxAndWhiskerExample{

DefaultBoxAndWhiskerCategoryDataset dataset;
JFreeChart chart;
ChartPanel chartPanel;
JFrame frame;
JScrollPane scrollPane;

public StretchedBoxAndWhiskerExample() {
    createCategoryBoxplot();

    frame = new JFrame();
    scrollPane = new JScrollPane(chartPanel);
    scrollPane.setPreferredSize(new Dimension(800,700));
    scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
    frame.add(scrollPane);
    frame.pack();
    frame.setVisible(true);
}

private void createCategoryBoxplot(){   
    dataset = createCategoryDataset();
    CategoryAxis xAxis = new CategoryAxis("");
    NumberAxis yAxis = new NumberAxis("Score");

    BoxAndWhiskerRenderer renderer = new BoxAndWhiskerRenderer();
    CategoryPlot plot = new CategoryPlot(dataset, xAxis, yAxis, renderer);
    createJFreeChart(plot,"Test");

    // Design
    renderer.setFillBox(false);
    renderer.setMeanVisible(false);

    chart.setBackgroundPaint(Color.white); 
    plot.setBackgroundPaint(Color.lightGray); 
    plot.setDomainGridlinePaint(Color.white); 
    plot.setDomainGridlinesVisible(true); 
    plot.setRangeGridlinePaint(Color.white);
    plot.getRangeAxis().setRange(-10.5, 10.5);


    chartPanel = new ChartPanel(chart);
    chartPanel.setPreferredSize(new Dimension(3250,600));
}

private DefaultBoxAndWhiskerCategoryDataset createCategoryDataset() {

    dataset = new DefaultBoxAndWhiskerCategoryDataset();
    ArrayList<Double> values = createSampleData();
    ArrayList<String> categories = createSampleCategories();
    for (int i=0;i<=5;i++){
        for (String category : categories){
            dataset.add(values,i,category);
        }
    }
    return dataset;
}


private ArrayList<String> createSampleCategories() {
    ArrayList<String> tmp = new ArrayList<String>();
    for (int i=0;i<=20;i++){
        tmp.add("Category"+i);
    }
    return tmp;
}

private ArrayList<Double> createSampleData() {
    ArrayList<Double> tmp = new ArrayList<Double>();
    for (int i=0;i<10;i++){
        tmp.add(5.0);
        tmp.add(7.0);
        tmp.add(2.0);
        tmp.add(4.0);
    }
    return tmp;
}

private void createJFreeChart(CategoryPlot plot, String title){
    chart = new JFreeChart(title, plot);
}

public static void main(String[] args) throws IOException { 
    StretchedBoxAndWhiskerExample demo = new StretchedBoxAndWhiskerExample();

}
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

看轻我的陪伴 2024-12-03 08:36:52

设置包含 ChartPanel 的首选大小,而不是图表的大小,如下所示 这里此处

附录:我认为您不能有效地将图表添加到滚动窗格。相反,创建一个类似于 的类SlidingCategoryDataset 实现了 BoxAndWhiskerCategoryDataset。将滚动条添加到控制第一个显示索引的框架。

附录:一种不太雄心勃勃的方法是使用一些合适的控件简单地对数据集的一部分进行分页,如下例所示。

在此处输入图像描述

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.renderer.category.BoxAndWhiskerRenderer;
import org.jfree.data.statistics.DefaultBoxAndWhiskerCategoryDataset;

/** @see https://stackoverflow.com/questions/6844759 */
public class BoxAndWhiskerDemo {

    private static final int COLS = 20;
    private static final int VISIBLE = 4;
    private static final int ROWS = 5;
    private static final int VALUES = 10;
    private static final Random rnd = new Random();
    private List<String> columns;
    private List<List<List<Double>>> data;
    private DefaultBoxAndWhiskerCategoryDataset dataset;
    private CategoryPlot plot;
    private ChartPanel chartPanel;
    private JPanel controlPanel;
    private int start = 0;

    public BoxAndWhiskerDemo() {
        createData();
        createDataset(start);
        createChartPanel();
        createControlPanel();
    }

    private void createData() {
        columns = new ArrayList<String>(COLS);
        data = new ArrayList<List<List<Double>>>();
        for (int i = 0; i < COLS; i++) {
            String name = "Category" + String.valueOf(i + 1);
            columns.add(name);
            List<List<Double>> list = new ArrayList<List<Double>>();
            for (int j = 0; j < ROWS; j++) {
                list.add(createValues());
            }
            data.add(list);
        }
    }

    private List<Double> createValues() {
        List<Double> list = new ArrayList<Double>();
        for (int i = 0; i < VALUES; i++) {
            list.add(rnd.nextGaussian());
        }
        return list;
    }

    private void createDataset(int start) {
        dataset = new DefaultBoxAndWhiskerCategoryDataset();
        for (int i = start; i < start + VISIBLE; i++) {
            List<List<Double>> list = data.get(i);
            int row = 0;
            for (List<Double> values : list) {
                String category = columns.get(i);
                dataset.add(values, "s" + row++, category);
            }
        }
    }

    private void createChartPanel() {
        CategoryAxis xAxis = new CategoryAxis("Category");
        NumberAxis yAxis = new NumberAxis("Value");
        BoxAndWhiskerRenderer renderer = new BoxAndWhiskerRenderer();
        plot = new CategoryPlot(dataset, xAxis, yAxis, renderer);
        JFreeChart chart = new JFreeChart("BoxAndWhiskerDemo", plot);
        chartPanel = new ChartPanel(chart);
    }

    private void createControlPanel() {
        controlPanel = new JPanel();
        controlPanel.add(new JButton(new AbstractAction("\u22b2Prev") {

            @Override
            public void actionPerformed(ActionEvent e) {
                start -= VISIBLE;
                if (start < 0) {
                    start = 0;
                    return;
                }
                createDataset(start);
                plot.setDataset(dataset);
            }
        }));
        controlPanel.add(new JButton(new AbstractAction("Next\u22b3") {

            @Override
            public void actionPerformed(ActionEvent e) {
                start += VISIBLE;
                if (start > COLS - VISIBLE) {
                    start = COLS - VISIBLE;
                    return;
                }
                createDataset(start);
                plot.setDataset(dataset);
            }
        }));
    }

    public ChartPanel getChartPanel() {
        return chartPanel;
    }

    public JPanel getControlPanel() {
        return controlPanel;
    }

    public static void main(String[] args) throws IOException {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                BoxAndWhiskerDemo demo = new BoxAndWhiskerDemo();
                frame.add(demo.getChartPanel(), BorderLayout.CENTER);
                frame.add(demo.getControlPanel(), BorderLayout.SOUTH);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

Set the preferred size of the containing ChartPanel, not the chart, as shown here and here.

Addendum: I don't think you can usefully add a chart to a scroll pane. Instead, create a class similar to SlidingCategoryDataset that implements BoxAndWhiskerCategoryDataset. Add a scroll bar to the frame that controls the first displayed index.

Addendum: A somewhat less ambitious approach is simply to page a portion of the data set using some suitable control, as shown in the example below.

enter image description here

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.renderer.category.BoxAndWhiskerRenderer;
import org.jfree.data.statistics.DefaultBoxAndWhiskerCategoryDataset;

/** @see https://stackoverflow.com/questions/6844759 */
public class BoxAndWhiskerDemo {

    private static final int COLS = 20;
    private static final int VISIBLE = 4;
    private static final int ROWS = 5;
    private static final int VALUES = 10;
    private static final Random rnd = new Random();
    private List<String> columns;
    private List<List<List<Double>>> data;
    private DefaultBoxAndWhiskerCategoryDataset dataset;
    private CategoryPlot plot;
    private ChartPanel chartPanel;
    private JPanel controlPanel;
    private int start = 0;

    public BoxAndWhiskerDemo() {
        createData();
        createDataset(start);
        createChartPanel();
        createControlPanel();
    }

    private void createData() {
        columns = new ArrayList<String>(COLS);
        data = new ArrayList<List<List<Double>>>();
        for (int i = 0; i < COLS; i++) {
            String name = "Category" + String.valueOf(i + 1);
            columns.add(name);
            List<List<Double>> list = new ArrayList<List<Double>>();
            for (int j = 0; j < ROWS; j++) {
                list.add(createValues());
            }
            data.add(list);
        }
    }

    private List<Double> createValues() {
        List<Double> list = new ArrayList<Double>();
        for (int i = 0; i < VALUES; i++) {
            list.add(rnd.nextGaussian());
        }
        return list;
    }

    private void createDataset(int start) {
        dataset = new DefaultBoxAndWhiskerCategoryDataset();
        for (int i = start; i < start + VISIBLE; i++) {
            List<List<Double>> list = data.get(i);
            int row = 0;
            for (List<Double> values : list) {
                String category = columns.get(i);
                dataset.add(values, "s" + row++, category);
            }
        }
    }

    private void createChartPanel() {
        CategoryAxis xAxis = new CategoryAxis("Category");
        NumberAxis yAxis = new NumberAxis("Value");
        BoxAndWhiskerRenderer renderer = new BoxAndWhiskerRenderer();
        plot = new CategoryPlot(dataset, xAxis, yAxis, renderer);
        JFreeChart chart = new JFreeChart("BoxAndWhiskerDemo", plot);
        chartPanel = new ChartPanel(chart);
    }

    private void createControlPanel() {
        controlPanel = new JPanel();
        controlPanel.add(new JButton(new AbstractAction("\u22b2Prev") {

            @Override
            public void actionPerformed(ActionEvent e) {
                start -= VISIBLE;
                if (start < 0) {
                    start = 0;
                    return;
                }
                createDataset(start);
                plot.setDataset(dataset);
            }
        }));
        controlPanel.add(new JButton(new AbstractAction("Next\u22b3") {

            @Override
            public void actionPerformed(ActionEvent e) {
                start += VISIBLE;
                if (start > COLS - VISIBLE) {
                    start = COLS - VISIBLE;
                    return;
                }
                createDataset(start);
                plot.setDataset(dataset);
            }
        }));
    }

    public ChartPanel getChartPanel() {
        return chartPanel;
    }

    public JPanel getControlPanel() {
        return controlPanel;
    }

    public static void main(String[] args) throws IOException {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                BoxAndWhiskerDemo demo = new BoxAndWhiskerDemo();
                frame.add(demo.getChartPanel(), BorderLayout.CENTER);
                frame.add(demo.getControlPanel(), BorderLayout.SOUTH);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文