В Boost.Accumulator вы можете добавить выборки в аккумулятор и затем извлечь из него статистические величины. например:
acc(1.)
acc(2.)
acc(3.)
cout << mean; // 2
В библиотеке есть много более сложных статистических величин, таких как skewness
, kurtosis
, или же p_square_cumulative_distribution
,
Я хотел бы сделать что-то вроде этого:
acc(1.)
acc(2.)
acc(3.)
std::cout << mean(acc); // 2
acc.pop() // withdraw the first value (1.)
std::cout << mean(acc); // 2.5
pop()
будет работать в режиме FIFO (First In First Out). То, что я пытаюсь сделать, — это вычислять статистику по моим данным в режиме онлайн (инкрементно) в скользящем временном окне.
Аккумулятор должен был бы внутренне хранить все значения.
Я мог бы сделать это самостоятельно, но я всегда хотел бы сначала проверить наличие существующих библиотек, и, возможно, существует алгоритм, которого я не знаю, который умно вычисляет количества, когда данные поступают или исходят.
Поскольку вы упомянули «скользящее временное окно», одним из вариантов является использование скользящего среднего (есть также скользящая сумма и скользящий счет), которое является средним значением последнего N образцы. В зависимости от ваших потребностей вы можете создать отдельные аккумуляторы с разными размерами окон.
typedef accumulator_set<double,
stats<tag::rolling_mean>
> my_accumulator;
my_accumulator acc(tag::rolling_window::window_size = 3);
acc(1.);
acc(2.);
acc(3.);
std::cout << rolling_mean(acc);
// Reset accumulator and use different window size
acc = my_accumulator(tag::rolling_window::window_size = 2);
acc(2.);
acc(3.);
std::cout << rolling_mean(acc);
Кроме того, если вы посмотрите на реализацию этих, они используют boost/circular_buffer.hpp
,
Вам, вероятно, нужно будет просто сохранить все свои выборки в векторе, а затем накапливать их из вектора для каждого расчета. Что-то вроде этого: https://stackoverflow.com/a/7616783/219136
Вы, вероятно, хотите сохранить данные в std::deque
вместо вектора, поэтому ваша вставка и удаление могут иметь постоянную сложность. Если вы используете вектор, он неизбежно будет линейным.
Кроме этого, довольно просто применить алгоритм к коллекции. Странно, однако, что я не знаю коллекцию таких алгоритмов, уже написанных и протестированных, несмотря на то, что набор доступных алгоритмов кажется довольно очевидным.
Для чего бы это ни стоило, довольно просто создать адаптер для подачи данных из коллекции в накопитель для вычисления статистики, которую вы можете получить. В некоторых случаях аккумулятору, вероятно, придется проделать дополнительную работу, чтобы постепенно вычислять результаты, но я думаю, что довольно редко можно потерять достаточную эффективность, чтобы о ней заботиться.