psteitz 2004/02/08 11:51:25
Modified: math/src/java/org/apache/commons/math/stat Frequency.java
math/src/test/org/apache/commons/math/random
RandomDataTest.java
math/src/test/org/apache/commons/math/stat
FrequencyTest.java
Log:
Refactored Frequency to support cummulative frequency counts and percentages. Also
eliminated the name property.
Revision Changes Path
1.12 +271 -51
jakarta-commons/math/src/java/org/apache/commons/math/stat/Frequency.java
Index: Frequency.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/math/src/java/org/apache/commons/math/stat/Frequency.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- Frequency.java 29 Jan 2004 00:49:01 -0000 1.11
+++ Frequency.java 8 Feb 2004 19:51:25 -0000 1.12
@@ -55,55 +55,61 @@
import java.io.Serializable;
import java.util.Iterator;
+import java.util.Comparator;
+import java.text.NumberFormat;
-import org.apache.commons.collections.Bag;
-import org.apache.commons.collections.HashBag;
+import org.apache.commons.collections.SortedBag;
+import org.apache.commons.collections.TreeBag;
/**
- * Maintains a frequency distribution. <br>
- * Accepts int, long or string values, converting
- * all to Strings and maintaining frequency counts.
+ * Maintains a frequency distribution.
+ * <p>
+ * Accepts int, long, char or Object values. New values added must be comparable
to
+ * those that have been added, otherwise the add method will throw an
IllegalArgumentException.
+ * The values are ordered using the default (natural order), unless a
<code>Comparator</code>
+ * is supplied in the constructor.
*
* @version $Revision$ $Date$
*/
-public class Frequency implements Serializable{
+public class Frequency implements Serializable {
- /** name for this frequency distribution. */
- private String name;
-
/** underlying collection */
- private Bag freqTable = new HashBag();
+ private SortedBag freqTable = null;
/**
* Default constructor.
*/
public Frequency() {
- this(null);
+ freqTable = new TreeBag();
}
-
+
/**
- * Construct a frequency distribution with the given name.
- * @param name the name for the new distribution.
+ * Constructor allowing values Comparator to be specified.
+ * @param comparator Comparator used to order values
*/
- public Frequency(String name) {
- super();
- setName(name);
+ public Frequency(Comparator comparator) {
+ freqTable = new TreeBag(comparator);
}
/**
- * Return a string representation of describing this frequency
+ * Return a string representation of this frequency
* distribution.
* @return a string representation.
*/
public String toString() {
+ NumberFormat nf = NumberFormat.getPercentInstance();
StringBuffer outBuffer = new StringBuffer();
- outBuffer.append("Value \t Frequency \n");
+ outBuffer.append("Value \t Freq. \t Pct. \t Cum Pct. \n");
Iterator iter = freqTable.uniqueSet().iterator();
while (iter.hasNext()) {
Object value = iter.next();
outBuffer.append(value);
outBuffer.append('\t');
- outBuffer.append(freqTable.getCount(value));
+ outBuffer.append(getCount(value));
+ outBuffer.append('\t');
+ outBuffer.append(nf.format(getPct(value)));
+ outBuffer.append('\t');
+ outBuffer.append(nf.format(getCumPct(value)));
outBuffer.append('\n');
}
return outBuffer.toString();
@@ -113,8 +119,13 @@
* Adds 1 to the frequency count for v
* @param v the value to add.
*/
- public void addValue(String v) {
- freqTable.add(v);
+ public void addValue(Object v) {
+ try {
+ freqTable.add(v);
+ } catch (ClassCastException ex) {
+ //TreeBag will throw ClassCastException if v is not comparable
+ throw new IllegalArgumentException("Value not comparable to existing
values.");
+ }
}
/**
@@ -122,7 +133,7 @@
* @param v the value to add.
*/
public void addValue(int v) {
- addValue((new Integer(v)).toString());
+ addValue(new Long(v));
}
/**
@@ -130,52 +141,261 @@
* @param v the value to add.
*/
public void addValue(long v) {
- addValue((new Long(v)).toString());
+ addValue(new Long(v));
}
-
+
/**
- * Returns the number of values = v
- * @param v the value to lookup.
- * @return the absolute frequency of v.
+ * Adds 1 to the frequency count for v.
+ * @param v the value to add.
*/
- public long getCount(String v) {
- return freqTable.getCount(v);
+ public void addValue(char v) {
+ addValue(new Character(v));
}
-
+
+ /** Clears the frequency table */
+ public void clear() {
+ freqTable.clear();
+ }
+
+ /**
+ * Returns an Iterator over the set of values that have been added
+ * @return values Iterator
+ */
+ public Iterator valuesIterator() {
+ return freqTable.uniqueSet().iterator();
+ }
+
+ //-------------------------------------------------------------------------
+
/**
* Returns the sum of all frequencies
- * @return the aggregate frequency.
+ * @return the total frequency count.
*/
public long getSumFreq() {
- return freqTable.size();
+ return freqTable.size();
}
/**
- * Returns the percentage of values = v.
+ * Returns the number of values = v
* @param v the value to lookup.
- * @return the relative frequency of v.
+ * @return the frequency of v.
*/
- public double getPct(String v) {
- return (double) getCount(v) / (double) getSumFreq();
+ public long getCount(Object v) {
+ long result = 0;
+ try {
+ result = freqTable.getCount(v);
+ } catch (Exception ex) {
+ // ignore and return 0 -- ClassCastException will be thrown if value
is not comparable
+ }
+ return result;
}
- /** Clears the frequency table */
- public void clear() {
- freqTable.clear();
+ /**
+ * Returns the number of values = v
+ * @param v the value to lookup.
+ * @return the frequency of v.
+ */
+ public long getCount(int v) {
+ long result = 0;
+ try {
+ result = freqTable.getCount(new Long(v));
+ } catch (Exception ex) {
+ // ignore and return 0 -- ClassCastException will be thrown if value
is not comparable
+ }
+ return result;
}
-
- /** Getter for property name.
- * @return Value of property name.
+
+ /**
+ * Returns the number of values = v
+ * @param v the value to lookup.
+ * @return the frequency of v.
*/
- public String getName() {
- return name;
+ public long getCount(long v) {
+ long result = 0;
+ try {
+ result = freqTable.getCount(new Long(v));
+ } catch (Exception ex) {
+ // ignore and return 0 -- ClassCastException will be thrown if value
is not comparable
+ }
+ return result;
}
-
- /** Setter for property name.
- * @param name New value of property name.
+
+ /**
+ * Returns the number of values = v
+ * @param v the value to lookup.
+ * @return the frequency of v.
*/
- public void setName(java.lang.String name) {
- this.name = name;
+ public long getCount(char v) {
+ long result = 0;
+ try {
+ result = freqTable.getCount(new Character(v));
+ } catch (Exception ex) {
+ // ignore and return 0 -- ClassCastException will be thrown if value
is not comparable
+ }
+ return result;
}
+
+ //-------------------------------------------------------------
+ /**
+ * Returns the percentage of values = v (as a proportion -- i.e. between 0 and
1).
+ * @param v the value to lookup.
+ * @return the proportion of values equal to v
+ */
+ public double getPct(Object v) {
+ return (double) getCount(v) / (double) getSumFreq();
+ }
+
+ /**
+ * Returns the percentage of values = v (as a proportion -- i.e. between 0 and
1).
+ * @param v the value to lookup.
+ * @return the proportion of values equal to v
+ */
+ public double getPct(int v) {
+ return getPct(new Long(v));
+ }
+
+ /**
+ * Returns the percentage of values = v (as a proportion -- i.e. between 0 and
1).
+ * @param v the value to lookup.
+ * @return the proportion of values equal to v
+ */
+ public double getPct(long v) {
+ return getPct(new Long(v));
+ }
+
+ /**
+ * Returns the percentage of values = v (as a proportion -- i.e. between 0 and
1).
+ * @param v the value to lookup.
+ * @return the proportion of values equal to v
+ */
+ public double getPct(char v) {
+ return getPct(new Character(v));
+ }
+
+
//-----------------------------------------------------------------------------------------
+
+ /**
+ * Returns the cummulative frequency of values less than or equal to v.
+ * <p>
+ * Returns 0 if v is not comparable to the values set.
+ *
+ * @param v the value to lookup.
+ * @return the proportion of values equal to v
+ */
+ public long getCumFreq(Object v) {
+ long result = 0;
+ try {
+ result = freqTable.getCount(v);
+ } catch (ClassCastException ex) {
+ return result; // v is not comparable
+ }
+ Comparable c = (Comparable) v;
+ if (c.compareTo(freqTable.first()) < 0) {
+ return 0; // v is comparable, but less than the first value
+ }
+ if (c.compareTo(freqTable.last()) > 0) {
+ return getSumFreq(); // v is comparable, but greater than the last
value
+ }
+ Iterator values = valuesIterator();
+ while (values.hasNext()) {
+ Object nextValue = values.next();
+ if (c.compareTo(nextValue) > 0) {
+ result += getCount(nextValue);
+ } else {
+ return result;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns the cummulative frequency of values less than or equal to v.
+ * <p>
+ * Returns 0 if v is not comparable to the values set.
+ *
+ * @param v the value to lookup.
+ * @return the proportion of values equal to v
+ */
+ public long getCumFreq(int v) {
+ return getCumFreq(new Long(v));
+ }
+
+ /**
+ * Returns the cummulative frequency of values less than or equal to v.
+ * <p>
+ * Returns 0 if v is not comparable to the values set.
+ *
+ * @param v the value to lookup.
+ * @return the proportion of values equal to v
+ */
+ public long getCumFreq(long v) {
+ return getCumFreq(new Long(v));
+ }
+
+ /**
+ * Returns the cummulative frequency of values less than or equal to v.
+ * <p>
+ * Returns 0 if v is not comparable to the values set.
+ *
+ * @param v the value to lookup.
+ * @return the proportion of values equal to v
+ */
+ public long getCumFreq(char v) {
+ return getCumFreq(new Character(v));
+ }
+
+
//----------------------------------------------------------------------------------------------
+
+ /**
+ * Returns the cummulative percentatge of values less than or equal to v
+ * (as a proportion -- i.e. between 0 and 1).
+ * <p>
+ * Returns 0 if v is not comparable to the values set.
+ *
+ * @param v the value to lookup.
+ * @return the proportion of values equal to v
+ */
+ public double getCumPct(Object v) {
+ return (double) getCumFreq(v) / (double) getSumFreq();
+ }
+
+ /**
+ * Returns the cummulative percentatge of values less than or equal to v
+ * (as a proportion -- i.e. between 0 and 1).
+ * <p>
+ * Returns 0 if v is not comparable to the values set.
+ *
+ * @param v the value to lookup.
+ * @return the proportion of values equal to v
+ */
+ public double getCumPct(int v) {
+ return getCumPct(new Long(v));
+ }
+
+ /**
+ * Returns the cummulative percentatge of values less than or equal to v
+ * (as a proportion -- i.e. between 0 and 1).
+ * <p>
+ * Returns 0 if v is not comparable to the values set.
+ *
+ * @param v the value to lookup.
+ * @return the proportion of values equal to v
+ */
+ public double getCumPct(long v) {
+ return getCumPct(new Long(v));
+ }
+
+ /**
+ * Returns the cummulative percentatge of values less than or equal to v
+ * (as a proportion -- i.e. between 0 and 1).
+ * <p>
+ * Returns 0 if v is not comparable to the values set.
+ *
+ * @param v the value to lookup.
+ * @return the proportion of values equal to v
+ */
+ public double getCumPct(char v) {
+ return getCumPct(new Character(v));
+ }
}
1.11 +7 -11
jakarta-commons/math/src/test/org/apache/commons/math/random/RandomDataTest.java
Index: RandomDataTest.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/math/src/test/org/apache/commons/math/random/RandomDataTest.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- RandomDataTest.java 29 Jan 2004 00:49:03 -0000 1.10
+++ RandomDataTest.java 8 Feb 2004 19:51:25 -0000 1.11
@@ -112,8 +112,7 @@
}
double[] observed = new double[4];
for (int i=0; i<4; i++) {
- String iString = new Integer(i).toString();
- observed[i] = freq.getCount(iString);
+ observed[i] = freq.getCount(i);
}
/* Use ChiSquare dist with df = 4-1 = 3, alpha = .001
@@ -140,8 +139,7 @@
}
double[] observed = new double[4];
for (int i=0; i<4; i++) {
- String iString = new Integer(i).toString();
- observed[i] = freq.getCount(iString);
+ observed[i] = freq.getCount(i);
}
/* Use ChiSquare dist with df = 4-1 = 3, alpha = .001
@@ -168,8 +166,7 @@
}
double[] observed = new double[4];
for (int i=0; i<4; i++) {
- String iString = new Integer(i).toString();
- observed[i] = freq.getCount(iString);
+ observed[i] = freq.getCount(i);
}
/* Use ChiSquare dist with df = 4-1 = 3, alpha = .001
@@ -196,8 +193,7 @@
}
double[] observed = new double[4];
for (int i=0; i<4; i++) {
- String iString = new Integer(i).toString();
- observed[i] = freq.getCount(iString);
+ observed[i] = freq.getCount(i);
}
/* Use ChiSquare dist with df = 4-1 = 3, alpha = .001
@@ -229,8 +225,8 @@
fail(ex.getMessage());
}
}
- long cumFreq = f.getCount("0") + f.getCount("1") + f.getCount("2") +
- f.getCount("3") + f.getCount("4") + f.getCount("5");
+ long cumFreq = f.getCount(0) + f.getCount(1) + f.getCount(2) +
+ f.getCount(3) + f.getCount(4) + f.getCount(5);
long sumFreq = f.getSumFreq();
double cumPct =
new Double(cumFreq).doubleValue()/new Double(sumFreq).doubleValue();
1.9 +50 -27
jakarta-commons/math/src/test/org/apache/commons/math/stat/FrequencyTest.java
Index: FrequencyTest.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/math/src/test/org/apache/commons/math/stat/FrequencyTest.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- FrequencyTest.java 29 Jan 2004 00:49:00 -0000 1.8
+++ FrequencyTest.java 8 Feb 2004 19:51:25 -0000 1.9
@@ -70,17 +70,21 @@
public final class FrequencyTest extends TestCase {
private long oneL = 1;
private long twoL = 2;
+ private long threeL = 3;
private int oneI = 1;
private int twoI = 2;
+ private int threeI=3;
private String oneS = "1";
private String twoS = "2";
private double tolerance = 10E-15;
+ private Frequency f = null;
public FrequencyTest(String name) {
super(name);
}
public void setUp() {
+ f = new Frequency();
}
public static Test suite() {
@@ -91,48 +95,77 @@
/** test freq counts */
public void testCounts() {
- Frequency f = new Frequency("test counts");
assertEquals("total count",0,f.getSumFreq());
f.addValue(oneL);
f.addValue(twoL);
- f.addValue(oneS);
+ f.addValue(1);
f.addValue(oneI);
- assertEquals("one frequency count",3,f.getCount("1"));
- assertEquals("two frequency count",1,f.getCount("2"));
- assertEquals("foo frequency count",0,f.getCount("foo"));
+ assertEquals("one frequency count",3,f.getCount(1));
+ assertEquals("two frequency count",1,f.getCount(2));
+ assertEquals("three frequency count",0,f.getCount(3));
assertEquals("total count",4,f.getSumFreq());
+ assertEquals("zero cummulative frequency", 0, f.getCumFreq(0));
+ assertEquals("one cummulative frequency", 3, f.getCumFreq(1));
+ assertEquals("two cummulative frequency", 4, f.getCumFreq(2));
+ assertEquals("two cummulative frequency", 4, f.getCumFreq(5));
+ assertEquals("two cummulative frequency", 0, f.getCumFreq("foo"));
f.clear();
assertEquals("total count",0,f.getSumFreq());
}
/** test pcts */
public void testPcts() {
- Frequency f = new Frequency("test pcts");
f.addValue(oneL);
f.addValue(twoL);
f.addValue(oneI);
f.addValue(twoI);
- f.addValue("foo");
- f.addValue("foo");
- f.addValue("foo");
- f.addValue("foo");
- assertEquals("one pct",0.25,f.getPct("1"),tolerance);
- assertEquals("two pct",0.25,f.getPct("2"),tolerance);
- assertEquals("foo pct",0.5,f.getPct("foo"),tolerance);
- assertEquals("bar pct",0,f.getPct("bar"),tolerance);
+ f.addValue(threeL);
+ f.addValue(threeL);
+ f.addValue(3);
+ f.addValue(threeI);
+ assertEquals("one pct",0.25,f.getPct(1),tolerance);
+ assertEquals("two pct",0.25,f.getPct(new Long(2)),tolerance);
+ assertEquals("three pct",0.5,f.getPct(threeL),tolerance);
+ assertEquals("five pct",0,f.getPct(5),tolerance);
+ assertEquals("foo pct",0,f.getPct("foo"),tolerance);
+ assertEquals("one cum pct",0.25,f.getCumPct(1),tolerance);
+ assertEquals("two cum pct",0.50,f.getCumPct(new Long(2)),tolerance);
+ assertEquals("three cum pct",1.0,f.getCumPct(threeL),tolerance);
+ assertEquals("five cum pct",1.0,f.getCumPct(5),tolerance);
+ assertEquals("zero cum pct",0.0,f.getCumPct(0),tolerance);
+ assertEquals("foo cum pct",0,f.getCumPct("foo"),tolerance);
+ }
+
+ /** test adding incomparable values */
+ public void testAdd() {
+ char aChar = 'a';
+ char bChar = 'b';
+ String aString = "a";
+ f.addValue(aChar);
+ f.addValue(bChar);
+ try {
+ f.addValue(aString);
+ fail("Expecting IllegalArgumentException");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ assertEquals("a pct",0.5,f.getPct(aChar),tolerance);
+ assertEquals("b cum pct",1.0,f.getCumPct(bChar),tolerance);
+ assertEquals("a string pct",0.0,f.getPct(aString),tolerance);
+ assertEquals("a string cum pct",0.0,f.getCumPct(aString),tolerance);
}
/**
- *
+ * Tests toString()
*/
public void testToString(){
- Frequency f = new Frequency("test toString");
f.addValue(oneL);
f.addValue(twoL);
f.addValue(oneI);
f.addValue(twoI);
String s = f.toString();
+ //System.out.println(s);
assertNotNull(s);
BufferedReader reader = new BufferedReader(new StringReader(s));
try {
@@ -151,15 +184,5 @@
fail(ex.getMessage());
}
}
-
- /**
- *
- */
- public void testSetName(){
- String name = "name";
- Frequency f = new Frequency();
- f.setName(name);
- assertEquals(name, f.getName());
- }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]