diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index cededa04e..d8acf73ec 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -51,6 +51,9 @@ If the output is not quite correct, check for invisible trailing spaces!
+
+ Add mode function to Frequency class.
+
Fixed "MathArrays.linearCombination" when array length is 1.
diff --git a/src/main/java/org/apache/commons/math3/stat/Frequency.java b/src/main/java/org/apache/commons/math3/stat/Frequency.java
index f15565079..ff5d20adf 100644
--- a/src/main/java/org/apache/commons/math3/stat/Frequency.java
+++ b/src/main/java/org/apache/commons/math3/stat/Frequency.java
@@ -18,10 +18,13 @@ package org.apache.commons.math3.stat;
import java.io.Serializable;
import java.text.NumberFormat;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Comparator;
+import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.TreeMap;
import org.apache.commons.math3.exception.MathIllegalArgumentException;
@@ -493,6 +496,39 @@ public class Frequency implements Serializable {
return getCumPct(Character.valueOf(v));
}
+ /**
+ * Returns the mode value(s) in comparator order.
+ *
+ * @return a list containing the value(s) which appear most often.
+ * @since 3.3
+ */
+ public List> getMode() {
+ long mostPopular = 0; // frequencies are always positive
+
+ // Get the max count first, so we avoid having to recreate the List each time
+ for(Long l : freqTable.values()) {
+ long frequency = l.longValue();
+ if (frequency > mostPopular) {
+ mostPopular = frequency;
+ }
+ }
+
+ List> modeList = new ArrayList>();
+ for (Entry, Long> ent : freqTable.entrySet()) {
+ long frequency = ent.getValue().longValue();
+ if (frequency == mostPopular) {
+ modeList.add(ent.getKey());
+// Alternatively, to avoid scanning the entries twice, keep recreating the set
+// To use this approach, comment out the values() scan loop above and uncomment below
+// } else if (frequency > mostPopular) {
+// modeList.clear(); // the previous List is obsolete
+// modeList.add(ent.getKey());
+// mostPopular = frequency;
+ }
+ }
+ return modeList;
+ }
+
//----------------------------------------------------------------------------------------------
/**
diff --git a/src/test/java/org/apache/commons/math3/stat/FrequencyTest.java b/src/test/java/org/apache/commons/math3/stat/FrequencyTest.java
index 7e59f16ed..edf61788c 100644
--- a/src/test/java/org/apache/commons/math3/stat/FrequencyTest.java
+++ b/src/test/java/org/apache/commons/math3/stat/FrequencyTest.java
@@ -334,18 +334,28 @@ public final class FrequencyTest {
Assert.assertEquals(1, f.getCount(THREEE));
}
-// @Test
-// public void testMode() {
-// Assert.assertEquals(0, f.getMode().size());
-// f.addValue("1");
-// Assert.assertEquals(1, f.getMode().size());
-// f.addValue("2");
-// Assert.assertEquals(2, f.getMode().size());
-// Assert.assertTrue(f.getMode().contains("1"));
-// Assert.assertTrue(f.getMode().contains("2"));
-// f.addValue("2");
-// Assert.assertEquals(1, f.getMode().size());
-// Assert.assertFalse(f.getMode().contains("1"));
-// Assert.assertTrue(f.getMode().contains("2"));
-// }
+ @Test
+ public void testMode() {
+ List> mode;
+ mode = f.getMode();
+ Assert.assertEquals(0, mode.size());
+
+ f.addValue("3");
+ mode = f.getMode();
+ Assert.assertEquals(1, mode.size());
+ Assert.assertEquals("3", mode.get(0));
+
+ f.addValue("2");
+ mode = f.getMode();
+ Assert.assertEquals(2, mode.size());
+ Assert.assertEquals("2", mode.get(0));
+ Assert.assertEquals("3",mode.get(1));
+
+ f.addValue("2");
+ mode = f.getMode();
+ Assert.assertEquals(1, mode.size());
+ Assert.assertEquals("2", mode.get(0));
+ Assert.assertFalse(mode.contains("1"));
+ Assert.assertTrue(mode.contains("2"));
+ }
}