package org.molgenis.charts.calculations;
import org.molgenis.charts.MolgenisChartException;
import java.util.List;
public class BoxPlotCalcUtil
{
/**
* calculates the 5 values needed to create a box plot and returns them in an 5 item sized array.
* <p>
* Double[0] = minimum;
* Double[1] = firstQuantile;
* Double[2] = median;
* Double[3] = thirdQuantile;
* Double[4] = maximum;
*
* @param sortedDataAscendingOrder
* @return Double[]
*/
public static Double[] calcBoxPlotValues(List<Double> sortedDataAscendingOrder)
{
if (null == sortedDataAscendingOrder)
{
throw new MolgenisChartException("The sortedDataAscendingOrder list is null");
}
if (sortedDataAscendingOrder.isEmpty())
{
return new Double[] { 0d, 0d, 0d, 0d, 0d };
}
Double[] plotBoxValues = new Double[5];
plotBoxValues[0] = minimum(sortedDataAscendingOrder);
plotBoxValues[1] = firstQuantile(sortedDataAscendingOrder);
plotBoxValues[2] = median(sortedDataAscendingOrder);
plotBoxValues[3] = thirdQuantile(sortedDataAscendingOrder);
plotBoxValues[4] = maximum(sortedDataAscendingOrder);
return plotBoxValues;
}
/**
* IQR inner quartile range
*
* @param thirdQuantile
* @param firstQuantile
* @return
*/
public static double iqr(double thirdQuantile, double firstQuantile)
{
return thirdQuantile - firstQuantile;
}
/**
* Get the minimum value thru linear interpolations
*
* @param sortedDataAscendingOrder
* @return Double
*/
public static Double minimum(List<Double> sortedDataAscendingOrder)
{
return interpolateLinearlyQuantile(sortedDataAscendingOrder, (double) 0);
}
/**
* Get the maximum value thru linear interpolations
*
* @param sortedDataAscendingOrder
* @return Double
*/
public static Double maximum(List<Double> sortedDataAscendingOrder)
{
return interpolateLinearlyQuantile(sortedDataAscendingOrder, (double) 1);
}
/**
* Get the median value thru linear interpolations
*
* @param sortedDataAscendingOrder
* @return Double
*/
public static Double median(List<Double> sortedDataAscendingOrder)
{
return interpolateLinearlyQuantile(sortedDataAscendingOrder, 0.50);
}
/**
* Get the firstQuantile value thru linear interpolations
*
* @param sortedDataAscendingOrder
* @return Double
*/
public static Double firstQuantile(List<Double> sortedDataAscendingOrder)
{
return interpolateLinearlyQuantile(sortedDataAscendingOrder, 0.25);
}
/**
* Get the thirdQuantile value thru linear interpolations
*
* @param sortedDataAscendingOrder
* @return Double
*/
public static Double thirdQuantile(List<Double> sortedDataAscendingOrder)
{
return interpolateLinearlyQuantile(sortedDataAscendingOrder, 0.75);
}
/**
* Interpolate linearly an quantile
* <p>
* Inspired on: http://msenux.redwoods.edu/math/R/boxplot.php
*
* @param sortedDataAscendingOrder sorted data in ascending order (NOT NULL)
* @param p percentage
* @return Double interpolated linearly quantile
*/
private static Double interpolateLinearlyQuantile(List<Double> sortedDataAscendingOrder, Double p)
{
int n = sortedDataAscendingOrder.size();
double position = (1 + (p * (n - 1)));
int leftIndex = (int) Math.floor(position) - 1;
int rightIndex = (int) Math.ceil(position) - 1;
Double quantile;
if (leftIndex == rightIndex)
{
quantile = sortedDataAscendingOrder.get(leftIndex);
}
else
{
Double leftIndexValue = sortedDataAscendingOrder.get(leftIndex);
Double rightIndexValue = sortedDataAscendingOrder.get(rightIndex);
quantile = leftIndexValue + 0.5 * (rightIndexValue - leftIndexValue);
}
return quantile;
}
}