Hi
Now I take a look for you great job with JFreeChart.
I want to ask how can I convert a XYDataset to XYSeries ?
I have a XYSeriesCollection and I want to add a XYDataset but the method
void addSeries(XYSeries series)
requires a XYSeries.
I want to make a chart starting from your examples with moving average but having on the same chart many moving average (at diferent periods) for the same share. This is the reason I need the conversion XYDataset to XYSeries.
Do you have any another idea how can I make a chart with many movavg?
thanks in advance.
Conevrt XYDataset to XYSeries
Re: Conevrt XYDataset to XYSeries
Hi Daniel,
I think the moving average calculation code in the demo needs updating. I'd create a new XYSeries (or better still BasicTimeSeries) for each moving average, based on data in another XYSeries or BasicTimeSeries. Then add them all to one XYSeriesCollection/TimeSeriesCollection.
Regards,
DG.
I think the moving average calculation code in the demo needs updating. I'd create a new XYSeries (or better still BasicTimeSeries) for each moving average, based on data in another XYSeries or BasicTimeSeries. Then add them all to one XYSeriesCollection/TimeSeriesCollection.
Regards,
DG.
a possible solution
Hi David
I have a solution and I want to know if it is a good one, anyway it works and for me it is ok.
First problem: The classes PlotFit and MovingAveragePlotFitAlgorithm are working with XYDataset. I tryed to use BasicTimeSeries but I did't succed and finaly I decided to let data in the XYDataset format which I think is the best way and it is enought to solve all problem.
The main problem, class PlotFit have the method:
public XYDataset getFit()
that returns a new XYDataset with BOTH datas (before applying the algorithm and data results from algorithm)
and here I need a method that returns only the XYDataset results from algorithm.
I chose to write a new class. Here is the code:
-----------------------
public class NewPlotFit extends PlotFit
{
public NewPlotFit(XYDataset data, PlotFitAlgorithm alg)
{
super(data,alg);
}
public Object[][][] getResults() {
/* set up our algorithm */
alg.setXYDataset(dataset);
/* make a data container big enough to hold it all */
int arraysize = 0;
int seriescount = dataset.getSeriesCount();
for(int i = 0; i < seriescount; i++) {
if(dataset.getItemCount(i) > arraysize) {
arraysize = dataset.getItemCount(i);
}
}
// we'll apply the plot fit to all of the series for now
Object[][][] newdata = new Object[seriescount /* * 2*/][arraysize][2];
/* copy in the series to the first half */
for(int i = 0; i < seriescount; i++) {
for(int j = 0; j < dataset.getItemCount(i); j++) {
Number x = dataset.getXValue(i,j);
// newdata[j][0] = x;
// newdata[j][1] = dataset.getYValue(i,j);
Number y = alg.getY(i, x);
/*
* only want to set data for non-null algorithm fits.
* This allows things like moving average plots, or partial
* plots to return null and not get NPEs when the chart is
* created
*/
if(y != null) {
newdata[i /*+ seriescount*/][j][0] = x;
newdata[i /*+ seriescount*/][j][1] = y;
}
else {
newdata[i /*+ seriescount*/][j][0] = null;
newdata[i /*+ seriescount*/][j][1] = null;
}
}
}
return newdata;
}
public XYDataset getFit() {
int seriescount = dataset.getSeriesCount();
String[] seriesnames = new String[seriescount /* * 2*/];
for(int i = 0; i < seriescount; i++) {
// seriesnames = dataset.getSeriesName(i);
seriesnames[i /*+ seriescount*/] = dataset.getSeriesName(i) + " " + alg.getName();
}
return new DefaultXYDataset(seriesnames, getResults());
}
}
-----------------------
then I need a method to concatenate two XYDataset.
the code is:
-----------------------
public XYDataset JoinXYDataset(XYDataset data1, XYDataset data2)
{
int arraysize = 0;
int seriescount1 = data1.getSeriesCount();
for(int i = 0; i < seriescount1; i++)
{
if(data1.getItemCount(i) > arraysize)
{
arraysize = data1.getItemCount(i);
}
}
int seriescount2 = data2.getSeriesCount();
for(int i = 0; i < seriescount2; i++)
{
if(data2.getItemCount(i) > arraysize)
{
arraysize = data2.getItemCount(i);
}
}
Object[][][] newdata = new Object[seriescount1 + seriescount2][arraysize][2];
String[] seriesnames = new String[seriescount1 + seriescount2];
for(int i = 0; i < seriescount1; i++)
{
for(int j = 0; j < data1.getItemCount(i); j++)
{
newdata[j][0] = data1.getXValue(i,j);
newdata[j][1] = data1.getYValue(i,j);
}
seriesnames = data1.getSeriesName(i);
}
for(int i = 0; i < seriescount2; i++)
{
for(int j = 0; j < data2.getItemCount(i); j++)
{
newdata[i + seriescount1][j][0] = data2.getXValue(i,j);
newdata[i + seriescount1][j][1] = data2.getYValue(i,j);
}
seriesnames[i + seriescount1] = data2.getSeriesName(i);
}
return new DefaultXYDataset(seriesnames, newdata);
}
-----------------------
finaly the method createChart from class JFreeChartServletDemo should be modify with:
-----------------------
case 8:
// moving avg
XYDataset xyData = DemoDatasetFactory.createTimeSeriesCollection3();
MovingAveragePlotFitAlgorithm mavg1 = new MovingAveragePlotFitAlgorithm();
mavg1.setPeriod(15);
NewPlotFit pf1 = new NewPlotFit(xyData, mavg1);
XYDataset xyData1 = pf1.getFit();
MovingAveragePlotFitAlgorithm mavg2 = new MovingAveragePlotFitAlgorithm();
mavg2.setPeriod(45);
NewPlotFit pf2 = new NewPlotFit(xyData, mavg2);
XYDataset xyData2 = pf2.getFit();
xyData = JoinXYDataset(xyData, xyData1);
xyData = JoinXYDataset(xyData, xyData2);
chart = ChartFactory.createTimeSeriesChart("Moving Average", "Date", "Value",
xyData, true);
-----------------------
and will draw two Moving Average with period of 15 and 45.
What do you think about this solution?
Or is it another shorter way that I didn't find it?
All the best,
Daniel
I have a solution and I want to know if it is a good one, anyway it works and for me it is ok.
First problem: The classes PlotFit and MovingAveragePlotFitAlgorithm are working with XYDataset. I tryed to use BasicTimeSeries but I did't succed and finaly I decided to let data in the XYDataset format which I think is the best way and it is enought to solve all problem.
The main problem, class PlotFit have the method:
public XYDataset getFit()
that returns a new XYDataset with BOTH datas (before applying the algorithm and data results from algorithm)
and here I need a method that returns only the XYDataset results from algorithm.
I chose to write a new class. Here is the code:
-----------------------
public class NewPlotFit extends PlotFit
{
public NewPlotFit(XYDataset data, PlotFitAlgorithm alg)
{
super(data,alg);
}
public Object[][][] getResults() {
/* set up our algorithm */
alg.setXYDataset(dataset);
/* make a data container big enough to hold it all */
int arraysize = 0;
int seriescount = dataset.getSeriesCount();
for(int i = 0; i < seriescount; i++) {
if(dataset.getItemCount(i) > arraysize) {
arraysize = dataset.getItemCount(i);
}
}
// we'll apply the plot fit to all of the series for now
Object[][][] newdata = new Object[seriescount /* * 2*/][arraysize][2];
/* copy in the series to the first half */
for(int i = 0; i < seriescount; i++) {
for(int j = 0; j < dataset.getItemCount(i); j++) {
Number x = dataset.getXValue(i,j);
// newdata[j][0] = x;
// newdata[j][1] = dataset.getYValue(i,j);
Number y = alg.getY(i, x);
/*
* only want to set data for non-null algorithm fits.
* This allows things like moving average plots, or partial
* plots to return null and not get NPEs when the chart is
* created
*/
if(y != null) {
newdata[i /*+ seriescount*/][j][0] = x;
newdata[i /*+ seriescount*/][j][1] = y;
}
else {
newdata[i /*+ seriescount*/][j][0] = null;
newdata[i /*+ seriescount*/][j][1] = null;
}
}
}
return newdata;
}
public XYDataset getFit() {
int seriescount = dataset.getSeriesCount();
String[] seriesnames = new String[seriescount /* * 2*/];
for(int i = 0; i < seriescount; i++) {
// seriesnames = dataset.getSeriesName(i);
seriesnames[i /*+ seriescount*/] = dataset.getSeriesName(i) + " " + alg.getName();
}
return new DefaultXYDataset(seriesnames, getResults());
}
}
-----------------------
then I need a method to concatenate two XYDataset.
the code is:
-----------------------
public XYDataset JoinXYDataset(XYDataset data1, XYDataset data2)
{
int arraysize = 0;
int seriescount1 = data1.getSeriesCount();
for(int i = 0; i < seriescount1; i++)
{
if(data1.getItemCount(i) > arraysize)
{
arraysize = data1.getItemCount(i);
}
}
int seriescount2 = data2.getSeriesCount();
for(int i = 0; i < seriescount2; i++)
{
if(data2.getItemCount(i) > arraysize)
{
arraysize = data2.getItemCount(i);
}
}
Object[][][] newdata = new Object[seriescount1 + seriescount2][arraysize][2];
String[] seriesnames = new String[seriescount1 + seriescount2];
for(int i = 0; i < seriescount1; i++)
{
for(int j = 0; j < data1.getItemCount(i); j++)
{
newdata[j][0] = data1.getXValue(i,j);
newdata[j][1] = data1.getYValue(i,j);
}
seriesnames = data1.getSeriesName(i);
}
for(int i = 0; i < seriescount2; i++)
{
for(int j = 0; j < data2.getItemCount(i); j++)
{
newdata[i + seriescount1][j][0] = data2.getXValue(i,j);
newdata[i + seriescount1][j][1] = data2.getYValue(i,j);
}
seriesnames[i + seriescount1] = data2.getSeriesName(i);
}
return new DefaultXYDataset(seriesnames, newdata);
}
-----------------------
finaly the method createChart from class JFreeChartServletDemo should be modify with:
-----------------------
case 8:
// moving avg
XYDataset xyData = DemoDatasetFactory.createTimeSeriesCollection3();
MovingAveragePlotFitAlgorithm mavg1 = new MovingAveragePlotFitAlgorithm();
mavg1.setPeriod(15);
NewPlotFit pf1 = new NewPlotFit(xyData, mavg1);
XYDataset xyData1 = pf1.getFit();
MovingAveragePlotFitAlgorithm mavg2 = new MovingAveragePlotFitAlgorithm();
mavg2.setPeriod(45);
NewPlotFit pf2 = new NewPlotFit(xyData, mavg2);
XYDataset xyData2 = pf2.getFit();
xyData = JoinXYDataset(xyData, xyData1);
xyData = JoinXYDataset(xyData, xyData2);
chart = ChartFactory.createTimeSeriesChart("Moving Average", "Date", "Value",
xyData, true);
-----------------------
and will draw two Moving Average with period of 15 and 45.
What do you think about this solution?
Or is it another shorter way that I didn't find it?

All the best,
Daniel