java - 在 JFreeChart XYPLot 中改变单点的形状

标签 java plot jfreechart knn

我正在使用 JFreeChart XYPLot 绘制具有不同标签的 XYData 集。我为不同的标签创建了不同的 XYSeries 对象,这样我就可以为不同的标签使用不同的颜色。现在我需要更改每个 XYDataSeries 中特定点(测试数据)的形状,如下所示 enter image description here . 在上面的绘图中,有蓝色和红色两种不同的 XYSeries。在这两个中,我需要将一些点(测试数据)的形状更改为 X 而不是 circle 。在 JFreeChart 中有可能吗? This post解释了如何对整个数据集执行此操作,但我只想更改特定点

下面是我目前写的代码

  public static Map<String, XYSeries> createXYSeries(Data[] dataSet){       
    Map<String,XYSeries> xySeries = new HashMap<String, XYSeries>();        
    for(Data data : dataSet){
        if(xySeries.get(data.actualLabel) == null){
            xySeries.put(data.actualLabel, new XYSeries(data.actualLabel));
        }
        xySeries.get(data.actualLabel).add(data.dimensionValues[0],data.dimensionValues[1]);
    }   

    return xySeries;
}

   public XYDataset createXYSeriesCollection(Map<String, XYSeries> plottingDataSet) {
    XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
    for (String key : plottingDataSet.keySet()) {
        xySeriesCollection.addSeries(plottingDataSet.get(key));
    }
    return xySeriesCollection;
}

   private ChartPanel createPlottingPanel(String title,
        Map<String, XYSeries> plottingDataSet) {
    JFreeChart jfreechart = ChartFactory.createScatterPlot(title, "X", "Y",
            createSampleData(plottingDataSet), PlotOrientation.VERTICAL,
            true, true, false);
    XYPlot xyPlot = (XYPlot) jfreechart.getPlot();
    xyPlot.setDomainCrosshairVisible(true);
    xyPlot.setRangeCrosshairVisible(true);
    xyPlot.setBackgroundPaint(Color.white);
    return new ChartPanel(jfreechart);
}

注意:我正在尝试绘制 KNearestNeighbors 结果。(训练数据的圆圈和测试数据的 X)

最佳答案

ChartFactory.createScatterPlot() 实例化一个 XYLineAndShapeRenderer。您可以将渲染器替换为允许您有选择地替换 getItemShape() 返回的 Shape 的渲染器,如下所示。

    xyPlot.setRenderer(new XYLineAndShapeRenderer(false, true) {

        @Override
        public Shape getItemShape(int row, int col) {
            if (row == 0 & col == N) {
                return ShapeUtilities.createDiagonalCross(5, 2);
            } else {
                return super.getItemShape(row, col);
            }
        }
    });

image

完整示例,如运行:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Shape;
import java.util.*;
import javax.swing.JFrame;
import org.jfree.chart.*;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.util.ShapeUtilities;

/**
 * @see http://stackoverflow.com/a/20359200/230513
 * @see http://stackoverflow.com/a/6669529/230513
 */
public class ScatterShape extends JFrame {

    private static final int N = 8;
    private static final int SIZE = 345;
    private static final String title = "Scatter Shape Demo";
    private static final Random rand = new Random();
    private final XYSeries series = new XYSeries("Data");

    public ScatterShape(String s) {
        super(s);
        final ChartPanel chartPanel = createDemoPanel();
        this.add(chartPanel, BorderLayout.CENTER);
    }

    private ChartPanel createDemoPanel() {
        JFreeChart chart = ChartFactory.createScatterPlot(
            title, "X", "Y", createSampleData(),
            PlotOrientation.VERTICAL, true, true, false);
        XYPlot xyPlot = (XYPlot) chart.getPlot();
        xyPlot.setDomainCrosshairVisible(true);
        xyPlot.setRangeCrosshairVisible(true);
        xyPlot.setRenderer(new XYLineAndShapeRenderer(false, true) {

            @Override
            public Shape getItemShape(int row, int col) {
                if (row == 0 & col == N) {
                    return ShapeUtilities.createDiagonalCross(5, 2);
                } else {
                    return super.getItemShape(row, col);
                }
            }
        });
        adjustAxis((NumberAxis) xyPlot.getDomainAxis(), true);
        adjustAxis((NumberAxis) xyPlot.getRangeAxis(), false);
        xyPlot.setBackgroundPaint(Color.white);
        return new ChartPanel(chart) {

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(SIZE, SIZE);
            }
        };
    }

    private void adjustAxis(NumberAxis axis, boolean vertical) {
        axis.setRange(-3.0, 3.0);
        axis.setTickUnit(new NumberTickUnit(0.5));
        axis.setVerticalTickLabels(vertical);
    }

    private XYDataset createSampleData() {
        XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
        for (int i = 0; i < N * N; i++) {
            series.add(rand.nextGaussian(), rand.nextGaussian());
        }
        xySeriesCollection.addSeries(series);
        return xySeriesCollection;
    }

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

            @Override
            public void run() {
                ScatterShape demo = new ScatterShape(title);
                demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                demo.pack();
                demo.setLocationRelativeTo(null);
                demo.setVisible(true);
            }
        });
    }
}

关于java - 在 JFreeChart XYPLot 中改变单点的形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20357839/

相关文章:

java - ExecutorCompletionService 挂起

java - 在 | 上拆分字符串Java 中的(管道)

java - 使用java读取文本文件中一定数量的行

java - jasypt PBKDF2 实现

R中箱线图中的反向y轴

java - 导出至excel并显示图表

python - 具有颜色渐变的 Matplotlib 3D 散点图

python - 如何使用所有 xticks 绘制 pandas 多索引数据帧

java - 如何在jsp页面中显示饼图?

java - 动态改变Jfreechart中的Y轴范围