Author: psteitz
Date: Tue May 19 13:31:34 2009
New Revision: 776311

URL: http://svn.apache.org/viewvc?rev=776311&view=rev
Log:
Added rank transformations.

Added:
    commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/
    
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/NaNStrategy.java
   (with props)
    
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/NaturalRanking.java
   (with props)
    
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/RankingAlgorithm.java
   (with props)
    
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/TiesStrategy.java
   (with props)
    
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/package.html
   (with props)
    commons/proper/math/trunk/src/test/org/apache/commons/math/stat/ranking/
    
commons/proper/math/trunk/src/test/org/apache/commons/math/stat/ranking/NaturalRankingTest.java
   (with props)
Modified:
    commons/proper/math/trunk/findbugs-exclude-filter.xml
    commons/proper/math/trunk/src/site/xdoc/changes.xml

Modified: commons/proper/math/trunk/findbugs-exclude-filter.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/findbugs-exclude-filter.xml?rev=776311&r1=776310&r2=776311&view=diff
==============================================================================
--- commons/proper/math/trunk/findbugs-exclude-filter.xml (original)
+++ commons/proper/math/trunk/findbugs-exclude-filter.xml Tue May 19 13:31:34 
2009
@@ -169,5 +169,11 @@
     <Method name="testNewNewtonSolverNull" params="" returns="void" />
     <Bug pattern="NP_NULL_PARAM_DEREF_ALL_TARGETS_DANGEROUS" />
   </Match>
+  
+  <!-- IntDoublePair intentionally implements Comparable inconsistently with 
equals -->
+  <Match>
+    <Class 
name="org.apache.commons.math.stat.ranking.NaturalRanking$IntDoublePair" />
+    <Bug pattern="EQ_COMPARETO_USE_OBJECT_EQUALS" />
+  </Match>
 
 </FindBugsFilter>

Added: 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/NaNStrategy.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/NaNStrategy.java?rev=776311&view=auto
==============================================================================
--- 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/NaNStrategy.java
 (added)
+++ 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/NaNStrategy.java
 Tue May 19 13:31:34 2009
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math.stat.ranking;
+
+/**
+ * Strategies for handling NaN values in rank transformations.
+ * <ul>
+ * <li>MINIMAL - NaNs are treated as minimal in the ordering, equivalent to
+ * (that is, tied with) <code>Double.NEGATIVE_INFINITY</code>.</li>
+ * <li>MAXIMAL - NaNs are treated as maximal in the ordering, equivalent to
+ * <code>Double.POSITIVE_INFINITY</code></li>
+ * <li>REMOVED - NaNs are removed before the rank transform is applied</li>
+ * <li>FIXED - NaNs are left "in place," that is the rank transformation is
+ * applied to the other elements in the input array, but the NaN elements
+ * are returned unchanged.</li>
+ * </ul>
+ *
+ * @since 2.0
+ * @version $Revision:$ $Date:$
+ */
+public enum NaNStrategy {
+    
+    /** NaNs are considered minimal in the ordering */
+    MINIMAL,
+    
+    /** NaNs are considered maximal in the ordering */
+    MAXIMAL,
+    
+    /** NaNs are removed before computing ranks */
+    REMOVED,
+    
+    /** NaNs are left in place */
+    FIXED
+}

Propchange: 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/NaNStrategy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/NaturalRanking.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/NaturalRanking.java?rev=776311&view=auto
==============================================================================
--- 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/NaturalRanking.java
 (added)
+++ 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/NaturalRanking.java
 Tue May 19 13:31:34 2009
@@ -0,0 +1,458 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math.stat.ranking;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.math.random.RandomData;
+import org.apache.commons.math.random.RandomDataImpl;
+import org.apache.commons.math.random.RandomGenerator;
+
+
+/**
+ * <p> Ranking based on the natural ordering on doubles.</p>
+ * <p>NaNs are treated according to the configured {...@link NaNStrategy} and 
ties
+ * are handled using the selected {...@link TiesStrategy}. 
+ * Configuration settings are supplied in optional constructor arguments.
+ * Defaults are {...@link NaNStrategy#MAXIMAL} and {...@link 
TiesStrategy#AVERAGE},
+ * respectively. When using {...@link TiesStrategy#RANDOM}, a 
+ * {...@link RandomGenerator} may be supplied as a constructor argument.</p>
+ * <p>Examples:
+ * <table border="1" cellpadding="3">
+ * <tr><th colspan="3">
+ * Input data: (20, 17, 30, 42.3, 17, 50, Double.NaN, 
Double.NEGATIVE_INFINITY, 17)
+ * </th></tr>
+ * <tr><th>NaNStrategy</th><th>TiesStrategy</th>
+ * <th><code>rank(data)</code></th>
+ * <tr>
+ * <td>default (NaNs maximal)</td>
+ * <td>default (ties averaged)</td>
+ * <td>(5, 3, 6, 7, 3, 8, 9, 1, 3)</td></tr>
+ * <tr>
+ * <td>default (NaNs maximal)</td>
+ * <td>MINIMUM</td>
+ * <td>(5, 2, 6, 7, 2, 8, 9, 1, 2)</td></tr>
+ * <tr>
+ * <td>MINIMAL</td>
+ * <td>default (ties averaged)</td>
+ * <td>(6, 4, 7, 8, 4, 9, 1.5, 1.5, 4)</td></tr>
+ * <tr>
+ * <td>REMOVED</td>
+ * <td>SEQUENTIAL</td>
+ * <td>(5, 2, 6, 7, 3, 8, 1, 4)</td></tr>
+ * <tr>
+ * <td>MINIMAL</td>
+ * <td>MAXIMUM</td>
+ * <td>(6, 5, 7, 8, 5, 9, 2, 2, 5)</td></tr></table></p>
+ * 
+ * @since 2.0
+ * @version $Revision:$ $Date:$
+ */
+public class NaturalRanking implements RankingAlgorithm {
+   
+    /** NaN strategy - defaults to NaNs maximal */
+    private final NaNStrategy nanStrategy;
+    
+    /** Ties strategy - defaults to ties averaged */
+    private final TiesStrategy tiesStrategy;
+    
+    /** Source of random data - used only when ties strategy is RANDOM */
+    private final RandomData randomData;
+    
+    /** default NaN strategy */
+    public static final NaNStrategy DEFAULT_NAN_STRATEGY = NaNStrategy.MAXIMAL;
+    
+    /** default ties strategy */
+    public static final TiesStrategy DEFAULT_TIES_STRATEGY = 
TiesStrategy.AVERAGE;
+    
+    /**
+     * Create a NaturalRanking with default strategies for handling ties and 
NaNs.
+     */
+    public NaturalRanking() {
+        super();
+        tiesStrategy = DEFAULT_TIES_STRATEGY;
+        nanStrategy = DEFAULT_NAN_STRATEGY;
+        randomData = null;
+    }
+
+    /**
+     * Create a NaturalRanking with the given TiesStrategy.
+     * 
+     * @param tiesStrategy the TiesStrategy to use
+     */
+    public NaturalRanking(TiesStrategy tiesStrategy) {
+        super();
+        this.tiesStrategy = tiesStrategy;
+        nanStrategy = DEFAULT_NAN_STRATEGY;
+        randomData = new RandomDataImpl();
+    }
+
+    /**
+     * Create a NaturalRanking with the given NaNStrategy.
+     * 
+     * @param nanStrategy the NaNStrategy to use
+     */
+    public NaturalRanking(NaNStrategy nanStrategy) {
+        super();
+        this.nanStrategy = nanStrategy;
+        tiesStrategy = DEFAULT_TIES_STRATEGY;
+        randomData = null; 
+    }
+
+    /**
+     * Create a NaturalRanking with the given NaNStrategy and TiesStrategy.
+     * 
+     * @param nanStrategy NaNStrategy to use
+     * @param tiesStrategy TiesStrategy to use
+     */
+    public NaturalRanking(NaNStrategy nanStrategy, TiesStrategy tiesStrategy) {
+        super();
+        this.nanStrategy = nanStrategy;
+        this.tiesStrategy = tiesStrategy;
+        randomData = new RandomDataImpl();
+    }
+    
+    /**
+     * Create a NaturalRanking with TiesStrategy.RANDOM and the given
+     * RandomGenerator as the source of random data.
+     * 
+     * @param randomGenerator source of random data
+     */
+    public NaturalRanking(RandomGenerator randomGenerator) {
+        super();
+        this.tiesStrategy = TiesStrategy.RANDOM;
+        nanStrategy = DEFAULT_NAN_STRATEGY;
+        randomData = new RandomDataImpl(randomGenerator);
+    }
+
+
+    /**
+     * Create a NaturalRanking with the given NaNStrategy, TiesStrategy.RANDOM
+     * and the given source of random data.
+     * 
+     * @param nanStrategy NaNStrategy to use
+     * @param randomGenerator source of random data
+     */
+    public NaturalRanking(NaNStrategy nanStrategy,
+            RandomGenerator randomGenerator) {
+        super();
+        this.nanStrategy = nanStrategy;
+        this.tiesStrategy = TiesStrategy.RANDOM;
+        randomData = new RandomDataImpl(randomGenerator);
+    }
+    
+    /**
+     * Return the NaNStrategy
+     * 
+     * @return returns the NaNStrategy
+     */
+    public NaNStrategy getNanStrategy() {
+        return nanStrategy;
+    }
+
+    /**
+     * Return the TiesStrategy
+     * 
+     * @return the TiesStrategy
+     */
+    public TiesStrategy getTiesStrategy() {
+        return tiesStrategy;
+    }
+
+    /**
+     * Rank <code>data</code> using the natural ordering on Doubles, with
+     * NaN values handled according to <code>nanStrategy</code> and ties
+     * resolved using <code>tiesStrategy.</code>
+     * 
+     * @param data array to be ranked
+     * @return array of ranks
+     */
+    public double[] rank(double[] data) {
+        
+        // Array recording initial positions of data to be ranked
+        IntDoublePair[] ranks = new IntDoublePair[data.length];  
+        for (int i = 0; i < data.length; i++) {
+            ranks[i] = new IntDoublePair(data[i], i);
+        }
+        
+        // Recode, remove or record positions of NaNs
+        List<Integer> nanPositions = null;
+        switch (nanStrategy) {
+            case MAXIMAL: // Replace NaNs with +INFs
+                recodeNaNs(ranks, Double.POSITIVE_INFINITY);
+                break;
+            case MINIMAL: // Replace NaNs with -INFs
+                recodeNaNs(ranks, Double.NEGATIVE_INFINITY);
+                break;
+            case REMOVED: // Drop NaNs from data
+                ranks = removeNaNs(ranks);
+                break;
+            case FIXED:   // Record positions of NaNs
+                nanPositions = getNanPositions(ranks);
+                break;
+        }
+        
+        // Sort the IntDoublePairs
+        Arrays.sort(ranks);
+        
+        // Walk the sorted array, filling output array using sorted positions,
+        // resolving ties as we go
+        double[] out = new double[ranks.length];
+        int pos = 1;  // position in sorted array 
+        out[ranks[0].getPosition()] = pos;
+        List<Integer> tiesTrace = new ArrayList<Integer>();
+        tiesTrace.add(ranks[0].getPosition());
+        for (int i = 1; i < ranks.length; i++) {
+            if (Double.compare(ranks[i].getValue(), ranks[i - 1].getValue()) > 
0) {
+                // tie sequence has ended (or had length 1)
+                pos = i + 1;
+                if (tiesTrace.size() > 1) {  // if seq is nontrivial, resolve
+                    resolveTie(out, tiesTrace);
+                }
+                tiesTrace = new ArrayList<Integer>();
+                tiesTrace.add(ranks[i].getPosition());
+            } else {
+                // tie sequence continues
+                tiesTrace.add(ranks[i].getPosition());
+            }
+            out[ranks[i].getPosition()] = pos;
+        }
+        if (tiesTrace.size() > 1) {  // handle tie sequence at end
+            resolveTie(out, tiesTrace);
+        }
+        if (nanStrategy == NaNStrategy.FIXED) {
+            restoreNaNs(out, nanPositions);
+        }
+        return out;
+    }
+    
+    /**
+     * Returns an array that is a copy of the input array with IntDoublePairs
+     * having NaN values removed.
+     * 
+     * @param ranks input array
+     * @return array with NaN-valued entries removed
+     */
+    private IntDoublePair[] removeNaNs(IntDoublePair[] ranks) {
+        if (!containsNaNs(ranks)) {
+            return ranks;
+        }
+        IntDoublePair[] outRanks = new IntDoublePair[ranks.length];
+        int j = 0;
+        for (int i = 0; i < ranks.length; i++) {
+            if (Double.isNaN(ranks[i].getValue())) {
+                // drop, but adjust original ranks of later elements
+                for (int k = i + 1; k < ranks.length; k++) {
+                    ranks[k] = new IntDoublePair(
+                            ranks[k].getValue(), ranks[k].getPosition() - 1);
+                }
+            } else {
+                outRanks[j] = new IntDoublePair(
+                        ranks[i].getValue(), ranks[i].getPosition());
+                j++;
+            }
+        }
+        IntDoublePair[] returnRanks = new IntDoublePair[j];
+        System.arraycopy(outRanks, 0, returnRanks, 0, j);
+        return returnRanks;
+    }
+
+    /**
+     * Recodes NaN values to the given value. 
+     * 
+     * @param ranks array to recode
+     * @param value the value to replace NaNs with
+     */
+    private void recodeNaNs(IntDoublePair[] ranks, double value) {
+        for (int i = 0; i < ranks.length; i++) {
+            if (Double.isNaN(ranks[i].getValue())) {
+                ranks[i] = new IntDoublePair(
+                        value, ranks[i].getPosition());
+            }
+        }
+    }
+    
+    /**
+     * Checks for presence of NaNs in <code>ranks.</code>
+     * 
+     * @param ranks array to be searched for NaNs
+     * @return true iff ranks contains one or more NaNs
+     */
+    private boolean containsNaNs(IntDoublePair[] ranks) {
+        for (int i = 0; i < ranks.length; i++) {
+            if (Double.isNaN(ranks[i].getValue())) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    /**
+     * Resolve a sequence of ties, using the cconfigured {...@link 
TiesStrategy}.
+     * The input <code>ranks</code> array is expected to take the same value
+     * for all indices in <code>tiesTrace</code>.  The common value is recoded
+     * according to the tiesStrategy. For example, if ranks = 
<5,8,2,6,2,7,1,2>,
+     * tiesTrace = <2,4,7> and tiesStrategy is MINIMUM, ranks will be 
unchanged.
+     * The same array and trace with tiesStrategy AVERAGE will come out
+     * <5,8,3,6,3,7,1,3>.
+     * 
+     * @param ranks array of ranks 
+     * @param tiesTrace list of indices where <code>ranks</code> is constant
+     * -- that is, for any i and j in TiesTrace, <code> ranks[i] == ranks[j] 
+     * </code>
+     */
+    private void resolveTie(double[] ranks, List<Integer> tiesTrace) {
+        
+        // constant value of ranks over tiesTrace
+        final double c = ranks[tiesTrace.get(0)];
+        
+        // length of sequence of tied ranks
+        final int length = tiesTrace.size();
+        
+        switch (tiesStrategy) {
+            case  AVERAGE:  // Replace ranks with average
+                fill(ranks, tiesTrace, (2 * c + length - 1) / 2d);
+                break;
+            case MAXIMUM:   // Replace ranks with maximum values
+                fill(ranks, tiesTrace, c + length - 1);
+                break;
+            case MINIMUM:   // Replace ties with minimum
+                fill(ranks, tiesTrace, c);
+                break;
+            case RANDOM:    // Fill with random integral values in [c, c + 
length - 1]
+                Iterator<Integer> iterator = tiesTrace.iterator();
+                long f = Math.round(c);
+                while (iterator.hasNext()) {
+                    ranks[iterator.next()] = 
+                        randomData.nextLong(f, f + length - 1);
+                }
+                break;
+            case SEQUENTIAL:  // Fill sequentially from c to c + length - 1
+                // walk and fill
+                iterator = tiesTrace.iterator();
+                f = Math.round(c);
+                int i = 0;
+                while (iterator.hasNext()) {
+                    ranks[iterator.next()] = f + i++;
+                }
+                break;
+        }   
+    }
+    
+    /**
+     * Sets<code>data[i] = value</code> for each i in <code>tiesTrace.</code>
+     * 
+     * @param data array to modify
+     * @param tiesTrace list of index values to set
+     * @param value value to set
+     */
+    private void fill(double[] data, List<Integer> tiesTrace, double value) {
+        Iterator<Integer> iterator = tiesTrace.iterator();
+        while (iterator.hasNext()) {
+            data[iterator.next()] = value;
+        }
+    }
+    
+    /**
+     * Set <code>ranks[i] = Double.NaN</code> for each i in 
<code>nanPositions.</code>
+     * 
+     * @param ranks array to modify
+     * @param nanPositions list of index values to set to 
<code>Double.NaN</code>
+     */
+    private void restoreNaNs(double[] ranks, List<Integer> nanPositions) {
+        if (nanPositions.size() == 0) {
+            return;
+        }
+        Iterator<Integer> iterator = nanPositions.iterator();
+        while (iterator.hasNext()) {
+            ranks[iterator.next().intValue()] = Double.NaN;  
+        }
+        
+    }
+    
+    /**
+     * Returns a list of indexes where <code>ranks</code> is <code>NaN.</code>
+     * 
+     * @param ranks array to search for <code>NaNs</code>
+     * @return list of indexes i such that <code>ranks[i] = NaN</code>
+     */
+    private List<Integer> getNanPositions(IntDoublePair[] ranks) {
+        ArrayList<Integer> out = new ArrayList<Integer>();
+        for (int i = 0; i < ranks.length; i++) {
+            if (Double.isNaN(ranks[i].getValue())) {
+                out.add(Integer.valueOf(i));
+            }
+        }
+        return out;     
+    }
+    
+    /**
+     * Represents the position of a double value in an ordering.
+     * Comparable interface is implemented so Arrays.sort can be used
+     * to sort an array of IntDoublePairs by value.  Note that the
+     * implicitly defined natural ordering is NOT consistent with equals.
+     */
+    private static class IntDoublePair implements Comparable<IntDoublePair>  {
+
+        /** Value of the pair */
+        final private double value;
+
+        /** Original position of the pair */
+        final private int position;
+
+        /**
+         * Construct an IntDoublePair with the given value and position.
+         * @param value the value of the pair
+         * @param position the original position
+         */
+        public IntDoublePair(double value, int position) {
+            this.value = value;
+            this.position = position;
+        }
+
+        /**
+         * Compare this IntDoublePair to another pair.
+         * Only the <strong>values</strong> are compared.
+         * 
+         * @param other the other pair to compare this to
+         * @return result of <code>Double.compare(value, other.value)</code>
+         */
+        public int compareTo(IntDoublePair other) {
+            return Double.compare(value, other.value);
+        }
+
+        /**
+         * Returns the value of the pair.
+         * @return value
+         */
+        public double getValue() {
+            return value;
+        }
+
+        /**
+         * Returns the original position of the pair.
+         * @return position
+         */
+        public int getPosition() {
+            return position;
+        }
+    }
+}

Propchange: 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/NaturalRanking.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/RankingAlgorithm.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/RankingAlgorithm.java?rev=776311&view=auto
==============================================================================
--- 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/RankingAlgorithm.java
 (added)
+++ 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/RankingAlgorithm.java
 Tue May 19 13:31:34 2009
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math.stat.ranking;
+
+/**
+ * Interface representing a rank transformation.
+ * 
+ * @since 2.0
+ * @version $Revision:$ $Date:$
+ */
+public interface RankingAlgorithm {
+    /**
+     * <p>Performs a rank transformation on the input data, returning an array
+     * of ranks.</p>
+     * 
+     * <p>Ranks should be 1-based - that is, the smallest value
+     * returned in an array of ranks should be greater than or equal to one,
+     * rather than 0. Ranks should in general take integer values, though
+     * implementations may return averages or other floating point values
+     * to resolve ties in the input data.</p>
+     * 
+     * @param data array of data to be ranked
+     * @return an array of ranks corresponding to the elements of the input 
array
+     */
+    double[] rank (double[] data);
+}

Propchange: 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/RankingAlgorithm.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/TiesStrategy.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/TiesStrategy.java?rev=776311&view=auto
==============================================================================
--- 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/TiesStrategy.java
 (added)
+++ 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/TiesStrategy.java
 Tue May 19 13:31:34 2009
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.math.stat.ranking;
+
+/**
+ * Strategies for handling tied values in rank transformations.
+ * <ul>
+ * <li>SEQUENTIAL - Ties are assigned ranks in order of occurrence in the 
original array,
+ * for example (1,3,4,3) is ranked as (1,2,4,3)</li>
+ * <li>MINIMUM - Tied values are assigned the minimum applicable rank, or the 
rank
+ * of the first occurrence. For example, (1,3,4,3) is ranked as (1,2,4,2)</li>
+ * <li>MAXIMUM - Tied values are assigned the maximum applicable rank, or the 
rank
+ * of the last occurrence. For example, (1,3,4,3) is ranked as (1,3,4,3)</li>
+ * <li>AVERAGE - Tied values are assigned the average of the applicable ranks. 
 
+ * For example, (1,3,4,3) is ranked as (1,2.5,4,2.5)</li>
+ * <li>AVERAGE - Tied values are assigned a random integer rank from among the
+ * applicable values. The assigned rank will always be an integer, 
(inclusively)
+ * between the values retured by the MINIMUM and MAXIMUM strategies.</li>
+ * </ul>
+ *
+ * @since 2.0
+ * @version $Revision:$ $Date:$
+ */
+public enum TiesStrategy {
+    
+    /** Ties assigned sequential ranks in order of occurrence */
+    SEQUENTIAL,
+    
+    /** Ties get the minimum applicable rank */
+    MINIMUM,
+    
+    /** Ties get the maximum applicable rank */
+    MAXIMUM,
+    
+    /** Ties get the average of applicable ranks */
+    AVERAGE,
+    
+    /** Ties get a random integral value from among applicable ranks */
+    RANDOM
+}

Propchange: 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/TiesStrategy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/package.html
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/package.html?rev=776311&view=auto
==============================================================================
--- 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/package.html
 (added)
+++ 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/package.html
 Tue May 19 13:31:34 2009
@@ -0,0 +1,22 @@
+<html>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+  -->
+    <!-- $Revision:$ $Date:$ -->
+    <body>
+      Classes providing rank transformations.
+    </body>
+</html>

Propchange: 
commons/proper/math/trunk/src/java/org/apache/commons/math/stat/ranking/package.html
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: commons/proper/math/trunk/src/site/xdoc/changes.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/site/xdoc/changes.xml?rev=776311&r1=776310&r2=776311&view=diff
==============================================================================
--- commons/proper/math/trunk/src/site/xdoc/changes.xml (original)
+++ commons/proper/math/trunk/src/site/xdoc/changes.xml Tue May 19 13:31:34 2009
@@ -39,7 +39,10 @@
   </properties>
   <body>
     <release version="2.0" date="TBD" description="TBD">
-      <action dev="luc" type="update" >
+      <action dev="psteitz" type="add">
+        Added support for rank transformations.
+      </action>
+      <action dev="luc" type="update">
         Completed internationalization of all error messages
       </action>
       <action dev="luc" type="add" issue="MATH-266" due-to="Benjamin McCann">

Added: 
commons/proper/math/trunk/src/test/org/apache/commons/math/stat/ranking/NaturalRankingTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/org/apache/commons/math/stat/ranking/NaturalRankingTest.java?rev=776311&view=auto
==============================================================================
--- 
commons/proper/math/trunk/src/test/org/apache/commons/math/stat/ranking/NaturalRankingTest.java
 (added)
+++ 
commons/proper/math/trunk/src/test/org/apache/commons/math/stat/ranking/NaturalRankingTest.java
 Tue May 19 13:31:34 2009
@@ -0,0 +1,188 @@
+/*
+ * TiesEquivalentRankTest.java created on Aug 24, 2005 by jdgant01
+ *
+ */
+package org.apache.commons.math.stat.ranking;
+
+import org.apache.commons.math.TestUtils;
+import org.apache.commons.math.random.JDKRandomGenerator;
+import org.apache.commons.math.random.RandomGenerator;
+
+import junit.framework.TestCase;
+
+/**
+ * Test cases for NaturalRanking class
+ * 
+ * @since 2.0
+ * @version $Revision:$ $Date:$
+ */
+public class NaturalRankingTest extends TestCase {
+    
+    private final double[] exampleData = 
+    {20, 17, 30, 42.3, 17, 50, Double.NaN, Double.NEGATIVE_INFINITY, 17};
+    private final double[] tiesFirst = {0, 0, 2, 1, 4};
+    private final double[] tiesLast = {4, 4, 1, 0};
+    private final double[] multipleNaNs = {0, 1, Double.NaN, Double.NaN};
+    private final double[] multipleTies = {3, 2, 5, 5, 6, 6, 1};
+    private final double[] allSame = {0, 0, 0, 0};
+    
+    public NaturalRankingTest(String arg0) {
+        super(arg0);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+    
+    public void testDefault() {  // Ties averaged, NaNs maximal
+        NaturalRanking ranking = new NaturalRanking();
+        double[] ranks = ranking.rank(exampleData);
+        double[] correctRanks = {5, 3, 6, 7, 3, 8, 9, 1, 3};
+        TestUtils.assertEquals(correctRanks, ranks, 0d); 
+        ranks = ranking.rank(tiesFirst);
+        correctRanks = new double[] {1.5, 1.5, 4, 3, 5};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(tiesLast);
+        correctRanks = new double[] {3.5, 3.5, 2, 1};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(multipleNaNs);
+        correctRanks = new double[] {1, 2, 3.5, 3.5};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(multipleTies);
+        correctRanks = new double[] {3, 2, 4.5, 4.5, 6.5, 6.5, 1};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(allSame);
+        correctRanks = new double[] {2.5, 2.5, 2.5, 2.5};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+    }
+    
+    public void testNaNsMaximalTiesMinimum() {
+        NaturalRanking ranking = new NaturalRanking(TiesStrategy.MINIMUM);
+        double[] ranks = ranking.rank(exampleData);
+        double[] correctRanks = {5, 2, 6, 7, 2, 8, 9, 1, 2};
+        TestUtils.assertEquals(correctRanks, ranks, 0d); 
+        ranks = ranking.rank(tiesFirst);
+        correctRanks = new double[] {1, 1, 4, 3, 5};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(tiesLast);
+        correctRanks = new double[] {3, 3, 2, 1};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(multipleNaNs);
+        correctRanks = new double[] {1, 2, 3, 3};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(multipleTies);
+        correctRanks = new double[] {3, 2, 4, 4, 6, 6, 1};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(allSame);
+        correctRanks = new double[] {1, 1, 1, 1};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+    }
+    
+    public void testNaNsRemovedTiesSequential() {
+        NaturalRanking ranking = new NaturalRanking(NaNStrategy.REMOVED, 
+                TiesStrategy.SEQUENTIAL);
+        double[] ranks = ranking.rank(exampleData);
+        double[] correctRanks = {5, 2, 6, 7, 3, 8, 1, 4};
+        TestUtils.assertEquals(correctRanks, ranks, 0d); 
+        ranks = ranking.rank(tiesFirst);
+        correctRanks = new double[] {1, 2, 4, 3, 5};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(tiesLast);
+        correctRanks = new double[] {3, 4, 2, 1};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(multipleNaNs);
+        correctRanks = new double[] {1, 2};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(multipleTies);
+        correctRanks = new double[] {3, 2, 4, 5, 6, 7, 1};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(allSame);
+        correctRanks = new double[] {1, 2, 3, 4};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+    }
+    
+    public void testNaNsMinimalTiesMaximum() {
+        NaturalRanking ranking = new NaturalRanking(NaNStrategy.MINIMAL, 
+                TiesStrategy.MAXIMUM);
+        double[] ranks = ranking.rank(exampleData);
+        double[] correctRanks = {6, 5, 7, 8, 5, 9, 2, 2, 5};
+        TestUtils.assertEquals(correctRanks, ranks, 0d); 
+        ranks = ranking.rank(tiesFirst);
+        correctRanks = new double[] {2, 2, 4, 3, 5};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(tiesLast);
+        correctRanks = new double[] {4, 4, 2, 1};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(multipleNaNs);
+        correctRanks = new double[] {3, 4, 2, 2};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(multipleTies);
+        correctRanks = new double[] {3, 2, 5, 5, 7, 7, 1};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(allSame);
+        correctRanks = new double[] {4, 4, 4, 4};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+    }
+    
+    public void testNaNsMinimalTiesAverage() {
+        NaturalRanking ranking = new NaturalRanking(NaNStrategy.MINIMAL);
+        double[] ranks = ranking.rank(exampleData);
+        double[] correctRanks = {6, 4, 7, 8, 4, 9, 1.5, 1.5, 4};
+        TestUtils.assertEquals(correctRanks, ranks, 0d); 
+        ranks = ranking.rank(tiesFirst);
+        correctRanks = new double[] {1.5, 1.5, 4, 3, 5};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(tiesLast);
+        correctRanks = new double[] {3.5, 3.5, 2, 1};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(multipleNaNs);
+        correctRanks = new double[] {3, 4, 1.5, 1.5};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(multipleTies);
+        correctRanks = new double[] {3, 2, 4.5, 4.5, 6.5, 6.5, 1};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(allSame);
+        correctRanks = new double[] {2.5, 2.5, 2.5, 2.5};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+    }
+    
+    public void testNaNsFixedTiesRandom() {
+        RandomGenerator randomGenerator = new JDKRandomGenerator();
+        randomGenerator.setSeed(1000);
+        NaturalRanking ranking = new NaturalRanking(NaNStrategy.FIXED,
+                randomGenerator);
+        double[] ranks = ranking.rank(exampleData);
+        double[] correctRanks = {5, 4, 6, 7, 3, 8, Double.NaN, 1, 4};
+        TestUtils.assertEquals(correctRanks, ranks, 0d); 
+        ranks = ranking.rank(tiesFirst);
+        correctRanks = new double[] {1, 1, 4, 3, 5};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(tiesLast);
+        correctRanks = new double[] {3, 4, 2, 1};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(multipleNaNs);
+        correctRanks = new double[] {1, 2, Double.NaN, Double.NaN};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(multipleTies);
+        correctRanks = new double[] {3, 2, 5, 5, 7, 6, 1};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranks = ranking.rank(allSame);
+        correctRanks = new double[] {1, 3, 4, 4};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);  
+    }
+    
+    public void testNaNsAndInfs() {
+        double[] data = {0, Double.POSITIVE_INFINITY, Double.NaN, 
Double.NEGATIVE_INFINITY};
+        NaturalRanking ranking = new NaturalRanking(NaNStrategy.MAXIMAL);
+        double[] ranks = ranking.rank(data);
+        double[] correctRanks = new double[] {2, 3.5, 3.5, 1};
+        TestUtils.assertEquals(correctRanks, ranks, 0d);
+        ranking = new NaturalRanking(NaNStrategy.MINIMAL);
+        ranks = ranking.rank(data);
+        correctRanks = new double[] {3, 4, 1.5, 1.5};
+    }
+}

Propchange: 
commons/proper/math/trunk/src/test/org/apache/commons/math/stat/ranking/NaturalRankingTest.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to