Ignore:
Timestamp:
Aug 8, 2008, 12:47:18 AM (13 years ago)
Author:
Peter
Message:

refs #366 - weighted percentile
Added a class Percentile that can calculate the percentile for both
unweighted and weighted ranges. In order to make sense of the weighted
case, I had to modify the definition of percentile (slightly). The old
function percentile is using the old definition, but a new function,
percentile2, is using the new function and is simply calling the
Percentile class. The median is the same for the two definitions and
therefore it makes no difference which function to call, but to enable
calculation of weighted median percentile2 is called.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/yat/statistics/utility.h

    r1338 r1404  
    153153  template <class T>
    154154  double median(T first, T last, const bool sorted=false)
    155   { return percentile(first, last, 50.0, sorted); }
     155  { return percentile2(first, last, 50.0, sorted); }
    156156
    157157  /**
     
    170170     
    171171     Requirements: T should be an iterator over a range of doubles (or
    172      any type being convertable to double). If \a sorted is false
    173      iterator must be mutable, else read-only iterator is also ok.
     172     any type being convertable to double).
    174173     
    175174     @return \a p'th percentile of range
    176   */
    177   template <class T>
    178   double percentile(T first, T last, double p, bool sorted=false)
     175
     176     \deprecated percentile2 will replace this function in the future
     177
     178     \note the definition of percentile used here is not identical to
     179     that one used in percentile2 and Percentile. The difference is
     180     smaller for large ranges.
     181  */
     182  template <class RandomAccessIterator>
     183  double percentile(RandomAccessIterator first, RandomAccessIterator last,
     184                    double p, bool sorted=false)
     185  {
     186    // range is one value only is a special case
     187    if (first+1 == last)
     188      return utility::iterator_traits<RandomAccessIterator>().data(first);
     189    if (sorted) {
     190      // have to take care of this special case
     191      if (p>=100)
     192        return utility::iterator_traits<RandomAccessIterator>().data(--last);
     193      double j = p/100 * (std::distance(first,last)-1);
     194      int i = static_cast<int>(j);
     195      return (1-j+floor(j))*first[i] + (j-floor(j))*first[i+1];
     196    }
     197
     198    std::vector<typename std::iterator_traits<RandomAccessIterator>::value_type>
     199      v_copy;
     200    v_copy.reserve(std::distance(first,last));
     201    std::copy(first, last, std::back_inserter(v_copy));
     202    size_t i = static_cast<size_t>(p/100 * (v_copy.size()-1));
     203    if (i+2 < v_copy.size()) {
     204      std::partial_sort(v_copy.begin(), v_copy.begin()+i+2, v_copy.end());
     205    }
     206    else
     207      std::sort(v_copy.begin(), v_copy.end());
     208    return percentile(v_copy.begin(), v_copy.end(), p, true);
     209  }
     210
     211
     212  /**
     213     \see Percentiler
     214     
     215     \since new in yat 0.5
     216   */
     217  template <class RandomAccessIterator>
     218  double percentile2(RandomAccessIterator first, RandomAccessIterator last,
     219                     double p, bool sorted=false)
    179220  {
    180221    Percentiler percentiler(p, sorted);
Note: See TracChangeset for help on using the changeset viewer.