BoxandWhisker timing plot
BoxandWhisker timing plot
Is it possible to do render a boxandwhisker chart with value domain and date/time range?
for example:
This is the normal way to fill the data:
[code]
private BoxAndWhiskerXYDataset createDataset() {
final int ENTITY_COUNT =1;
DefaultBoxAndWhiskerXYDataset dataset = new DefaultBoxAndWhiskerXYDataset("Test");
for (int i = 0; i < ENTITY_COUNT; i++) {
Date date = DateUtilities.createDate(2003, 7, i + 1, 12, 0);
List values = new ArrayList();
for (int j = 0; j < 2; j++) {
values.add(new Double(180000));
values.add(new Double(180000*1.05));
values.add(new Double(180000*1.10));
values.add(new Double(180000*1.15));
values.add(new Double(180000*1.20));
values.add(new Double(180000*1.25));
}
dataset.add(date, BoxAndWhiskerCalculator.calculateBoxAndWhiskerStatistics(values));
}
return dataset;
}[/code]
is it possible to modify existing add method it to accept following:
import org.joda.time;
...
private BoxAndWhiskerXYDataset createDataset() {
final int ENTITY_COUNT =1;
for (int i = 0; i < ENTITY_COUNT; i++) {
new Double ThresholdValue =180000;
List<LocalDate> localDates = new ArrayList();
LocalDate localDate = LocalDate.ofInstant( 2016 , 1 , 1 ) ;
for (int j = 0; j < 5; j++) {
localDates.add( localDate );
// Set up the next loop.
localDate = localDate.plusDays( 1 );
}
dataset.add(ThresholdValue, BoxAndWhiskerCalculator.calculateBoxAndWhiskerStatistics(localDate));
}
return dataset;
}
}[/code]
This is a BoxAndWhisker chart with a single fixed Y-value, the variable date_time value. It's looks like this: |----[ ]----| box will stretch by on x-axis for number of days in the list.
for example:
This is the normal way to fill the data:
[code]
private BoxAndWhiskerXYDataset createDataset() {
final int ENTITY_COUNT =1;
DefaultBoxAndWhiskerXYDataset dataset = new DefaultBoxAndWhiskerXYDataset("Test");
for (int i = 0; i < ENTITY_COUNT; i++) {
Date date = DateUtilities.createDate(2003, 7, i + 1, 12, 0);
List values = new ArrayList();
for (int j = 0; j < 2; j++) {
values.add(new Double(180000));
values.add(new Double(180000*1.05));
values.add(new Double(180000*1.10));
values.add(new Double(180000*1.15));
values.add(new Double(180000*1.20));
values.add(new Double(180000*1.25));
}
dataset.add(date, BoxAndWhiskerCalculator.calculateBoxAndWhiskerStatistics(values));
}
return dataset;
}[/code]
is it possible to modify existing add method it to accept following:
import org.joda.time;
...
private BoxAndWhiskerXYDataset createDataset() {
final int ENTITY_COUNT =1;
for (int i = 0; i < ENTITY_COUNT; i++) {
new Double ThresholdValue =180000;
List<LocalDate> localDates = new ArrayList();
LocalDate localDate = LocalDate.ofInstant( 2016 , 1 , 1 ) ;
for (int j = 0; j < 5; j++) {
localDates.add( localDate );
// Set up the next loop.
localDate = localDate.plusDays( 1 );
}
dataset.add(ThresholdValue, BoxAndWhiskerCalculator.calculateBoxAndWhiskerStatistics(localDate));
}
return dataset;
}
}[/code]
This is a BoxAndWhisker chart with a single fixed Y-value, the variable date_time value. It's looks like this: |----[ ]----| box will stretch by on x-axis for number of days in the list.
Last edited by bztom333 on Tue Aug 23, 2016 6:07 pm, edited 1 time in total.
-
- Posts: 1634
- Joined: Sat Feb 17, 2007 1:51 pm
Re: BoxandWhisker timing plot
You obviously can't use the LocalDate instance "localDate" as parameter for BoxAndWhiskerCalculator.calculateBoxAndWhiskerStatistics, but you could use the List instance localDates. This will lead to an Exception, since the BoxAndWhiskerCalculator assumes that the supplied list is list of Numbers, and a LocalDate is not a Number. You also can´t directly convert that to an e. g. long, because the time zone information is missing. So convert the LocalDate to LocalDateTime, convert that to a ZonedDateTime, and convert that to an Instant and finally a long by calling topEpochMillis().
Another suggetions: use instances of org.jfree.data.time.Day.
Another suggetions: use instances of org.jfree.data.time.Day.
Re: BoxandWhisker timing plot
I was hoping to modify the xybarrender to do render a boxandwhisker chart with DATE as timeline and a range is a NumberAxis.
Code: Select all
package misc.test;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RectangularShape;
import javax.swing.JPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.renderer.category.StandardBarPainter;
import org.jfree.chart.renderer.xy.GradientXYBarPainter;
import org.jfree.chart.renderer.xy.XYBarPainter;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.data.time.Day;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.xy.IntervalXYDataset;
import org.jfree.data.xy.XYIntervalSeries;
import org.jfree.data.xy.XYIntervalSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.RefineryUtilities;
/**
* A simple demonstration application showing an {@link MyXYBarRenderer}
* plotting data from a {@link XYIntervalSeriesCollection}.
*/
public class XYBarChartDemo7 extends ApplicationFrame {
/**
* Constructs the demo application.
*
* @param title the frame title.
*/
public XYBarChartDemo7(String title) {
super(title);
JPanel chartPanel = createDemoPanel();
chartPanel.setPreferredSize(new java.awt.Dimension(500, 300));
setContentPane(chartPanel);
}
private static JFreeChart createChart(IntervalXYDataset dataset) {
JFreeChart chart = ChartFactory.createXYBarChart("XYBarChartDemo7",
"Date", true, "Y", dataset, PlotOrientation.HORIZONTAL,
true, false, false);
XYPlot plot = (XYPlot) chart.getPlot();
//plot.setRangePannable(true);
plot.setRangeAxis(new DateAxis("Date"));
plot.setDomainAxis(new NumberAxis("CFS"));
XYBarRenderer renderer = (XYBarRenderer) plot.getRenderer() ;
renderer.setDrawBarOutline(true);
// renderer.setSeriesOutlinePaint(1,Color.BLACK);
// renderer.setSeriesOutlinePaint(2,Color.BLACK);
// renderer.setSeriesOutlinePaint(3,Color.BLACK);
renderer.setUseYInterval(true);
// renderer.setBaseItemLabelsVisible(true);
// renderer.setBaseFillPaint(Color.white);
XYBarPainter painter = new XYBarPainter() {
@Override
public void paintBarShadow(Graphics2D g2, XYBarRenderer renderer, int row, int column, RectangularShape bar, RectangleEdge base, boolean pegShadow) {
}
@Override
public void paintBar(Graphics2D g2, XYBarRenderer renderer, int row, int column, RectangularShape bar, RectangleEdge base) {
// TODO Auto-generated method stub
bar.setFrame(bar.getX(), bar.getY() , bar.getWidth() + 8, bar.getHeight());
// g2.setBackground(Color.GREEN);
//Shape box = new Rectangle2D.Double(bar.getX(), bar.getY() , bar.getWidth() + 8, bar.getHeight() );
g2.setColor(Color.BLACK);
g2.draw(bar);
/*double xxmid=bar.getCenterX();
double yyMax=bar.getMaxY();
double yyMin=bar.getMinY();
double xx=bar.getMinX();
double yyQ1=bar.getMinY();
double yyQ3=bar.getMaxY()*/;
// draw the upper whisker
//g2.draw(new Line2D.Double(xxmid, yyMax, xxmid, yyQ3));
// g2.draw(new Line2D.Double(xx, yyMax, xx + bar.getBounds().getCenterY(), yyMax));
// draw the lower whisker
// g2.draw(new Line2D.Double(xxmid, yyMin, xxmid, yyQ1));
// g2.draw(new Line2D.Double(xx, yyMin, xx + bar.getWidth(), yyMin));
}
};
renderer.setBarPainter(painter);
plot.setRenderer(renderer);
// plot.setBackgroundPaint(Color.lightGray);
// plot.setDomainGridlinePaint(Color.white);
// plot.setRangeGridlinePaint(Color.white);
// plot.setOutlinePaint(Color.black);
// ChartUtilities.applyCurrentTheme(chart);
return chart;
}
/**
* Creates a sample dataset.
*
* @return A dataset.
*/
private static IntervalXYDataset createDataset() {
Day d0 = new Day(12, 6, 2007);
Day d1 = new Day(13, 6, 2007);
Day d2 = new Day(14, 6, 2007);
Day d3 = new Day(15, 6, 2007);
Day d4 = new Day(16, 6, 2007);
Day d5 = new Day(17, 6, 2007);
XYIntervalSeriesCollection dataset = new XYIntervalSeriesCollection();
XYIntervalSeries s1 = new XYIntervalSeries("Sampson Road 57.7ft");
XYIntervalSeries s2 = new XYIntervalSeries("Uncle Joe Lane 65.7ft");
XYIntervalSeries s3 = new XYIntervalSeries("Bob Main Lain 77.2ft");
// addItem(s1, d0, d1, 1800);
//addItem(s1, d3, d3, 1000);
addItem(s2, d4, d5, 200);
addItem(s3, d3, d4, 2000);
dataset.addSeries(s1);
dataset.addSeries(s2);
dataset.addSeries(s3);
return dataset;
}
private static void addItem(XYIntervalSeries s, RegularTimePeriod p0,
RegularTimePeriod p1, int index) {
s.add(index, index - 0.45, index + 200.45, p0.getFirstMillisecond(),
p0.getFirstMillisecond(), p1.getLastMillisecond());
}
/**
* Creates a panel for the demo.
*
* @return A panel.
*/
public static JPanel createDemoPanel() {
return new ChartPanel(createChart(createDataset()));
}
/**
* Starting point for the demonstration application.
*
* @param args ignored.
*/
public static void main(String[] args) {
XYBarChartDemo7 demo = new XYBarChartDemo7(
"JFreeChart : BoxAndWhisker Timging Chart");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}
-
- Posts: 1634
- Joined: Sat Feb 17, 2007 1:51 pm
Re: BoxandWhisker timing plot
You are not using any of the BoxAndWhisker classes, half of the code is commented out, you are using a bar painter that does not fill the bars but only draws them, 3 of the 6 day instances and one of the 3 series is not used at all.
I really wonder what is the exact problem.
I really wonder what is the exact problem.
-
- Posts: 513
- Joined: Wed Sep 12, 2007 3:18 pm
Re: BoxandWhisker timing plot
You can use PlotOrientation.HORIZONTAL , as shown here and use a Date, or its formatted String, as the columnKey when adding data to an instance of DefaultBoxAndWhiskerCategoryDataset.
Re: BoxandWhisker timing plot
Great suggestion, however; is it possible to cast or override the string y-axis to be a number axis?
Want to draw some things like below:
Trying to plot...
For a given y value, there are potentially up to 21 value of dates. 1st date is valued at 0% increment. So 2nd day is valued @5%., 3rd date is valued at 10% and so on up to 100%.
I Only want to render one box and whisker chart that will stretch horizontally if more dated is added. See above Drawing.
I am trying to show the relationship of a given y value that % would likely to occur over the a periods of time,hence timing plot.
May be I was barking on the wrong tree.
Want to draw some things like below:
Code: Select all
10| |------[‾‾‾‾‾‾‾|‾‾‾‾‾]------|
| ‾‾‾‾‾‾‾‾‾‾‾‾
|
--------------d1----d2---d3-------------
For a given y value, there are potentially up to 21 value of dates. 1st date is valued at 0% increment. So 2nd day is valued @5%., 3rd date is valued at 10% and so on up to 100%.
I Only want to render one box and whisker chart that will stretch horizontally if more dated is added. See above Drawing.
I am trying to show the relationship of a given y value that % would likely to occur over the a periods of time,hence timing plot.
May be I was barking on the wrong tree.

-
- Posts: 513
- Joined: Wed Sep 12, 2007 3:18 pm
Re: BoxandWhisker timing plot
You could try using milliseconds for the values and a DateAxis for the domain.
Re: BoxandWhisker timing plot
This is the closest thing that I can sort of generate the desire plot for a " BoxAndWhisker Timing Plot". It would be nice if someone with intimate knowledge of the API framework to include a new enhancement in future release of the BoxAndWhiskerrenderer to allow a proper way to generate this kind of chart. Again, this is no mean the real thing.
Code: Select all
package misc.test;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import javax.swing.JPanel;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickUnit;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYBoxAndWhiskerRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.statistics.BoxAndWhiskerCalculator;
import org.jfree.data.statistics.BoxAndWhiskerXYDataset;
import org.jfree.data.statistics.DefaultBoxAndWhiskerXYDataset;
import org.jfree.data.time.Day;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
/**
* A simple demonstration application showing how to create a "box-and-whisker Timing "
* chart.
*/
public class BoxAndWhiskerChartTimingDemo extends ApplicationFrame {
/**
* Creates a new demo instance.
*
* @param title the frame title.
*/
public BoxAndWhiskerChartTimingDemo(String title) {
super(title);
JPanel chartPanel = createDemoPanel();
chartPanel.setPreferredSize(new Dimension(500, 270));
setContentPane(chartPanel);
}
NumberAxis xAxis = new NumberAxis("CFS");
XYPlot plot;
DateAxis dateaxis = new DateAxis("Ensemble Timing");
/**
* Returns a sample dataset.
*
* @return The dataset.
*/
private static BoxAndWhiskerXYDataset createDataset() {
final int VALUE_COUNT = 6;
DefaultBoxAndWhiskerXYDataset result = new DefaultBoxAndWhiskerXYDataset("Timing Series Demo");
RegularTimePeriod t = new Day();
for (int i = 0; i <1; i++) {
List values = createValueList(0, 100, VALUE_COUNT);
result.add(t.getStart(),
BoxAndWhiskerCalculator.calculateBoxAndWhiskerStatistics(values));
t = t.next();
}
return result;
}
private static List createValueList(double lowerBound, double upperBound, int count) {
List result = new java.util.ArrayList();
for (int i = 0; i<count; i++) {
result.add(new Double(5));
result.add(new Double(10));
result.add(new Double(15));
result.add(new Double(20));
result.add(new Double(25));
result.add(new Double(30));
}
return result;
}
/**
* Creates a sample chart.
*
* @param dataset the dataset.
*
* @return The chart.
*/
private JFreeChart createChart(BoxAndWhiskerXYDataset dataset) {
DateAxis domainAxis = new DateAxis("Day");
NumberAxis rangeAxis = new NumberAxis("Value");
XYItemRenderer renderer = new XYBoxAndWhiskerRenderer();
plot = new XYPlot(dataset, domainAxis, rangeAxis, renderer);
JFreeChart chart = new JFreeChart("Box-and-Whisker Chart Timing Plot", plot);
chart.setBackgroundPaint(Color.white);
plot.setOrientation(PlotOrientation.HORIZONTAL);
plot.setBackgroundPaint(Color.lightGray);
plot.setDomainGridlinePaint(Color.white);
plot.setDomainGridlinesVisible(true);
plot.setRangeGridlinePaint(Color.white);
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
rangeAxis.setVisible(false);
domainAxis.setVisible(false);
Date minDate = new Date();
Date maxDate = new Date();
String dateFormat = "MM/dd/yyyy HH:mm";
//set min and max range date
Calendar cal = new GregorianCalendar();
cal.setTime(minDate);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
minDate = cal.getTime();
cal.set(Calendar.HOUR_OF_DAY, 9);
maxDate = cal.getTime();
dateaxis.setRange(minDate, maxDate);
dateaxis.setDateFormatOverride(new SimpleDateFormat(dateFormat));
plot.setRangeAxis(1, dateaxis);
plot.setRangeAxisLocation(1,AxisLocation.BOTTOM_OR_RIGHT);
xAxis.setRange(100000,270000);
plot.setDomainAxis(1,xAxis);
plot.setDomainAxisLocation(1,AxisLocation.BOTTOM_OR_LEFT);
return chart;
}
/**
* Creates a panel for the demo (used by SuperDemo.java).
*
* @return A panel.
*/
public JPanel createDemoPanel() {
JFreeChart chart = createChart(createDataset());
return new MyChartPanel(chart);
}
/**
* Starting point for the demonstration application.
*
* @param args ignored.
*/
public static void main(String[] args) {
BoxAndWhiskerChartTimingDemo demo = new BoxAndWhiskerChartTimingDemo(
"Box-and-Whisker Timing Plot - Fake It Until You Make It.");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
public class MyChartPanel extends ChartPanel
{
public MyChartPanel(JFreeChart chart)
{
super(chart);
}
@Override
public void restoreAutoDomainBounds()
{
super.restoreAutoDomainBounds();
// Set your desired range
xAxis.setRange(100000,270000);
}
@Override
public void restoreAutoRangeBounds()
{
super.restoreAutoRangeBounds();
// Set your desired range
Date minDate = new Date();
Date maxDate = new Date();
String dateFormat = "MM/dd/yyyy HH:mm";
//set min and max range date
Calendar cal = new GregorianCalendar();
cal.setTime(minDate);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
minDate = cal.getTime();
cal.set(Calendar.HOUR_OF_DAY, 9);
maxDate = cal.getTime();
dateaxis.setRange(minDate, maxDate);
dateaxis.setDateFormatOverride(new SimpleDateFormat(dateFormat));
}
}
}
-
- Posts: 513
- Joined: Wed Sep 12, 2007 3:18 pm
Re: BoxandWhisker timing plot
Also consider the DateAxis methods setVerticalTickLabels and setDateFormatOverride.