2010-11-16 41 views

Respuesta

61

Sí, parece que hay 3 bibliotecas (ninguna en Java Math). Dos que han llegado son:

http://opsresearch.com/app/

http://www.iro.umontreal.ca/~simardr/ssj/indexe.html

pero, en realidad no es tan difícil de escribir sus propios métodos para calcular la media, mediana, moda y rango.

MEDIA

public static double mean(double[] m) { 
    double sum = 0; 
    for (int i = 0; i < m.length; i++) { 
     sum += m[i]; 
    } 
    return sum/m.length; 
} 

MEDIANA

// the array double[] m MUST BE SORTED 
public static double median(double[] m) { 
    int middle = m.length/2; 
    if (m.length%2 == 1) { 
     return m[middle]; 
    } else { 
     return (m[middle-1] + m[middle])/2.0; 
    } 
} 

MODO

public static int mode(int a[]) { 
    int maxValue, maxCount; 

    for (int i = 0; i < a.length; ++i) { 
     int count = 0; 
     for (int j = 0; j < a.length; ++j) { 
      if (a[j] == a[i]) ++count; 
     } 
     if (count > maxCount) { 
      maxCount = count; 
      maxValue = a[i]; 
     } 
    } 

    return maxValue; 
} 

ACTUALIZACIÓN

Como ha señalado Neelesh Salpe, lo anterior no contempla colecciones multimodales. Podemos arreglar esto con bastante facilidad:

public static List<Integer> mode(final int[] numbers) { 
    final List<Integer> modes = new ArrayList<Integer>(); 
    final Map<Integer, Integer> countMap = new HashMap<Integer, Integer>(); 

    int max = -1; 

    for (final int n : numbers) { 
     int count = 0; 

     if (countMap.containsKey(n)) { 
      count = countMap.get(n) + 1; 
     } else { 
      count = 1; 
     } 

     countMap.put(n, count); 

     if (count > max) { 
      max = count; 
     } 
    } 

    for (final Map.Entry<Integer, Integer> tuple : countMap.entrySet()) { 
     if (tuple.getValue() == max) { 
      modes.add(tuple.getKey()); 
     } 
    } 

    return modes; 
} 

ADEMÁS

Si está utilizando Java 8 o superior, también puede determinar los modos como esta:

public static List<Integer> getModes(final List<Integer> numbers) { 
    final Map<Integer, Long> countFrequencies = numbers.stream() 
      .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); 

    final long maxFrequency = countFrequencies.values().stream() 
      .mapToLong(count -> count) 
      .max().orElse(-1); 

    return countFrequencies.entrySet().stream() 
      .filter(tuple -> tuple.getValue() == maxFrequency) 
      .map(Map.Entry::getKey) 
      .collect(Collectors.toList()); 
} 
+0

gracias, pero yo preferiría usar algo fuera de la caja, si es posible – user339108

+0

@Stephen C. Lo siento, me actualiza el enlace de nuevo. –

+0

Esta clase tendrá problemas si tiene una matriz muy grande o tiene que calcular los valores sobre la marcha. Se puede escribir sin una matriz para la media y la desviación estándar; no tan seguro para la mediana y el modo. – duffymo

2

El algoritmo MODE no está considerando casos con más de un modo (bimodal, trimodal, ...) - sucede cuando hay más de un número que aparece en la misma cantidad de veces que maxCount. Teniendo esto en cuenta, debería devolver una matriz en lugar de un único valor int.

-1
public class Mode { 
    public static void main(String[] args) { 
     int[] unsortedArr = new int[] { 3, 1, 5, 2, 4, 1, 3, 4, 3, 2, 1, 3, 4, 1 ,-1,-1,-1,-1,-1}; 
     Map<Integer, Integer> countMap = new HashMap<Integer, Integer>(); 

     for (int i = 0; i < unsortedArr.length; i++) { 
      Integer value = countMap.get(unsortedArr[i]); 

      if (value == null) { 
       countMap.put(unsortedArr[i], 0); 
      } else { 
       int intval = value.intValue(); 
       intval++; 
       countMap.put(unsortedArr[i], intval); 
      } 
     } 

     System.out.println(countMap.toString()); 

     int max = getMaxFreq(countMap.values()); 
     List<Integer> modes = new ArrayList<Integer>(); 

     for (Entry<Integer, Integer> entry : countMap.entrySet()) { 
      int value = entry.getValue(); 
      if (value == max) 
       modes.add(entry.getKey()); 
     } 
     System.out.println(modes); 
    } 

    public static int getMaxFreq(Collection<Integer> valueSet) { 
     int max = 0; 
     boolean setFirstTime = false; 

     for (Iterator iterator = valueSet.iterator(); iterator.hasNext();) { 
      Integer integer = (Integer) iterator.next(); 

      if (!setFirstTime) { 
       max = integer; 
       setFirstTime = true; 
      } 
      if (max < integer) { 
       max = integer; 
      } 
     } 
     return max; 
    } 
} 

Los datos de prueba

Modos {1,3} para {3, 1, 5, 2, 4, 1, 3, 4, 3, 2, 1, 3, 4, 1 };
Modos {-1} para {3, 1, 5, 2, 4, 1, 3, 4, 3, 2, 1, 3, 4, 1, -1, -1, -1, -1, - 1};

0
public static Set<Double> getMode(double[] data) { 
      if (data.length == 0) { 
       return new TreeSet<>(); 
      } 
      TreeMap<Double, Integer> map = new TreeMap<>(); //Map Keys are array values and Map Values are how many times each key appears in the array 
      for (int index = 0; index != data.length; ++index) { 
       double value = data[index]; 
       if (!map.containsKey(value)) { 
        map.put(value, 1); //first time, put one 
       } 
       else { 
        map.put(value, map.get(value) + 1); //seen it again increment count 
       } 
      } 
      Set<Double> modes = new TreeSet<>(); //result set of modes, min to max sorted 
      int maxCount = 1; 
      Iterator<Integer> modeApperance = map.values().iterator(); 
      while (modeApperance.hasNext()) { 
       maxCount = Math.max(maxCount, modeApperance.next()); //go through all the value counts 
      } 
      for (double key : map.keySet()) { 
       if (map.get(key) == maxCount) { //if this key's value is max 
        modes.add(key); //get it 
       } 
      } 
      return modes; 
     } 

     //std dev function for good measure 
     public static double getStandardDeviation(double[] data) { 
      final double mean = getMean(data); 
      double sum = 0; 
      for (int index = 0; index != data.length; ++index) { 
       sum += Math.pow(Math.abs(mean - data[index]), 2); 
      } 
      return Math.sqrt(sum/data.length); 
     } 


     public static double getMean(double[] data) { 
     if (data.length == 0) { 
      return 0; 
     } 
     double sum = 0.0; 
     for (int index = 0; index != data.length; ++index) { 
      sum += data[index]; 
     } 
     return sum/data.length; 
    } 

//by creating a copy array and sorting it, this function can take any data. 
    public static double getMedian(double[] data) { 
     double[] copy = Arrays.copyOf(data, data.length); 
     Arrays.sort(copy); 
     return (copy.length % 2 != 0) ? copy[copy.length/2] : (copy[copy.length/2] + copy[(copy.length/2) - 1])/2; 
    } 
Cuestiones relacionadas