使用boost :: accumulators对值之间的增量进行采样

时间:2010-03-30 22:18:54

标签: c++ boost

我有一个包含N个样本的数据集(例如,13,16,17,20),其中每个下一个样本都会增加一些值(在这种情况下为3,1,3),我想查找各种统计数据。 第二个序列

样本是以递增方式收集的时间戳(即并非所有样本都可以一次获得),因此我想使用boost::accumulators::accumulator_set看起来像是适合该法案的东西。

我希望能够做到这样的事情:

accumulator_set< double, features< tag::mean > > acc;
...
acc(13);
acc(16);
acc(17);
acc(20);

... 但是对差异进行采样而不是实际值。

如何在不跟踪最后一个值的情况下使用accumulator_set执行此操作?

2 个答案:

答案 0 :(得分:3)

增压累加器没有差异统计量。你可以自己动手:

http://www.boost.org/doc/libs/1_37_0/doc/html/accumulators/user_s_guide.html#accumulators.user_s_guide.the_accumulators_framework.extending_the_accumulators_framework

我认为最好的解决方案就是跟踪最后添加的值。

答案 1 :(得分:1)

这个答案可能比你想要的更多,但至少它并不像我担心它可能会变得那么离谱。我们的想法是从创建一个迭代器类型开始,该类型充当从“普通”算法到Boost累加器算法样式的适配器。这个部分比我预期的要简单一些:

#ifndef ACCUM_ITERATOR_H_INCLUDED
#define ACCUM_ITERATOR_H_INCLUDED

#include <iterator>

template <class Accumulator>
class accum_iterator :
    public std::iterator<std::output_iterator_tag,void,void,void,void> {
protected:
    Accumulator &accumulator;
public:
    typedef Accumulator accumulator_type;
    explicit accum_iterator(Accumulator& x) : accumulator(x) {}

    // The only part that really does anything: handle assignment by 
    // calling the accumulator with the value.
    accum_iterator<Accumulator>&
        operator=(typename Accumulator::sample_type value) {
            accumulator(value);
            return *this;
    }
    accum_iterator<Accumulator>& operator*() { return *this; }
    accum_iterator<Accumulator>& operator++() { return *this; }
    accum_iterator<Accumulator> operator++(int) { return *this; }
};

// A convenience function to create an accum_iterator for a given accumulator.    
template <class Accumulator>
accum_iterator<Accumulator> to_accum(Accumulator &accum) { 
    return accum_iterator<Accumulator>(accum);
}

#endif

然后是一个有点不幸的部分。标准库具有adjacent_difference算法,该算法应该生成您想要的流(集合中相邻项之间的差异)。它有一个严重的问题:有人认为生成一个与输入集合大小相同的结果集合会很有用(即使显然有一个输入而不是结果)。为此,adjacent_difference将结果中的第一项留下一些未指定的值,因此您必须忽略第一个值才能从中获取任何有用的内容。

为了弥补这一点,我重新实现了一个算法,如 std::adjacent_difference,只有一个很小的区别:因为显然结果比输入少一个,它只有< em>生成比输入少一个结果,并且不会在结果中给出无意义的,未指定的值。结合这两者,我们得到:

#include "accum_iterator.h"
#include <iostream>
#include <vector>

#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/mean.hpp>
using namespace boost::accumulators;

// A re-implementation of std::adjacent_difference, but with sensible outputs.
template <class InIt, class OutIt>
void diffs(InIt in1, InIt in2, OutIt out) { 
    typename InIt::value_type prev = *in1;
    ++in1;
    while (in1 != in2) {
        typename InIt::value_type temp = *in1;
        *out++ = temp - prev;
        prev = temp;
        ++in1;
    }
}

int main() {
    // Create the accumulator.
    accumulator_set<double, features< tag::mean > > acc;  

    // Set up the test values.
    std::vector<double> values;
    values.push_back(13);
    values.push_back(16);
    values.push_back(17);
    values.push_back(20);

    // Use diffs to compute the differences, and feed the results to the 
    // accumulator via the accum_iterator:
    diffs(values.begin(), values.end(), to_accum(acc));

    // And print the result from the accumulator:    
    std::cout << "Mean:   " << mean(acc) << std::endl;
    return 0;
}