/** * Calculates the third quartile for a list of numbers in ascending order. * * @param values the list of values. * @return The third quartile. */ public static double calculateQ3(final List values) { double result = Double.NaN; final int count = values.size(); if (count > 0) { if (count % 2 == 1) { if (count > 1) { result = Statistics.calculateMedian(values, count / 2 + 1, count - 1); } else { result = Statistics.calculateMedian(values, 0, 0); } } else { result = Statistics.calculateMedian(values, count / 2 + 1, count - 1); } } return result; }
/** * Calculates the statistics required for a {@link BoxAndWhiskerItem}. * * <p>Any items in the list that are not instances of the <code>Number</code> class are ignored. * Likewise, <code>null</code> values are ignored. * * @param values A list of numbers (a <code>null</code> list is not permitted). * @return Box-and-whisker statistics. */ public static BoxAndWhiskerItem calculateBoxAndWhiskerStatistics(final List values) { Collections.sort(values); final double mean = Statistics.calculateMean(values); final double median = Statistics.calculateMedian(values, false); final double q1 = calculateQ1(values); final double q3 = calculateQ3(values); final double interQuartileRange = q3 - q1; final double upperOutlierThreshold = q3 + (interQuartileRange * 1.5); final double lowerOutlierThreshold = q1 - (interQuartileRange * 1.5); final double upperFaroutThreshold = q3 + (interQuartileRange * 2.0); final double lowerFaroutThreshold = q1 - (interQuartileRange * 2.0); double minRegularValue = Double.POSITIVE_INFINITY; double maxRegularValue = Double.NEGATIVE_INFINITY; double minOutlier = Double.POSITIVE_INFINITY; double maxOutlier = Double.NEGATIVE_INFINITY; final List outliers = new ArrayList(); final Iterator iterator = values.iterator(); while (iterator.hasNext()) { final Object object = iterator.next(); if (object != null && object instanceof Number) { final Number number = (Number) object; final double value = number.doubleValue(); if (value > upperOutlierThreshold) { outliers.add(number); if (value > maxOutlier && value <= upperFaroutThreshold) { maxOutlier = value; } } else if (value < lowerOutlierThreshold) { outliers.add(number); if (value < minOutlier && value >= lowerFaroutThreshold) { minOutlier = value; } } else { if (minRegularValue == Double.NaN) { minRegularValue = value; } else { minRegularValue = Math.min(minRegularValue, value); } if (maxRegularValue == Double.NaN) { maxRegularValue = value; } else { maxRegularValue = Math.max(maxRegularValue, value); } } } } minOutlier = Math.min(minOutlier, minRegularValue); maxOutlier = Math.max(maxOutlier, maxRegularValue); return new BoxAndWhiskerItem( new Double(mean), new Double(median), new Double(q1), new Double(q3), new Double(minRegularValue), new Double(maxRegularValue), new Double(minOutlier), new Double(maxOutlier), outliers); }