source: trunk/yat/normalizer/Spearman.h @ 1739

Last change on this file since 1739 was 1739, checked in by Peter, 12 years ago

fixes #479 and removing some debug output

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 4.0 KB
Line 
1#ifndef _theplu_yat_normalizer_spearman_
2#define _theplu_yat_normalizer_spearman_
3
4// $Id: Spearman.h 1739 2009-01-21 01:34:18Z peter $
5
6/*
7  Copyright (C) 2008, 2009 Peter Johansson
8
9  This file is part of the yat library, http://dev.thep.lu.se/yat
10
11  The yat library is free software; you can redistribute it and/or
12  modify it under the terms of the GNU General Public License as
13  published by the Free Software Foundation; either version 3 of the
14  License, or (at your option) any later version.
15
16  The yat library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  General Public License for more details.
20
21  You should have received a copy of the GNU General Public License
22  along with yat. If not, see <http://www.gnu.org/licenses/>.
23*/
24
25#include "yat/utility/DataIterator.h"
26#include "yat/utility/iterator_traits.h"
27#include "yat/utility/sort_index.h"
28#include "yat/utility/WeightIterator.h"
29
30#include <algorithm>
31#include <functional>
32#include <vector>
33
34namespace theplu {
35namespace yat {
36namespace normalizer {
37
38  /**
39     \brief Replace elements with normalized rank
40
41     Each element x is replaced by \f$ \frac{\sum I(x_i-x) w_i}{\sum
42     w_i} \f$ where \f$ I(x) = 1 \f$ for \f$ x>0 \f$, \f$I(x) = 0.5
43     \f$ for \f$ x=0 \f$, and \f$ I(x) = 0 \f$ for \f$ x<0 \f$.
44
45     \since New in yat 0.5
46   */
47  class Spearman
48  {
49  public:
50    /**
51       \brief default constructor
52     */
53    Spearman(void){}
54
55    /**
56       It is possible to centralize a range "in place"; it is
57       permissible for the iterators \a first and \a result to be the
58       same.
59     */
60    template<typename ForwardIterator, typename RandomAccessIterator>
61    void operator()(ForwardIterator first, ForwardIterator last,
62                    RandomAccessIterator result) const
63    {
64      typename utility::weighted_iterator_traits<ForwardIterator>::type tag;
65      normalize(first, last, result, tag);
66    }
67
68
69  private:
70    // unweighted version
71    template<typename ForwardIterator, typename RandomAccessIterator>
72    void normalize(ForwardIterator first, ForwardIterator last,
73                   RandomAccessIterator result, 
74                   utility::unweighted_iterator_tag) const
75    {
76      std::vector<size_t> perm;
77      utility::sort_index(first, last, perm);
78      double n = perm.size();
79      size_t i=0; 
80      while ( i<perm.size() ) {
81        size_t min_i = i;
82        while (i<perm.size() && first[perm[i]]<=first[perm[min_i]])
83          ++i;
84        double res = static_cast<double>(i + min_i)/(2*n);
85        for ( ; min_i < i; ++min_i)
86          result[perm[min_i]] = res;
87      }
88    }
89
90
91    // weighted version
92    template<typename ForwardIterator, typename RandomAccessIterator>
93    void normalize(ForwardIterator first, ForwardIterator last,
94                   RandomAccessIterator result, 
95                   utility::weighted_iterator_tag) const
96    {
97      std::copy(utility::weight_iterator(first), 
98                utility::weight_iterator(last),
99                utility::weight_iterator(result));
100      // set values with w=0 to 0 to avoid problems with NaNs
101      utility::iterator_traits<ForwardIterator> trait;
102      for (ForwardIterator i=first; i!=last; ++i)
103        if (trait.weight(i)==0)
104          trait.data(i)=0.0;
105
106      std::vector<size_t> perm(std::distance(first, last));
107      utility::sort_index(utility::data_iterator(first), 
108                          utility::data_iterator(last), perm);
109      utility::iterator_traits<RandomAccessIterator> rtrait;
110
111      double sum_w=0;
112      size_t i=0; 
113      while ( i<perm.size() ) {
114        double w=0;
115        size_t min_i = i;
116        while (i<perm.size() && (trait.weight(first+perm[i])==0 ||
117                                 trait.data(first+perm[i]) <= 
118                                 trait.data(first+perm[min_i])) ) {
119          w += trait.weight(first+perm[i]);
120          ++i;
121        }
122        double res=sum_w + 0.5*w;
123        for ( size_t j=min_i; j<i; ++j)
124          rtrait.data(result+perm[j]) = res;
125        sum_w += w;
126      }       
127
128      size_t n = std::distance(first, last);
129      std::transform(utility::data_iterator(result),
130                     utility::data_iterator(result+n),
131                     utility::data_iterator(result),
132                     std::bind2nd(std::divides<double>(), sum_w));
133    }
134
135  };
136
137}}} // end of namespace normalizer, yat and thep
138#endif
Note: See TracBrowser for help on using the repository browser.