2010-03-30 30 views
5

我有一个数据集有N个样本(比如13,16,17,20),其中每个下一个样本都增加了一些值(在这种情况下为3,1,3) ),我想找到第二序列的各种统计数据。使用boost :: accumulators来取值之间的增量值

样本是渐进式收集的时间戳(即并非所有样本都可以一次使用),因此我想使用boost::accumulators::accumulator_set,因为它看起来像是适合帐单的东西。

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

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

... 采样的差异,而不是实际值。

我该如何做到这一点与accumulator_set没有手动跟踪上一个值?

+0

这样的事情,或者确切的说呢?差异的平均值只是第一个和最后一个样本之间的差值除以(样本数-1); -p – 2010-03-30 22:28:34

+0

@Steve Jessop,我也想计算标准偏差。因此使用累加器框架。 – 2010-03-30 22:33:41

回答

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一个哦,所谓微小的差别:因为有明显的一个不是投入少的结果,它只是产生少一个结果不是投入,并没有给出结果中没有意义的,未指明的价值。结合两者,我们得到:

#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; 
} 
+0

我觉得我应该在我的问题中提供更多信息。我的实际问题是,我不断在延迟敏感的系统中收集时间戳样本,并且想要测量抖动,所以理想情况下我需要逐步更新我的统计数据。因此,在这种情况下收集样品是不理想的。 – 2010-03-31 10:14:44

+0

@Checkers:'diffs'只需从'input_iterator'输入输入并将结果写入'output_iterator'。对于演示/测试,'input_iterator'连接到一个集合 - 但它可以轻松地从磁盘上的文件或网络连接读取数据。 – 2010-03-31 14:16:28