2010-03-30 54 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