JFreeChartを使って、2種類のグラフ (散布図と折れ線グラフ) を重ねて表示する。
ここでは、データをグラフに表示し、その中で極大値と極小値を表示するプログラムを書く。
ただし、コードを簡潔にするために解析用のデータはRandomで作成し、極大値と極小値の代わりに“5の倍数”と“8の倍数”の点をマークするプログラムを書いた。
import java.awt.BorderLayout; import java.awt.Color; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Random; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import org.jfree.chart.ChartColor; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.DatasetRenderingOrder; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; public class Plot extends JFrame implements ActionListener { Random rand = new Random(); int no = 30; //解析例用のデータを入れる配列 int data [] = new int [no]; //解析用データの作成 public void makeData (int [] data) { System.out.println("解析用のデータ:"); for (int i = 0; i < data.length; i++) { data [i] = rand.nextInt(100) + 1; System.out.print(data [i] + " "); } System.out.println(); } //Fig作成メソッド public void MakeFig (int no) { JFrame frame = new JFrame("ShowData"); frame.setBounds(200, 200, 400, 400); frame.setVisible(true); XYSeriesCollection plot = new XYSeriesCollection (); //5の倍数の値をプロット XYSeries plot5Series = new XYSeries("Multiple of 5"); for (int i = 1; i < no ; i++) { if (i* 5 >= no) break; plot5Series.add(i*5, data[i*5]); } //8の倍数の値をプロット XYSeries plot8Series = new XYSeries("Multiple of 8"); for (int i = 1; i < no ; i++) { if (i* 8 >= no) break; plot8Series.add(i*8, data[i*8]); } plot.addSeries(plot5Series); plot.addSeries(plot8Series); JFreeChart chart = ChartFactory.createScatterPlot( "Data", //タイトル "Frame", //x軸のラベル "Value", //y軸のラベル plot, //表示するデータ PlotOrientation.VERTICAL, //値が表す軸がy軸 true, //凡例の表示 false, //ツールチップを作成するか false); //URLを作成するか XYSeriesCollection rowData = new XYSeriesCollection (); XYSeries rowSeries = new XYSeries("Trace"); //折れ線グラフの作成 for (int i = 0; i < no; i++) { rowSeries.add(i, data[i]); } rowData.addSeries(rowSeries); XYPlot linePlot = chart.getXYPlot(); linePlot.setBackgroundPaint(Color.white); //グラフの背景を白に linePlot.setDataset(1, rowData); linePlot.mapDatasetToRangeAxis(1, 0); XYLineAndShapeRenderer render = new XYLineAndShapeRenderer(); linePlot.setRenderer(1, render); render.setSeriesPaint(0, ChartColor.BLACK); linePlot.setDatasetRenderingOrder(DatasetRenderingOrder.REVERSE); ChartPanel pane = new ChartPanel(chart); frame.add(pane); } public void actionPerformed (ActionEvent e) { String cmd = e.getActionCommand(); if (cmd.equals("button")) { makeData(data); MakeFig(no); } } Plot (String title) { setTitle(title); setSize(180, 80); setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); JButton button = new JButton("Show"); button.addActionListener (this); button.setActionCommand("button"); JPanel pane = new JPanel(); pane.add(button); getContentPane().add(pane, BorderLayout.CENTER); } public static void main(String[] args) { Plot frame = new Plot("Plot"); frame.setVisible(true); } }
このプログラムの実行結果例を下記に示す。
今回のプログラミングではグラフの作成にJFreeChartを使用しているため、本ソースコードを使うにはJFreeChart(JFreeChart)のインストールが必要となる。詳細な利用方法等は他のサイト(JFreeChartを使ったグラフ作成)を参照されたし。
時系列の折れ線グラフの特定のマーカー(極大値や極小値など)のみを標識するために、ここでは時系列折れ線グラフに散布図を重ねることにした。
実際のFig作成メソッドは下記の通り。
//Fig作成メソッド public void MakeFig (int no) { JFrame frame = new JFrame("ShowData"); frame.setBounds(200, 200, 400, 400); frame.setVisible(true); XYSeriesCollection plot = new XYSeriesCollection (); XYSeries plot5Series = new XYSeries("Multiple of 5"); for (int i = 1; i < no ; i++) { if (i* 5 >= no) break; plot5Series.add(i*5, data[i*5]); } XYSeries plot8Series = new XYSeries("Multiple of 8"); for (int i = 1; i < no ; i++) { if (i* 8 >= no) break; plot8Series.add(i*8, data[i*8]); } plot.addSeries(plot5Series); plot.addSeries(plot8Series); JFreeChart chart = ChartFactory.createScatterPlot( "Data", //タイトル "Frame", //x軸のラベル "Value", //y軸のラベル plot, //表示するデータ PlotOrientation.VERTICAL, //値が表す軸がy軸 true, //凡例の表示 false, //ツールチップを作成するか false); //URLを作成するか XYSeriesCollection rowData = new XYSeriesCollection (); XYSeries rowSeries = new XYSeries("Trace"); for (int i = 0; i < no; i++) { rowSeries.add(i, data[i]); } rowData.addSeries(rowSeries); XYPlot linePlot = chart.getXYPlot(); linePlot.setBackgroundPaint(Color.white); linePlot.setDataset(1, rowData); linePlot.mapDatasetToRangeAxis(1, 0); XYLineAndShapeRenderer render = new XYLineAndShapeRenderer(); linePlot.setRenderer(1, render); render.setSeriesPaint(0, ChartColor.BLACK); linePlot.setDatasetRenderingOrder(DatasetRenderingOrder.REVERSE); ChartPanel pane = new ChartPanel(chart); frame.add(pane); }
本来は元データの時系列折れ線グラフの上に散布図を重ねたかったのだが、知識不足のため散布図を作成後に折れ線グラフを重ねた(おそらく、Scatter plotのrendererの取得に失敗したため)。
JFreeChart chart = ChartFactory.createScatterPlot
この部分で、ScatterPlotを作成している。ここのScattePlotをXYLineChartに変えると時系列折れ線グラフが作成できる。
グラフの線やマーカーを変える場合は、
render.setShapesVisible(true); //マーカーの表示 render.setDrawOutlines(true); //マーカーの外枠の表示 render.setUseFillPaint(true); //マーカーの内を塗りつぶす render.setFillPaint(Color.GREEN); //マーカーを塗りつぶす色の指定 render.setSeriesStroke(0, new BasicStroke(3.0f)); //線を太くする render.setSeriesOutlineStroke(0, new BasicStroke(5.0f)); //マーカーの線を太くする。 render.setSeriesShape(0, new Ellipse2D.Double (-5.0, -5.0, 10.0, 10.0)); //マーカーの形を指定
などの方法がある。
今回用いた、5の倍数や8の倍数の値の代わりに、極大値、極小値の値を導入することでデータ内の極大値、極小値の位置を可視化できる。
ここまでの方法で、エクセルファイルからデータを読み込み、Peakの検出およびFig作成、解析結果のエクセルファイルへの書き出しが出来るはず。