What does size of median circle on BoxAndWhisker mean ?
What does size of median circle on BoxAndWhisker mean ?
Is there any significance to the size of the median circle on the box and whisker plot or is it just meant to scale up with size of the box ?
Reason being if I have a really wide (vertical) box the circle gets so big it looks stupid... Does it need to be there or could it be a fixed maximum size ? (In the code it's radius is /4 box width) ??
Reason being if I have a really wide (vertical) box the circle gets so big it looks stupid... Does it need to be there or could it be a fixed maximum size ? (In the code it's radius is /4 box width) ??
-
- Posts: 3
- Joined: Fri Jan 25, 2008 7:10 pm
To get around this problem I copied the BoxAndWhiskerRenderer class and created my own class called MyBoxAndWhiskerRenderer. I then added the following attributes:
I then modified the drawVerticalItem method by adding the following code:
Make sure to replace all instances of state.getBarWidth() with barWidth
then for the mean after aRadius = barWidth / 4, add:
The resulting drawVerticalItem method is:
Code: Select all
private double fixedRadius = -1;
public void setFixedRadius(double value) { fixedRadius = value; }
public double getFixedRadius() { return fixedRadius; }
private double fixedBarWidth = -1;
public void setFixedBarWidth(double value) { fixedBarWidth = value; }
public double getFixedBarWidth() { return fixedBarWidth; }
Code: Select all
double barWidth = state.getBarWidth();
if (fixedBarWidth > 0)
barWidth = fixedBarWidth;
then for the mean after aRadius = barWidth / 4, add:
Code: Select all
if (fixedRadius > 0)
aRadius = fixedRadius;
Code: Select all
public void drawVerticalItem(Graphics2D g2,
CategoryItemRendererState state,
Rectangle2D dataArea,
CategoryPlot plot,
CategoryAxis domainAxis,
ValueAxis rangeAxis,
CategoryDataset dataset,
int row,
int column) {
BoxAndWhiskerCategoryDataset bawDataset
= (BoxAndWhiskerCategoryDataset) dataset;
double categoryEnd = domainAxis.getCategoryEnd(column,
getColumnCount(), dataArea, plot.getDomainAxisEdge());
double categoryStart = domainAxis.getCategoryStart(column,
getColumnCount(), dataArea, plot.getDomainAxisEdge());
double categoryWidth = categoryEnd - categoryStart;
// Custom Code
double barWidth = state.getBarWidth();
if (fixedBarWidth > 0)
barWidth = fixedBarWidth;
double xx = categoryStart;
int seriesCount = getRowCount();
int categoryCount = getColumnCount();
if (seriesCount > 1) {
double seriesGap = dataArea.getWidth() * getItemMargin()
/ (categoryCount * (seriesCount - 1));
double usedWidth = (barWidth * seriesCount)
+ (seriesGap * (seriesCount - 1));
// offset the start of the boxes if the total width used is smaller
// than the category width
double offset = (categoryWidth - usedWidth) / 2;
xx = xx + offset + (row * (barWidth + seriesGap));
}
else {
// offset the start of the box if the box width is smaller than the
// category width
double offset = (categoryWidth - barWidth) / 2;
xx = xx + offset;
}
double yyAverage = 0.0;
double yyOutlier;
Paint p = getItemPaint(row, column);
if (p != null) {
g2.setPaint(p);
}
Stroke s = getItemStroke(row, column);
g2.setStroke(s);
double aRadius = 0; // average radius
RectangleEdge location = plot.getRangeAxisEdge();
Number yQ1 = bawDataset.getQ1Value(row, column);
Number yQ3 = bawDataset.getQ3Value(row, column);
Number yMax = bawDataset.getMaxRegularValue(row, column);
Number yMin = bawDataset.getMinRegularValue(row, column);
Shape box = null;
if (yQ1 != null && yQ3 != null && yMax != null && yMin != null) {
double yyQ1 = rangeAxis.valueToJava2D(yQ1.doubleValue(), dataArea,
location);
double yyQ3 = rangeAxis.valueToJava2D(yQ3.doubleValue(), dataArea,
location);
double yyMax = rangeAxis.valueToJava2D(yMax.doubleValue(),
dataArea, location);
double yyMin = rangeAxis.valueToJava2D(yMin.doubleValue(),
dataArea, location);
double xxmid = xx + barWidth / 2.0;
// draw the upper shadow...
g2.draw(new Line2D.Double(xxmid, yyMax, xxmid, yyQ3));
g2.draw(new Line2D.Double(xx, yyMax, xx + barWidth,
yyMax));
// draw the lower shadow...
g2.draw(new Line2D.Double(xxmid, yyMin, xxmid, yyQ1));
g2.draw(new Line2D.Double(xx, yyMin, xx + barWidth,
yyMin));
// draw the body...
box = new Rectangle2D.Double(xx, Math.min(yyQ1, yyQ3),
barWidth, Math.abs(yyQ1 - yyQ3));
if (this.fillBox) {
g2.fill(box);
}
g2.draw(box);
}
g2.setPaint(this.artifactPaint);
// draw mean - SPECIAL AIMS REQUIREMENT...
Number yMean = bawDataset.getMeanValue(row, column);
if (yMean != null) {
yyAverage = rangeAxis.valueToJava2D(yMean.doubleValue(),
dataArea, location);
aRadius = barWidth / 4;
// Custom Code
if (fixedRadius > 0)
aRadius = fixedRadius;
// here we check that the average marker will in fact be visible
// before drawing it...
if ((yyAverage > (dataArea.getMinY() - aRadius))
&& (yyAverage < (dataArea.getMaxY() + aRadius))) {
Ellipse2D.Double avgEllipse = new Ellipse2D.Double(xx + (barWidth/2 - aRadius),
yyAverage - aRadius, aRadius * 2, aRadius * 2);
g2.fill(avgEllipse);
g2.draw(avgEllipse);
}
}
// draw median...
Number yMedian = bawDataset.getMedianValue(row, column);
if (yMedian != null) {
double yyMedian = rangeAxis.valueToJava2D(yMedian.doubleValue(),
dataArea, location);
g2.draw(new Line2D.Double(xx, yyMedian, xx + barWidth,
yyMedian));
}
// draw yOutliers...
double maxAxisValue = rangeAxis.valueToJava2D(
rangeAxis.getUpperBound(), dataArea, location) + aRadius;
double minAxisValue = rangeAxis.valueToJava2D(
rangeAxis.getLowerBound(), dataArea, location) - aRadius;
g2.setPaint(p);
// draw outliers
double oRadius = barWidth / 3; // outlier radius
List outliers = new ArrayList();
OutlierListCollection outlierListCollection
= new OutlierListCollection();
// From outlier array sort out which are outliers and put these into a
// list If there are any farouts, set the flag on the
// OutlierListCollection
List yOutliers = bawDataset.getOutliers(row, column);
if (yOutliers != null) {
for (int i = 0; i < yOutliers.size(); i++) {
double outlier = ((Number) yOutliers.get(i)).doubleValue();
Number minOutlier = bawDataset.getMinOutlier(row, column);
Number maxOutlier = bawDataset.getMaxOutlier(row, column);
Number minRegular = bawDataset.getMinRegularValue(row, column);
Number maxRegular = bawDataset.getMaxRegularValue(row, column);
if (outlier > maxOutlier.doubleValue()) {
outlierListCollection.setHighFarOut(true);
}
else if (outlier < minOutlier.doubleValue()) {
outlierListCollection.setLowFarOut(true);
}
else if (outlier > maxRegular.doubleValue()) {
yyOutlier = rangeAxis.valueToJava2D(outlier, dataArea,
location);
outliers.add(new Outlier(xx + barWidth / 2.0,
yyOutlier, oRadius));
}
else if (outlier < minRegular.doubleValue()) {
yyOutlier = rangeAxis.valueToJava2D(outlier, dataArea,
location);
outliers.add(new Outlier(xx + barWidth / 2.0,
yyOutlier, oRadius));
}
Collections.sort(outliers);
}
// Process outliers. Each outlier is either added to the
// appropriate outlier list or a new outlier list is made
for (Iterator iterator = outliers.iterator(); iterator.hasNext();) {
Outlier outlier = (Outlier) iterator.next();
outlierListCollection.add(outlier);
}
for (Iterator iterator = outlierListCollection.iterator();
iterator.hasNext();) {
OutlierList list = (OutlierList) iterator.next();
Outlier outlier = list.getAveragedOutlier();
Point2D point = outlier.getPoint();
if (list.isMultiple()) {
drawMultipleEllipse(point, barWidth, oRadius,
g2);
}
else {
drawEllipse(point, oRadius, g2);
}
}
// draw farout indicators
if (outlierListCollection.isHighFarOut()) {
drawHighFarOut(aRadius / 2.0, g2,
xx + barWidth / 2.0, maxAxisValue);
}
if (outlierListCollection.isLowFarOut()) {
drawLowFarOut(aRadius / 2.0, g2,
xx + barWidth / 2.0, minAxisValue);
}
}
// collect entity and tool tip information...
if (state.getInfo() != null && box != null) {
EntityCollection entities = state.getEntityCollection();
if (entities != null) {
String tip = null;
CategoryToolTipGenerator tipster
= getToolTipGenerator(row, column);
if (tipster != null) {
tip = tipster.generateToolTip(dataset, row, column);
}
String url = null;
if (getItemURLGenerator(row, column) != null) {
url = getItemURLGenerator(row, column).generateURL(dataset,
row, column);
}
CategoryItemEntity entity = new CategoryItemEntity(box, tip,
url, dataset, dataset.getRowKey(row),
dataset.getColumnKey(column));
entities.add(entity);
}
}
}
-
- Posts: 59
- Joined: Fri Feb 23, 2007 7:41 am
Hi,
I had submitted a patch sometime back addressing this issue of large circles and triangles(mean, outliers and farouts) when the no. of groups in the chart is small.
The circles and triangles are of a fixed size irrespective of the no. of groups. You can find this in sourceforge under patches. Search for "New BoxAndWhiskerRenderer".
I'm not sure if David is planning to include these changes in the next version.
Regards,
Priya
I had submitted a patch sometime back addressing this issue of large circles and triangles(mean, outliers and farouts) when the no. of groups in the chart is small.
The circles and triangles are of a fixed size irrespective of the no. of groups. You can find this in sourceforge under patches. Search for "New BoxAndWhiskerRenderer".
I'm not sure if David is planning to include these changes in the next version.
Regards,
Priya
-
- Posts: 10
- Joined: Wed Apr 18, 2007 8:37 pm
Re: What does size of median circle on BoxAndWhisker mean ?
I'm trying to create a Box and Whisker with only with "box and whisker" (or one set of data to apply). Upon display (as I'm assuming most of you here with similar troubles) there is a rather large black dot. Is there a way to remove or at least make this circle much smaller as it's blocking out just about everything else in the display? Thanks.
-
- Posts: 513
- Joined: Wed Sep 12, 2007 3:18 pm
Re: What does size of median circle on BoxAndWhisker mean ?
I haven't tested it, but the renderer's setMeanVisible() method appears to control this.
Re: What does size of median circle on BoxAndWhisker mean ?
spyderman03 wrote:To get around this problem I copied the BoxAndWhiskerRenderer class and created my own class called MyBoxAndWhiskerRenderer. I then added the following attributes:
I then modified the drawVerticalItem method by adding the following code:Code: Select all
private double fixedRadius = -1; public void setFixedRadius(double value) { fixedRadius = value; } public double getFixedRadius() { return fixedRadius; } private double fixedBarWidth = -1; public void setFixedBarWidth(double value) { fixedBarWidth = value; } public double getFixedBarWidth() { return fixedBarWidth; }
Make sure to replace all instances of state.getBarWidth() with barWidthCode: Select all
double barWidth = state.getBarWidth(); if (fixedBarWidth > 0) barWidth = fixedBarWidth;
then for the mean after aRadius = barWidth / 4, add:The resulting drawVerticalItem method is:Code: Select all
if (fixedRadius > 0) aRadius = fixedRadius;
Code: Select all
public void drawVerticalItem(Graphics2D g2, CategoryItemRendererState state, Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis, ValueAxis rangeAxis, CategoryDataset dataset, int row, int column) { BoxAndWhiskerCategoryDataset bawDataset = (BoxAndWhiskerCategoryDataset) dataset; double categoryEnd = domainAxis.getCategoryEnd(column, getColumnCount(), dataArea, plot.getDomainAxisEdge()); double categoryStart = domainAxis.getCategoryStart(column, getColumnCount(), dataArea, plot.getDomainAxisEdge()); double categoryWidth = categoryEnd - categoryStart; // Custom Code double barWidth = state.getBarWidth(); if (fixedBarWidth > 0) barWidth = fixedBarWidth; double xx = categoryStart; int seriesCount = getRowCount(); int categoryCount = getColumnCount(); if (seriesCount > 1) { double seriesGap = dataArea.getWidth() * getItemMargin() / (categoryCount * (seriesCount - 1)); double usedWidth = (barWidth * seriesCount) + (seriesGap * (seriesCount - 1)); // offset the start of the boxes if the total width used is smaller // than the category width double offset = (categoryWidth - usedWidth) / 2; xx = xx + offset + (row * (barWidth + seriesGap)); } else { // offset the start of the box if the box width is smaller than the // category width double offset = (categoryWidth - barWidth) / 2; xx = xx + offset; } double yyAverage = 0.0; double yyOutlier; Paint p = getItemPaint(row, column); if (p != null) { g2.setPaint(p); } Stroke s = getItemStroke(row, column); g2.setStroke(s); double aRadius = 0; // average radius RectangleEdge location = plot.getRangeAxisEdge(); Number yQ1 = bawDataset.getQ1Value(row, column); Number yQ3 = bawDataset.getQ3Value(row, column); Number yMax = bawDataset.getMaxRegularValue(row, column); Number yMin = bawDataset.getMinRegularValue(row, column); Shape box = null; if (yQ1 != null && yQ3 != null && yMax != null && yMin != null) { double yyQ1 = rangeAxis.valueToJava2D(yQ1.doubleValue(), dataArea, location); double yyQ3 = rangeAxis.valueToJava2D(yQ3.doubleValue(), dataArea, location); double yyMax = rangeAxis.valueToJava2D(yMax.doubleValue(), dataArea, location); double yyMin = rangeAxis.valueToJava2D(yMin.doubleValue(), dataArea, location); double xxmid = xx + barWidth / 2.0; // draw the upper shadow... g2.draw(new Line2D.Double(xxmid, yyMax, xxmid, yyQ3)); g2.draw(new Line2D.Double(xx, yyMax, xx + barWidth, yyMax)); // draw the lower shadow... g2.draw(new Line2D.Double(xxmid, yyMin, xxmid, yyQ1)); g2.draw(new Line2D.Double(xx, yyMin, xx + barWidth, yyMin)); // draw the body... box = new Rectangle2D.Double(xx, Math.min(yyQ1, yyQ3), barWidth, Math.abs(yyQ1 - yyQ3)); if (this.fillBox) { g2.fill(box); } g2.draw(box); } g2.setPaint(this.artifactPaint); // draw mean - SPECIAL AIMS REQUIREMENT... Number yMean = bawDataset.getMeanValue(row, column); if (yMean != null) { yyAverage = rangeAxis.valueToJava2D(yMean.doubleValue(), dataArea, location); aRadius = barWidth / 4; // Custom Code if (fixedRadius > 0) aRadius = fixedRadius; // here we check that the average marker will in fact be visible // before drawing it... if ((yyAverage > (dataArea.getMinY() - aRadius)) && (yyAverage < (dataArea.getMaxY() + aRadius))) { Ellipse2D.Double avgEllipse = new Ellipse2D.Double(xx + (barWidth/2 - aRadius), yyAverage - aRadius, aRadius * 2, aRadius * 2); g2.fill(avgEllipse); g2.draw(avgEllipse); } } // draw median... Number yMedian = bawDataset.getMedianValue(row, column); if (yMedian != null) { double yyMedian = rangeAxis.valueToJava2D(yMedian.doubleValue(), dataArea, location); g2.draw(new Line2D.Double(xx, yyMedian, xx + barWidth, yyMedian)); } // draw yOutliers... double maxAxisValue = rangeAxis.valueToJava2D( rangeAxis.getUpperBound(), dataArea, location) + aRadius; double minAxisValue = rangeAxis.valueToJava2D( rangeAxis.getLowerBound(), dataArea, location) - aRadius; g2.setPaint(p); // draw outliers double oRadius = barWidth / 3; // outlier radius List outliers = new ArrayList(); OutlierListCollection outlierListCollection = new OutlierListCollection(); // From outlier array sort out which are outliers and put these into a // list If there are any farouts, set the flag on the // OutlierListCollection List yOutliers = bawDataset.getOutliers(row, column); if (yOutliers != null) { for (int i = 0; i < yOutliers.size(); i++) { double outlier = ((Number) yOutliers.get(i)).doubleValue(); Number minOutlier = bawDataset.getMinOutlier(row, column); Number maxOutlier = bawDataset.getMaxOutlier(row, column); Number minRegular = bawDataset.getMinRegularValue(row, column); Number maxRegular = bawDataset.getMaxRegularValue(row, column); if (outlier > maxOutlier.doubleValue()) { outlierListCollection.setHighFarOut(true); } else if (outlier < minOutlier.doubleValue()) { outlierListCollection.setLowFarOut(true); } else if (outlier > maxRegular.doubleValue()) { yyOutlier = rangeAxis.valueToJava2D(outlier, dataArea, location); outliers.add(new Outlier(xx + barWidth / 2.0, yyOutlier, oRadius)); } else if (outlier < minRegular.doubleValue()) { yyOutlier = rangeAxis.valueToJava2D(outlier, dataArea, location); outliers.add(new Outlier(xx + barWidth / 2.0, yyOutlier, oRadius)); } Collections.sort(outliers); } // Process outliers. Each outlier is either added to the // appropriate outlier list or a new outlier list is made for (Iterator iterator = outliers.iterator(); iterator.hasNext();) { Outlier outlier = (Outlier) iterator.next(); outlierListCollection.add(outlier); } for (Iterator iterator = outlierListCollection.iterator(); iterator.hasNext();) { OutlierList list = (OutlierList) iterator.next(); Outlier outlier = list.getAveragedOutlier(); Point2D point = outlier.getPoint(); if (list.isMultiple()) { drawMultipleEllipse(point, barWidth, oRadius, g2); } else { drawEllipse(point, oRadius, g2); } } // draw farout indicators if (outlierListCollection.isHighFarOut()) { drawHighFarOut(aRadius / 2.0, g2, xx + barWidth / 2.0, maxAxisValue); } if (outlierListCollection.isLowFarOut()) { drawLowFarOut(aRadius / 2.0, g2, xx + barWidth / 2.0, minAxisValue); } } // collect entity and tool tip information... if (state.getInfo() != null && box != null) { EntityCollection entities = state.getEntityCollection(); if (entities != null) { String tip = null; CategoryToolTipGenerator tipster = getToolTipGenerator(row, column); if (tipster != null) { tip = tipster.generateToolTip(dataset, row, column); } String url = null; if (getItemURLGenerator(row, column) != null) { url = getItemURLGenerator(row, column).generateURL(dataset, row, column); } CategoryItemEntity entity = new CategoryItemEntity(box, tip, url, dataset, dataset.getRowKey(row), dataset.getColumnKey(column)); entities.add(entity); } } }
Thank you very VERY much spyderman03.
You're really help me!!!

Regards,
Joaquín