JFreeChart строит данные, но не рисует линейную регрессию - PullRequest
1 голос
/ 23 апреля 2020

Я использовал JFreeChart для представления моего массива x и y . Эти массивы отображаются очень хорошо, однако линия преемственности прерывается и никогда не рисуется. Работают все функции, такие как отображение значений, кроме функций drawinputpoint и drawregressionline. Почему-то эти двое никогда не работают. Я не возражаю против drawwinginputpoint, но мне нравится иметь возможность drawregressionline. Мой массив содержит правильные данные, поэтому не уверен, в чем проблема. Я импортирую данные своих массивов в набор данных в функции createDateSetFromFile. Мой Home_JFrame имеет массив targetx и targety. Они имеют arraylist и тип данных Double.

package gradleproject2;

import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.ui.ApplicationFrame;
import org.jfree.data.function.LineFunction2D;
import org.jfree.data.general.DatasetUtils;
import org.jfree.data.statistics.Regression;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import gradleproject2.Home_JFrame;
import org.jfree.ui.RefineryUtilities;

public class PriceEstimator extends ApplicationFrame{

private static final long serialVersionUID = 1L;

    XYDataset inputData;
    JFreeChart chart;

    public static void main(String[] args) throws IOException {
        PriceEstimator demo = new PriceEstimator();
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
                demo.drawRegressionLine();

                if (args.length >= 1 && args[0] != null) {
            // Estimate the linear function given the input data
            double regressionParameters[] = Regression.getOLSRegression(
                    demo.inputData, 0);
            double x = Double.parseDouble(args[0]);

            // Prepare a line function using the found parameters
            LineFunction2D linefunction2d = new LineFunction2D(
                    regressionParameters[0], regressionParameters[1]);
            // This is the estimated price
            double y = linefunction2d.getValue(x);

            demo.drawInputPoint(x, y);
    }
        }

    public PriceEstimator() throws IOException {
        super("Linear Regression");

        // Read sample data from prices.txt file
        inputData = createDatasetFromFile();

        // Create the chart using the sample data
        chart = createChart(inputData);

        ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
        setContentPane(chartPanel);
    }

    public XYDataset createDatasetFromFile() throws IOException {
        ClassLoader classLoader = getClass().getClassLoader();

        XYSeriesCollection dataset = new XYSeriesCollection();
        XYSeries series = new XYSeries("Stock Item");

        // Read the price and the date
        for (int row = 0; row < Home_JFrame.targetx.size(); row++) {
                     series.add(Home_JFrame.targetx.get(row), Home_JFrame.targety.get(row));
                }

        dataset.addSeries(series);
                Home_JFrame.targetx.clear();
                 Home_JFrame.targety.clear();
        return dataset;
    }

    private JFreeChart createChart(XYDataset inputData) throws IOException {
        // Create the chart using the data read from the prices.txt file
        JFreeChart chart = ChartFactory.createScatterPlot(
                "Stock Price", "Stock Date", "Stock Opening Price", inputData,
                PlotOrientation.VERTICAL, true, true, false);

        XYPlot plot = chart.getXYPlot();
        plot.getRenderer().setSeriesPaint(0, Color.blue);
        return chart;
    }


    private void drawRegressionLine() {
        // Get the parameters 'a' and 'b' for an equation y = a + b * x,
        // fitted to the inputData using ordinary least squares regression.
        // a - regressionParameters[0], b - regressionParameters[1]
        double regressionParameters[] = Regression.getOLSRegression(inputData,
                0);

        // Prepare a line function using the found parameters
        LineFunction2D linefunction2d = new LineFunction2D(
                regressionParameters[0], regressionParameters[1]);

        // Creates a dataset by taking sample values from the line function
        XYDataset dataset = DatasetUtils.sampleFunction2D(linefunction2d,
                0D, 300, 100, "Fitted Regression Line");

        // Draw the line dataset
        XYPlot xyplot = chart.getXYPlot();
        xyplot.setDataset(1, dataset);
        XYLineAndShapeRenderer xylineandshaperenderer = new XYLineAndShapeRenderer(
                true, false);
        xylineandshaperenderer.setSeriesPaint(0, Color.YELLOW);
        xyplot.setRenderer(1, xylineandshaperenderer);
    }

    private void drawInputPoint(double x, double y) {
        // Create a new dataset with only one row
        XYSeriesCollection dataset = new XYSeriesCollection();
        String title = "Stock Date Distance: " + x + ", Stock Opening Price: " + y;
        XYSeries series = new XYSeries(title);
        series.add(x, y);
        dataset.addSeries(series);

        XYPlot plot = (XYPlot) chart.getPlot();
        plot.setDataset(2, dataset);
        XYItemRenderer renderer = new XYLineAndShapeRenderer(false, true);
        plot.setRenderer(2, renderer);
    }
}

1 Ответ

1 голос
/ 24 апреля 2020

Похоже, что вам нужна линия тренда на графике рассеяния, но вы можете создавать ненужные средства визуализации в дополнение к тому, которое было создано выбранным вами ChartFactory. Чтобы изучить проблему в отдельности, измените этот полный пример , чтобы создать точечную диаграмму, и измените существующее средство визуализации, чтобы при необходимости отобразить линию тренда.

JFreeChart chart = ChartFactory.createScatterPlot(…);
XYPlot plot = chart.getXYPlot();
XYLineAndShapeRenderer r = (XYLineAndShapeRenderer) plot.getRenderer();
r.setSeriesLinesVisible(1, Boolean.TRUE);
r.setSeriesShapesVisible(1, Boolean.FALSE);

image

Код:

import java.awt.Dimension;
import java.awt.EventQueue;
import java.util.Random;
import javax.swing.JFrame;
import org.jfree.chart.*;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.statistics.Regression;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

/**
 * @see https://stackoverflow.com/a/37716411/230513
 * @see http://stackoverflow.com/a/37716411/230513
 */
public class RegressionTest {

    private static final int N = 16;
    private static final Random R = new Random();

    private static XYDataset createDataset() {
        XYSeries series = new XYSeries("Data");
        for (int i = 0; i < N; i++) {
            series.add(i, R.nextGaussian() + i);
        }
        XYSeriesCollection xyData = new XYSeriesCollection(series);
        double[] coefficients = Regression.getOLSRegression(xyData, 0);
        double b = coefficients[0]; // intercept
        double m = coefficients[1]; // slope
        XYSeries trend = new XYSeries("Trend");
        double x = series.getDataItem(0).getXValue();
        trend.add(x, m * x + b);
        x = series.getDataItem(series.getItemCount() - 1).getXValue();
        trend.add(x, m * x + b);
        xyData.addSeries(trend);
        return xyData;
    }

    private static JFreeChart createChart(final XYDataset dataset) {
        JFreeChart chart = ChartFactory.createScatterPlot("Test", "X", "Y",
            dataset, PlotOrientation.VERTICAL, true, false, false);
        XYPlot plot = chart.getXYPlot();
        XYLineAndShapeRenderer r = (XYLineAndShapeRenderer) plot.getRenderer();
        r.setSeriesLinesVisible(1, Boolean.TRUE);
        r.setSeriesShapesVisible(1, Boolean.FALSE);
        return chart;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                XYDataset dataset = createDataset();
                JFreeChart chart = createChart(dataset);
                ChartPanel chartPanel = new ChartPanel(chart) {
                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(640, 480);
                    }
                };
                f.add(chartPanel);
                f.pack();
                f.setLocationRelativeTo(null);
                f.setVisible(true);
            }
        });
    }
}
...