You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by tn...@apache.org on 2012/10/21 19:33:37 UTC

svn commit: r1400683 - in /commons/proper/math/trunk/src: changes/changes.xml main/java/org/apache/commons/math3/stat/Frequency.java test/java/org/apache/commons/math3/stat/FrequencyTest.java

Author: tn
Date: Sun Oct 21 17:33:37 2012
New Revision: 1400683

URL: http://svn.apache.org/viewvc?rev=1400683&view=rev
Log:
[MATH-474] Added Frequency#merge method, thanks to patch from Dan Checkoway.

Modified:
    commons/proper/math/trunk/src/changes/changes.xml
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/stat/Frequency.java
    commons/proper/math/trunk/src/test/java/org/apache/commons/math3/stat/FrequencyTest.java

Modified: commons/proper/math/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/changes/changes.xml?rev=1400683&r1=1400682&r2=1400683&view=diff
==============================================================================
--- commons/proper/math/trunk/src/changes/changes.xml (original)
+++ commons/proper/math/trunk/src/changes/changes.xml Sun Oct 21 17:33:37 2012
@@ -52,6 +52,10 @@ If the output is not quite correct, chec
   <body>
     <release version="3.1" date="TBD" description="
 ">
+      <action dev="tn" type="add" issue="MATH-474" due-to="Dan Checkoway">
+        Added new methods "merge(Frequency)", "merge(Collection<Frequency>)",
+        "incrementValue(Comparable<?>, long)" and "entrySetIterator()" to the "Frequency" class.
+      </action>
       <action dev="tn" type="fix" issue="MATH-778" due-to="Sébastien Brisard">
         Allow unlimited input values for "Dfp#multiply(int)".
       </action>

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/stat/Frequency.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/stat/Frequency.java?rev=1400683&r1=1400682&r2=1400683&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/stat/Frequency.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/stat/Frequency.java Sun Oct 21 17:33:37 2012
@@ -18,8 +18,10 @@ package org.apache.commons.math3.stat;
 
 import java.io.Serializable;
 import java.text.NumberFormat;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.Comparator;
+import java.util.Map;
 import java.util.TreeMap;
 
 import org.apache.commons.math3.exception.MathIllegalArgumentException;
@@ -108,16 +110,31 @@ public class Frequency implements Serial
      * @throws MathIllegalArgumentException if <code>v</code> is not comparable with previous entries
      */
     public void addValue(Comparable<?> v) throws MathIllegalArgumentException {
+        incrementValue(v, 1);
+    }
+
+    /**
+     * Increments the frequency count for v.
+     * <p>
+     * If other objects have already been added to this Frequency, v must
+     * be comparable to those that have already been added.
+     * </p>
+     *
+     * @param v the value to add.
+     * @param increment the amount by which the value should be incremented
+     * @throws IllegalArgumentException if <code>v</code> is not comparable with previous entries
+     */
+    public void incrementValue(Comparable<?> v, long increment){
         Comparable<?> obj = v;
         if (v instanceof Integer) {
-           obj = Long.valueOf(((Integer) v).longValue());
+            obj = Long.valueOf(((Integer) v).longValue());
         }
         try {
             Long count = freqTable.get(obj);
             if (count == null) {
-                freqTable.put(obj, Long.valueOf(1));
+                freqTable.put(obj, Long.valueOf(increment));
             } else {
-                freqTable.put(obj, Long.valueOf(count.longValue() + 1));
+                freqTable.put(obj, Long.valueOf(count.longValue() + increment));
             }
         } catch (ClassCastException ex) {
             //TreeMap will throw ClassCastException if v is not comparable
@@ -178,6 +195,22 @@ public class Frequency implements Serial
         return freqTable.keySet().iterator();
     }
 
+    /**
+     * Return an Iterator over the set of keys and values that have been added.
+     * Using the entry set to iterate is more efficient in the case where you
+     * need to access respective counts as well as values, since it doesn't
+     * require a "get" for every key...the value is provided in the Map.Entry.
+     * <p>
+     * If added values are integral (i.e., integers, longs, Integers, or Longs),
+     * they are converted to Longs when they are added, so the values of the
+     * map entries returned by the Iterator will in this case be Longs.</p>
+     *
+     * @return entry set Iterator
+     */
+    public Iterator<Map.Entry<Comparable<?>, Long>> entrySetIterator() {
+        return freqTable.entrySet().iterator();
+    }
+
     //-------------------------------------------------------------------------
 
     /**
@@ -456,6 +489,37 @@ public class Frequency implements Serial
         return getCumPct(Character.valueOf(v));
     }
 
+    //----------------------------------------------------------------------------------------------
+
+    /**
+     * Merge another Frequency object's counts into this instance.
+     * This Frequency's counts will be incremented (or set when not already set)
+     * by the counts represented by other.
+     *
+     * @param other the other {@link Frequency} object to be merged
+     */
+    public void merge(Frequency other) {
+        for (Iterator<Map.Entry<Comparable<?>, Long>> iter = other.entrySetIterator(); iter.hasNext();) {
+            Map.Entry<Comparable<?>, Long> entry = iter.next();
+            incrementValue(entry.getKey(), entry.getValue());
+        }
+    }
+
+    /**
+     * Merge a {@link Collection} of {@link Frequency} objects into this instance.
+     * This Frequency's counts will be incremented (or set when not already set)
+     * by the counts represented by each of the others.
+     *
+     * @param others the other {@link Frequency} objects to be merged
+     */
+    public void merge(Collection<Frequency> others) {
+        for (Iterator<Frequency> iter = others.iterator(); iter.hasNext();) {
+            merge(iter.next());
+        }
+    }
+
+    //----------------------------------------------------------------------------------------------
+
     /**
      * A Comparator that compares comparable objects using the
      * natural order.  Copied from Commons Collections ComparableComparator.

Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/stat/FrequencyTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/stat/FrequencyTest.java?rev=1400683&r1=1400682&r2=1400683&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/stat/FrequencyTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/stat/FrequencyTest.java Sun Oct 21 17:33:37 2012
@@ -18,7 +18,9 @@ package org.apache.commons.math3.stat;
 
 import java.io.BufferedReader;
 import java.io.StringReader;
+import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
 
 
 import org.apache.commons.math3.TestUtils;
@@ -262,5 +264,73 @@ public final class FrequencyTest {
         f.addValue(twoI);
         Assert.assertEquals(2, f.getUniqueCount());
     }
+    
+    @Test
+    public void testIncrement() {
+        Assert.assertEquals(0, f.getUniqueCount());
+        f.incrementValue(oneL, 1);
+        Assert.assertEquals(1, f.getCount(oneL));
+
+        f.incrementValue(oneL, 4);
+        Assert.assertEquals(5, f.getCount(oneL));
+        
+        f.incrementValue(oneL, -5);
+        Assert.assertEquals(0, f.getCount(oneL));
+    }
+    
+    @Test
+    public void testMerge() {
+        Assert.assertEquals(0, f.getUniqueCount());
+        f.addValue(oneL);
+        f.addValue(twoL);
+        f.addValue(oneI);
+        f.addValue(twoI);
+        
+        Assert.assertEquals(2, f.getUniqueCount());
+        Assert.assertEquals(2, f.getCount(oneI));
+        Assert.assertEquals(2, f.getCount(twoI));
+
+        Frequency g = new Frequency();
+        g.addValue(oneL);
+        g.addValue(threeL);
+        g.addValue(threeI);
+
+        Assert.assertEquals(2, g.getUniqueCount());
+        Assert.assertEquals(1, g.getCount(oneI));
+        Assert.assertEquals(2, g.getCount(threeI));
+
+        f.merge(g);
+        
+        Assert.assertEquals(3, f.getUniqueCount());
+        Assert.assertEquals(3, f.getCount(oneI));
+        Assert.assertEquals(2, f.getCount(twoI));
+        Assert.assertEquals(2, f.getCount(threeI));        
+    }
+    
+    @Test
+    public void testMergeCollection() {
+        Assert.assertEquals(0, f.getUniqueCount());
+        f.addValue(oneL);
+        
+        Assert.assertEquals(1, f.getUniqueCount());
+        Assert.assertEquals(1, f.getCount(oneI));
+        Assert.assertEquals(0, f.getCount(twoI));
+
+        Frequency g = new Frequency();
+        g.addValue(twoL);
+
+        Frequency h = new Frequency();
+        h.addValue(threeL);
+        
+        List<Frequency> coll = new ArrayList<Frequency>();
+        coll.add(g);
+        coll.add(h);
+        f.merge(coll);
+        
+        Assert.assertEquals(3, f.getUniqueCount());
+        Assert.assertEquals(1, f.getCount(oneI));
+        Assert.assertEquals(1, f.getCount(twoI));
+        Assert.assertEquals(1, f.getCount(threeI));        
+    }
 }