KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > math > stat > Frequency


1 /*
2  * Copyright 2003-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.math.stat;
17
18 import java.io.Serializable JavaDoc;
19 import java.text.NumberFormat JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.Comparator JavaDoc;
22 import java.util.TreeMap JavaDoc;
23
24 /**
25  * Maintains a frequency distribution.
26  * <p>
27  * Accepts int, long, char or Object values. New values added must be
28  * comparable to those that have been added, otherwise the add method will
29  * throw an IllegalArgumentException.
30  * <p>
31  * Integer values (int, long, Integer, Long) are not distinguished by type --
32  * i.e. <code>addValue(new Long(2)), addValue(2), addValue(2l)</code> all have
33  * the same effect (similarly for arguments to <code>getCount,</code> etc.).
34  * <p>
35  * The values are ordered using the default (natural order), unless a
36  * <code>Comparator</code> is supplied in the constructor.
37  *
38  * @version $Revision$ $Date: 2005-02-26 05:11:52 -0800 (Sat, 26 Feb 2005) $
39  */

40 public class Frequency implements Serializable JavaDoc {
41     
42     /** Serializable version identifier */
43     static final long serialVersionUID = -3845586908418844111L;
44
45     /** underlying collection */
46     private TreeMap JavaDoc freqTable = null;
47
48     /**
49      * Default constructor.
50      */

51     public Frequency() {
52         freqTable = new TreeMap JavaDoc();
53     }
54     
55     /**
56      * Constructor allowing values Comparator to be specified.
57      *
58      * @param comparator Comparator used to order values
59      */

60     public Frequency(Comparator JavaDoc comparator) {
61         freqTable = new TreeMap JavaDoc(comparator);
62     }
63
64     /**
65      * Return a string representation of this frequency
66      * distribution.
67      *
68      * @return a string representation.
69      */

70     public String JavaDoc toString() {
71         NumberFormat JavaDoc nf = NumberFormat.getPercentInstance();
72         StringBuffer JavaDoc outBuffer = new StringBuffer JavaDoc();
73         outBuffer.append("Value \t Freq. \t Pct. \t Cum Pct. \n");
74         Iterator JavaDoc iter = freqTable.keySet().iterator();
75         while (iter.hasNext()) {
76             Object JavaDoc value = iter.next();
77             outBuffer.append(value);
78             outBuffer.append('\t');
79             outBuffer.append(getCount(value));
80             outBuffer.append('\t');
81             outBuffer.append(nf.format(getPct(value)));
82             outBuffer.append('\t');
83             outBuffer.append(nf.format(getCumPct(value)));
84             outBuffer.append('\n');
85         }
86         return outBuffer.toString();
87     }
88
89     /**
90      * Adds 1 to the frequency count for v.
91      *
92      * @param v the value to add.
93      * @throws IllegalArgumentException if <code>v</code> is not comparable.
94      */

95     public void addValue(Object JavaDoc v) {
96         Object JavaDoc obj = v;
97         if (v instanceof Integer JavaDoc) {
98            obj = new Long JavaDoc(((Integer JavaDoc) v).longValue());
99         }
100         try {
101             Long JavaDoc count = (Long JavaDoc) freqTable.get(obj);
102             if (count == null) {
103                 freqTable.put(obj, new Long JavaDoc(1));
104             } else {
105                 freqTable.put(obj, new Long JavaDoc(count.longValue() + 1));
106             }
107         } catch (ClassCastException JavaDoc ex) {
108             //TreeMap will throw ClassCastException if v is not comparable
109
throw new IllegalArgumentException JavaDoc("Value not comparable to existing values.");
110         }
111     }
112
113     /**
114      * Adds 1 to the frequency count for v.
115      *
116      * @param v the value to add.
117      */

118     public void addValue(int v) {
119         addValue(new Long JavaDoc(v));
120     }
121     
122     /**
123      * Adds 1 to the frequency count for v.
124      *
125      * @param v the value to add.
126      */

127     public void addValue(Integer JavaDoc v) {
128         addValue(new Long JavaDoc(v.longValue()));
129     }
130
131     /**
132      * Adds 1 to the frequency count for v.
133      *
134      * @param v the value to add.
135      */

136     public void addValue(long v) {
137         addValue(new Long JavaDoc(v));
138     }
139     
140     /**
141      * Adds 1 to the frequency count for v.
142      *
143      * @param v the value to add.
144      */

145     public void addValue(char v) {
146         addValue(new Character JavaDoc(v));
147     }
148     
149     /** Clears the frequency table */
150     public void clear() {
151         freqTable.clear();
152     }
153     
154     /**
155      * Returns an Iterator over the set of values that have been added.
156      * <p>
157      * If added values are itegral (i.e., integers, longs, Integers, or Longs),
158      * they are converted to Longs when they are added, so the objects returned
159      * by the Iterator will in this case be Longs.
160      *
161      * @return values Iterator
162      */

163     public Iterator JavaDoc valuesIterator() {
164         return freqTable.keySet().iterator();
165     }
166     
167     //-------------------------------------------------------------------------
168

169     /**
170      * Returns the sum of all frequencies.
171      *
172      * @return the total frequency count.
173      */

174     public long getSumFreq() {
175         long result = 0;
176         Iterator JavaDoc iterator = freqTable.values().iterator();
177         while (iterator.hasNext()) {
178             result += ((Long JavaDoc) iterator.next()).longValue();
179         }
180         return result;
181     }
182
183     /**
184      * Returns the number of values = v.
185      *
186      * @param v the value to lookup.
187      * @return the frequency of v.
188      */

189     public long getCount(Object JavaDoc v) {
190         if (v instanceof Integer JavaDoc) {
191             return getCount(((Integer JavaDoc) v).longValue());
192         }
193         long result = 0;
194         try {
195             Long JavaDoc count = (Long JavaDoc) freqTable.get(v);
196             if (count != null) {
197                 result = count.longValue();
198             }
199         } catch (ClassCastException JavaDoc ex) {
200             // ignore and return 0 -- ClassCastException will be thrown if value is not comparable
201
}
202         return result;
203     }
204
205     /**
206      * Returns the number of values = v.
207      *
208      * @param v the value to lookup.
209      * @return the frequency of v.
210      */

211     public long getCount(int v) {
212         return getCount(new Long JavaDoc(v));
213     }
214     
215     /**
216      * Returns the number of values = v.
217      *
218      * @param v the value to lookup.
219      * @return the frequency of v.
220      */

221     public long getCount(long v) {
222         return getCount(new Long JavaDoc(v));
223     }
224     
225     /**
226      * Returns the number of values = v.
227      *
228      * @param v the value to lookup.
229      * @return the frequency of v.
230      */

231     public long getCount(char v) {
232         return getCount(new Character JavaDoc(v));
233     }
234     
235     //-------------------------------------------------------------
236

237     /**
238       * Returns the percentage of values that are equal to v
239      * (as a proportion between 0 and 1).
240      * <p>
241      * Returns <code>Double.NaN</code> if no values have been added.
242      *
243      * @param v the value to lookup
244      * @return the proportion of values equal to v
245      */

246     public double getPct(Object JavaDoc v) {
247         if (getSumFreq() == 0) {
248             return Double.NaN;
249         }
250         return (double) getCount(v) / (double) getSumFreq();
251     }
252     
253     /**
254       * Returns the percentage of values that are equal to v
255      * (as a proportion between 0 and 1).
256      *
257      * @param v the value to lookup
258      * @return the proportion of values equal to v
259      */

260     public double getPct(int v) {
261         return getPct(new Long JavaDoc(v));
262     }
263     
264     /**
265       * Returns the percentage of values that are equal to v
266      * (as a proportion between 0 and 1).
267      *
268      * @param v the value to lookup
269      * @return the proportion of values equal to v
270      */

271     public double getPct(long v) {
272         return getPct(new Long JavaDoc(v));
273     }
274     
275     /**
276      * Returns the percentage of values that are equal to v
277      * (as a proportion between 0 and 1).
278      *
279      * @param v the value to lookup
280      * @return the proportion of values equal to v
281      */

282     public double getPct(char v) {
283         return getPct(new Character JavaDoc(v));
284     }
285     
286     //-----------------------------------------------------------------------------------------
287

288     /**
289      * Returns the cumulative frequency of values less than or equal to v.
290      * <p>
291      * Returns 0 if v is not comparable to the values set.
292      *
293      * @param v the value to lookup.
294      * @return the proportion of values equal to v
295      */

296     public long getCumFreq(Object JavaDoc v) {
297         if (getSumFreq() == 0) {
298             return 0;
299         }
300         if (v instanceof Integer JavaDoc) {
301             return getCumFreq(((Integer JavaDoc) v).longValue());
302         }
303         Comparator JavaDoc c = freqTable.comparator();
304         if (c == null) {
305             c = new NaturalComparator();
306         }
307         long result = 0;
308         
309         try {
310             Long JavaDoc value = (Long JavaDoc) freqTable.get(v);
311             if (value != null) {
312                 result = value.longValue();
313             }
314         } catch (ClassCastException JavaDoc ex) {
315             return result; // v is not comparable
316
}
317         
318         if (c.compare(v, freqTable.firstKey()) < 0) {
319             return 0; // v is comparable, but less than first value
320
}
321         
322         if (c.compare(v, freqTable.lastKey()) >= 0) {
323             return getSumFreq(); // v is comparable, but greater than the last value
324
}
325         
326         Iterator JavaDoc values = valuesIterator();
327         while (values.hasNext()) {
328             Object JavaDoc nextValue = values.next();
329             if (c.compare(v, nextValue) > 0) {
330                 result += getCount(nextValue);
331             } else {
332                 return result;
333             }
334         }
335         return result;
336     }
337     
338      /**
339      * Returns the cumulative frequency of values less than or equal to v.
340      * <p>
341      * Returns 0 if v is not comparable to the values set.
342      *
343      * @param v the value to lookup
344      * @return the proportion of values equal to v
345      */

346     public long getCumFreq(int v) {
347         return getCumFreq(new Long JavaDoc(v));
348     }
349     
350      /**
351      * Returns the cumulative frequency of values less than or equal to v.
352      * <p>
353      * Returns 0 if v is not comparable to the values set.
354      *
355      * @param v the value to lookup
356      * @return the proportion of values equal to v
357      */

358     public long getCumFreq(long v) {
359         return getCumFreq(new Long JavaDoc(v));
360     }
361     
362     /**
363      * Returns the cumulative frequency of values less than or equal to v.
364      * <p>
365      * Returns 0 if v is not comparable to the values set.
366      *
367      * @param v the value to lookup
368      * @return the proportion of values equal to v
369      */

370     public long getCumFreq(char v) {
371         return getCumFreq(new Character JavaDoc(v));
372     }
373     
374     //----------------------------------------------------------------------------------------------
375

376      /**
377      * Returns the cumulative percentage of values less than or equal to v
378      * (as a proportion between 0 and 1).
379      * <p>
380      * Returns <code>Double.NaN</code> if no values have been added.
381      * Returns 0 if at least one value has been added, but v is not comparable
382      * to the values set.
383      *
384      * @param v the value to lookup
385      * @return the proportion of values less than or equal to v
386      */

387     public double getCumPct(Object JavaDoc v) {
388         if (getSumFreq() == 0) {
389             return Double.NaN;
390         }
391         return (double) getCumFreq(v) / (double) getSumFreq();
392     }
393     
394     /**
395      * Returns the cumulative percentage of values less than or equal to v
396      * (as a proportion between 0 and 1).
397      * <p>
398      * Returns 0 if v is not comparable to the values set.
399      *
400      * @param v the value to lookup
401      * @return the proportion of values less than or equal to v
402      */

403     public double getCumPct(int v) {
404         return getCumPct(new Long JavaDoc(v));
405     }
406     
407     /**
408      * Returns the cumulative percentage of values less than or equal to v
409      * (as a proportion between 0 and 1).
410      * <p>
411      * Returns 0 if v is not comparable to the values set.
412      *
413      * @param v the value to lookup
414      * @return the proportion of values less than or equal to v
415      */

416     public double getCumPct(long v) {
417         return getCumPct(new Long JavaDoc(v));
418     }
419     
420     /**
421      * Returns the cumulative percentage of values less than or equal to v
422      * (as a proportion between 0 and 1).
423      * <p>
424      * Returns 0 if v is not comparable to the values set.
425      *
426      * @param v the value to lookup
427      * @return the proportion of values less than or equal to v
428      */

429     public double getCumPct(char v) {
430         return getCumPct(new Character JavaDoc(v));
431     }
432     
433     /**
434      * A Comparator that compares comparable objects using the
435      * natural order. Copied from Commons Collections ComparableComparator.
436      */

437     private static class NaturalComparator implements Comparator JavaDoc {
438         /**
439          * Compare the two {@link Comparable Comparable} arguments.
440          * This method is equivalent to:
441          * <pre>(({@link Comparable Comparable})o1).{@link Comparable#compareTo compareTo}(o2)</pre>
442          *
443          * @param o1 the first object
444          * @param o2 the second object
445          * @return result of comparison
446          * @throws NullPointerException when <i>o1</i> is <code>null</code>,
447          * or when <code>((Comparable)o1).compareTo(o2)</code> does
448          * @throws ClassCastException when <i>o1</i> is not a {@link Comparable Comparable},
449          * or when <code>((Comparable)o1).compareTo(o2)</code> does
450          */

451         public int compare(Object JavaDoc o1, Object JavaDoc o2) {
452             return ((Comparable JavaDoc)o1).compareTo(o2);
453         }
454     }
455 }
456
Popular Tags