2010-03-30 42 views
5

Tôi có tập dữ liệu với các mẫu N (ví dụ: 13, 16, 17, 20) trong đó mỗi mẫu tiếp theo được tăng thêm một số giá trị (3, 1, 3 trong trường hợp này)) và tôi muốn tìm các thống kê khác nhau của chuỗi thứ hai thứ hai.Lấy mẫu các giá trị giữa các giá trị sử dụng boost :: accumulators

Mẫu là dấu thời gian được thu thập gia tăng (nghĩa là không phải tất cả các mẫu đều có sẵn cùng một lúc), vì vậy tôi muốn sử dụng boost::accumulators::accumulator_set giống như một thứ phù hợp với hóa đơn.

Tôi muốn để có thể làm điều gì đó như thế này:

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

... NHƯNG lấy mẫu khác nhau thay vì giá trị thực tế.

Tôi làm cách nào để thực hiện điều đó với accumulator_set mà không theo dõi giá trị cuối cùng theo cách thủ công?

+0

Điều gì đó tương tự hoặc chính xác? Trung bình của sự khác biệt chỉ là sự khác biệt giữa mẫu đầu tiên và cuối cùng, chia cho (số lượng mẫu -1) ;-p –

+0

@Steve Jessop, tôi cũng muốn tính toán độ lệch chuẩn. Do đó sử dụng khung tích lũy. –

Trả lời

1

Câu trả lời này có thể liên quan nhiều hơn bạn muốn, nhưng ít nhất nó không phải là thái quá vì tôi sợ nó có thể xuất hiện. Ý tưởng sẽ là bắt đầu bằng cách tạo một loại trình lặp hoạt động như một bộ chuyển đổi từ các thuật toán "bình thường" sang kiểu trình tăng cường các thuật toán Boost. Đây là phần được bật ra đơn giản hơn một chút so với tôi thực sự mong đợi:

#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 

Sau đó là một phần không may mắn. Thư viện chuẩn có thuật toán adjacent_difference được cho là tạo luồng bạn muốn (sự khác biệt giữa các mục liền kề trong bộ sưu tập). Tuy nhiên, nó có một vấn đề nghiêm trọng : ai đó nghĩ rằng nó sẽ hữu ích cho nó để tạo ra một bộ sưu tập kết quả có cùng kích thước với bộ sưu tập đầu vào (mặc dù có một đầu vào rõ ràng hơn kết quả). Để làm điều đó, adjacent_difference để lại mục đầu tiên trong kết quả với một số giá trị không xác định, vì vậy bạn phải bỏ qua giá trị đầu tiên để nhận bất kỳ thứ gì hữu ích từ nó.

Để bù đắp cho điều đó, tôi lại thực hiện một thuật toán nhưstd::adjacent_difference với một sự khác biệt oh-so-nhỏ: vì không rõ ràng là một kết quả ít hơn đầu vào, nó chỉ sản xuất kết quả một ít hơn đầu vào, và không đưa ra giá trị vô nghĩa, không xác định trong kết quả. Kết hợp cả hai, chúng tôi nhận được:

#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

Tôi cảm thấy mình nên có thêm thông tin trong câu hỏi của mình. Vấn đề thực tế của tôi là tôi liên tục thu thập các mẫu dấu thời gian trong một hệ thống có độ trễ và muốn đo lường jitter, vì vậy lý tưởng tôi cần cập nhật số liệu thống kê của mình theo từng bước. Do đó, việc thu thập các mẫu là không mong muốn trong trường hợp này. –

+0

@Checkers: 'diffs' chỉ lấy đầu vào từ' input_iterator' và ghi kết quả vào 'output_iterator'.Đối với bản demo/thử nghiệm, 'input_iterator' kết nối với một bộ sưu tập - nhưng nó có thể dễ dàng đọc dữ liệu từ một tệp trên đĩa hoặc từ kết nối mạng. –

Các vấn đề liên quan