2010-08-20 4 views
4

Есть ли встроенная библиотека, которую я могу использовать для вычисления медианы в java ??Статистические вычисления

Я работал с apache.commons.math для других статистических функций, но медианной нигде не было.

Спасибо,

ответ

7

Какую версию Apache Commmons Math вы используете? Существует средний класс, по крайней мере, начиная с версии 2.1 (более старая версия, я не уверен). Вы можете использовать его как:

Median median = new Median(); 
median.evaluate(values); 
+0

работает! Большое спасибо :) Я использовал 2.0: P – JJunior

+3

Какой это смешной надстроенный дизайн API? IMHO нет оправдания для чего-то столь же простого, как калибровка медианы, требующей создания объекта и принятия нескольких строк кода. – dsimcha

+1

double median = new Median(). Оценить (значения); Добро пожаловать. – Matunos

9

Поместите все номера в список, отсортировать список и взять среднее значение (или среднее из двух средних значений для одинакового размера). Никаких расчетов не требуется

+0

ИТАК его сортировку и принимая среднее значение, которое: SortedList [SortedList .lenght/2] должен дать мне правильное медианное право? – JJunior

+0

Вам нужно проверить, отсортирован ли sortedList.length% 2 == 0, и если это так, возьмите среднее значение sortedList.length/2 & (sortedList.length/2) + 1 - это именно то, что вам нужно выполнить модульный тест –

+0

статистическая медиана - это не что иное, как среднее значение, так что да, это должно быть хорошо. Однако, когда есть четное число значений, вы не можете просто посередине, так как нет середины. Вместо этого вы должны взять среднее значение из двух значений, наиболее близких к середине. В списке размера 4 среднее значение второго и третьего значений. Code wise, это будет '(list [list.length/2] + list [(list.length/2) +1])/2' –

2

Получить значения в объекте «Список». Предположим, что значения являются целыми числами, а список называется «значениями». Затем

List<Integer> values; 
... populate values ... 
Collections.sort(values); 
int median; 
int midpoint=values.size()/2; 
if (values.size()%2==1) 
    median=values.get(midpoint+1).intValue(); 
else 
    median=(values.get(midpoint).intValue()+values.get(midpoint+1).intValue())/2; 

Если число значений велико, как и в сотнях или больше, баловаться с модами-2 может быть технически правильным, но излишним.

Возможно, есть более эффективный способ сделать это - сортировка довольно медленная в большом списке - но это сработает.

О, и вам действительно нужно проверить список с нулевыми значениями. Возможно, мне не хватает других граничных условий.

+0

Ваша формула правильная, но манипуляция списком массивов неверна. Ваш ответ приводит к неправильному результату. ArrayList # get method index начинается с '0', поэтому он терпит неудачу, когда в списке есть 2 элемента, происходит' ArrayIndexOutOfBoundsException'. Могу ли я исправить код? –

+0

О, ты прав. Неуклюжий. Последняя строка должна занимать среднюю и среднюю точку MINUS 1, а не PLUS 1. Я думаю, что это тоже правильно. Вы можете высмеять, если увидите другую ошибку. :-) – Jay

1

От «слишком много времени-на-мои-руки» отдел: здесь немного класс MedianGenerator:

/** 
* Methods to calculate the median value of a supplied {@link List}. 
*/ 
public final class MedianGenerator{ 

    private MedianGenerator(){ 
    } 

    /** 
    * Calculate the median of a supplied list. 
    * <ol> 
    * <li>A copy will be generated</li> 
    * <li>this copy will be sorted with the supplied comparator</li> 
    * <li>the median will be calculated, using the supplied averageCalculator 
    * for collections with an even number of items</li> 
    * </ol> 
    * 
    * @param data 
    * @param comparator 
    * @param averageCalculator 
    * @return the median 
    */ 
    public static <T> T calculateMedian(final List<T> data, 
     final Comparator<? super T> comparator, 
     final AverageCalculator<T> averageCalculator){ 
     final List<T> copy = new ArrayList<T>(data); 
     Collections.sort(copy, comparator); 
     return doCalculateMedian(data, averageCalculator); 

    } 

    /** 
    * Calculate the median of a supplied list. 
    * <ol> 
    * <li>A copy will be generated</li> 
    * <li>this copy will be sorted with the supplied comparator</li> 
    * <li>the median will be calculated, using the {@link #ALWAYS_FIRST} {@link AverageCalculator} 
    * for collections with an even number of items</li> 
    * </ol> 
    * 
    * @param data 
    * @param comparator 
    * @return the median 
    */ 
    @SuppressWarnings("unchecked") 
    public static <T> T calculateMedian(final List<T> data, 
     final Comparator<? super T> comparator){ 
     return calculateMedian(data, comparator, (AverageCalculator<T>) ALWAYS_FIRST); 
    } 

    /** 
    * Calculate the median of a supplied list. 
    * <ol> 
    * <li>A copy will be generated</li> 
    * <li>this copy will be sorted using natural ordering</li> 
    * <li>the median will be calculated, using the {@link #ALWAYS_FIRST} {@link AverageCalculator} 
    * for collections with an even number of items</li> 
    * </ol> 
    * 
    * @param data 
    * @return the median 
    */ 
    @SuppressWarnings("unchecked") 
    public static <T extends Comparable<? super T>> T calculateMedian(final List<T> data){ 
     return calculateMedian(data, (AverageCalculator<T>) ALWAYS_FIRST); 
    } 

    /** 
    * Calculate the median of a supplied list. 
    * <ol> 
    * <li>A copy will be generated</li> 
    * <li>this copy will be sorted using natural ordering</li> 
    * <li>the median will be calculated, using the supplied averageCalculator 
    * for collections with an even number of items</li> 
    * </ol> 
    * 
    * @param data 
    * @param averageCalculator 
    * @return the median 
    */ 
    public static <T extends Comparable<? super T>> T calculateMedian(final List<T> data, 
     final AverageCalculator<T> averageCalculator){ 
     final List<T> copy = new ArrayList<T>(data); 
     Collections.sort(copy); 
     return doCalculateMedian(copy, averageCalculator); 
    } 

    private static <T> T doCalculateMedian(final List<T> sortedData, 
     final AverageCalculator<T> averageCalculator){ 
     T result; 
     if(sortedData.isEmpty()){ 
      result = null; 
     } else{ 
      final int size = sortedData.size(); 
      if(size % 2 == 0){ 
       result = 
        averageCalculator.getAverage(sortedData.get(size/2 - 1), 
         sortedData.get(size/2)); 
      } else{ 
       result = sortedData.get(size/2 - 1); 
      } 

     } 
     return result; 
    } 

    /** 
    * Generic accessor method for {@link #ALWAYS_FIRST}. 
    */ 
    @SuppressWarnings("unchecked") 
    public static <T> AverageCalculator<T> alwaysFirst(){ 
     return ALWAYS_FIRST; 
    } 

    /** 
    * {@link AverageCalculator} implementation that always returns the lower 
    * bound unchanged. 
    */ 
    @SuppressWarnings("rawtypes") 
    public static final AverageCalculator ALWAYS_FIRST = 
     new AverageCalculator(){ 

      @Override 
      public Object getAverage(final Object first, final Object second){ 
       return first; 
      } 

     }; 

    /** 
    * When there is an even number of items, this interface is used to generate 
    * the average between the two middle items. 
    */ 
    public static interface AverageCalculator<E> { 

     E getAverage(E first, E second); 
    } 

} 
Смежные вопросы