001 /*--------------------------------------------------------------------------+
002 $Id: MedianAggregator.java 29788 2010-08-19 08:46:02Z juergens $
003 | |
004 | Copyright 2005-2010 Technische Universitaet Muenchen |
005 | |
006 | Licensed under the Apache License, Version 2.0 (the "License"); |
007 | you may not use this file except in compliance with the License. |
008 | You may obtain a copy of the License at |
009 | |
010 | http://www.apache.org/licenses/LICENSE-2.0 |
011 | |
012 | Unless required by applicable law or agreed to in writing, software |
013 | distributed under the License is distributed on an "AS IS" BASIS, |
014 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
015 | See the License for the specific language governing permissions and |
016 | limitations under the License. |
017 +--------------------------------------------------------------------------*/
018 package edu.tum.cs.commons.math;
019
020 import java.util.ArrayList;
021 import java.util.Collection;
022 import java.util.Collections;
023
024 /**
025 * Median aggregator. Note that for an even number of elements this aggregator
026 * returns the mean value of both middle elements.
027 *
028 * @author deissenb
029 * @author $Author: juergens $
030 * @version $Rev: 29788 $
031 * @levd.rating GREEN Hash: 263069760E186DA03CC4463A773263DD
032 */
033 public class MedianAggregator implements IAggregator {
034
035 /**
036 * Aggregates by finding the median.
037 *
038 * @return {@link Double#NaN} for empty input collection
039 */
040 @Override
041 public double aggregate(Collection<? extends Number> values) {
042 if (values.isEmpty()) {
043 return Double.NaN;
044 }
045
046 ArrayList<Double> doubleValues = new ArrayList<Double>();
047
048 for (Number value : values) {
049 doubleValues.add(value.doubleValue());
050 }
051
052 Collections.sort(doubleValues);
053
054 // odd number of elements
055 if (doubleValues.size() % 2 == 1) {
056 int medianIndex = (int) Math.ceil(doubleValues.size() / 2);
057 return doubleValues.get(medianIndex);
058 }
059
060 // even number of elements
061 int lowerMedianIndex = doubleValues.size() / 2 - 1;
062 double lowerMedian = doubleValues.get(lowerMedianIndex);
063 double upperMedian = doubleValues.get(lowerMedianIndex + 1);
064
065 return (lowerMedian + upperMedian) / 2;
066 }
067
068 /** Returns {@link Double#NaN}. */
069 @Override
070 public double getNeutralElement() {
071 return Double.NaN;
072 }
073 }