/** * Calculate the average value but removing outliers based on Median Absolute Deviation with a * fixed threshold of 3.0 TODO make the threshold be the first parameter in the list or make a * smarter analysis of method to use, not just MAD, based on the number of data in the set, * variance, etc */ @SuppressWarnings("unchecked") @Override public void run(Stack stack) throws ParseException { checkStack(stack); if (curNumberOfParameters < 1) { throw new ParseException("No arguments for Average MAD - median average deviation"); } // Get the first parameter that has to be the threshold // Double threshold = (Double) stack.pop(); Double threshold = 3.0; Object param; ArrayList<Double> orginalValues = new ArrayList<Double>(); int i = 0; while (i < (curNumberOfParameters)) { param = stack.pop(); if (!(supportNull && param instanceof Null)) { orginalValues.add((Double) param); } i++; } // calculate median Double median = median(orginalValues); ArrayList<Double> absMedianValues = new ArrayList<Double>(); // calculate mad by abs(median - value) for each for (Double value : orginalValues) { absMedianValues.add(Math.abs(value - median)); } Double mad = median(absMedianValues); // select only values in the range of the mad*threshold => removing the // outliers int count = 0; int index = 0; Double sum = new Double(0); while (index < absMedianValues.size()) { if (absMedianValues.get(index) < mad * threshold) { sum += orginalValues.get(index); count++; } index++; } if (index > 0) { stack.push(sum / count); } else { stack.push(new Null()); } }
private Double median(ArrayList<Double> median1) { // Calculate the median Double medianValue = null; Object[] objectArr = median1.toArray(); Double[] median = Arrays.copyOf(objectArr, objectArr.length, Double[].class); // get the numbers into a sorted order Arrays.sort(median); if ((median.length & 1) == 0) { // even number of parameters medianValue = (median[median.length / 2 - 1] + median[median.length / 2]) / 2; } else { // odd number of parameters medianValue = median[median.length / 2]; } return medianValue; }