平均 、中央値、モード、数値のセットからの範囲を計算する関数(数学ライブラリの一部として)はありますか?.
はい、3番目のライブラリがあるようです(Java Mathにはありません)。次の2つがあります。
http://www.iro.umontreal.ca/~simardr/ssj/indexe.html
しかし、実際には、平均、中央値、モード、範囲を計算する独自のメソッドを記述することはそれほど難しくありません。
平均
public static double mean(double[] m) {
double sum = 0;
for (int i = 0; i < m.length; i++) {
sum += m[i];
}
return sum / m.length;
}
中央値
// 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;
}
}
モード
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;
}
UPDATE
Neelesh Salpeが指摘したように、上記はマルチモーダルコレクションには対応していません。これは非常に簡単に修正できます。
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;
}
追加
Java 8以降を使用している場合、次のようにモードを決定することもできます。
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());
}
Apacheのcommons math をご覧ください。かなりたくさんあります。
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;
}
}
テストデータ
モード{1,3} for {3、1、5、2、4、1、3、4、3、2、1、3、4、1};
モード{-1}は{3、1、5、2、4、1、3、4、3、2、1、3、4、1、-1、-1、-1、- 1、-1};
Nico Huysamenがすでに指摘したように、Java 1.8で複数モードを見つけることは、以下のように代替的に行うことができます。
import Java.util.ArrayList;
import Java.util.List;
import Java.util.HashMap;
import Java.util.Map;
public static void mode(List<Integer> numArr) {
Map<Integer, Integer> freq = new HashMap<Integer, Integer>();;
Map<Integer, List<Integer>> mode = new HashMap<Integer, List<Integer>>();
int modeFreq = 1; //record the highest frequence
for(int x=0; x<numArr.size(); x++) { //1st for loop to record mode
Integer curr = numArr.get(x); //O(1)
freq.merge(curr, 1, (a, b) -> a + b); //increment the frequency for existing element, O(1)
int currFreq = freq.get(curr); //get frequency for current element, O(1)
//lazy instantiate a list if no existing list, then
//record mapping of frequency to element (frequency, element), overall O(1)
mode.computeIfAbsent(currFreq, k -> new ArrayList<>()).add(curr);
if(modeFreq < currFreq) modeFreq = currFreq; //update highest frequency
}
mode.get(modeFreq).forEach(x -> System.out.println("Mode = " + x)); //pretty print the result //another for loop to return result
}
ハッピーコーディング!
ユニモーダル分布のみに関心がある場合は、sthを検討してください。このような。
public static Optional<Integer> mode(Stream<Integer> stream) {
Map<Integer, Long> frequencies = stream
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
return frequencies.entrySet().stream()
.max(Comparator.comparingLong(Map.Entry::getValue))
.map(Map.Entry::getKey);
}
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;
}