Boost.Accumulators是一个累加器,实现的功能很简单,就是对一组数据进行操作,然后可以得到一些特征数据。
由于累加器默认不对数据进行储存操作,所以不能把它作为一个简单的容器使用。
简单使用
从实际使用上来看,它应该是一个header only库,所以可以直接include,不需要在最后的时候进行链接操作。
它的一般操作步骤如下:
- 定义一个累加器
- 输入数据
- 获取结果
先来看一个简单的例子吧。
#include <iostream>
#include <string>
#include <vector>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/sum.hpp>
namespace ba = boost::accumulators;
int main() {
ba::accumulator_set<double, ba::stats<ba::tag::mean, ba::tag::sum>> acc;
acc(100);
acc(101);
acc(102);
std::cout << ba::mean(acc) << " " << ba::sum(acc) << std::endl;
return 0;
}
这个例子实现了一个简单的求平均和求和的累加器。
首先来看main
函数里面的第一句,这里定义了一个名为acc
的累加器。
ba::accumulator_set<double, ba::stats<ba::tag::mean, ba::tag::sum>> acc;
accumulator_set
的定义为
template< typename Sample, typename Features, typename Weight = void >
struct accumulator_set;
模板里面第一个参数为数据的类型;第二个参数是在运行中需要计算的特征,它是Boost::MPL里的模板向量;第三个参数是权重的类型,这一个我们在后面讨论。
然后就是向累加器里面添加数据,可以看到定义好的累加器是作为一个函数对象使用的(重载了()
操作符)。因此也可以如下操作:
std::vector data({1, 2, 3, 4});
std::for_each(data.begin(), data.end(), acc);
这样操作可以很方便的对data
里面的数据进行遍历操作。
在添加完数据之后,便是获取最后的结果:
std::cout << ba::mean(acc) << " " << ba::sum(acc) << std::endl;
这里我们使用了对应特征的函数,来获取对应的特征结果。
官方给出的可以使用的特征有很多种,详细的信息可以访问The Statistical Accumulators Library,里面有每一种特征详细的定义和使用方法。
加权
在统计中,我们也经常会遇到需要加权统计的情况。从之前的accumulator_set
的定义中,我们也可以很清晰的看到,其也有权重的类型。所以他也是可以使用权重来对数据进行操作的。
使用加权的累加器和使用普通的累加器
#include <iostream>
#include <string>
#include <vector>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/sum.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics.hpp>
namespace ba = boost::accumulators;
int main() {
ba::accumulator_set<double, ba::stats<ba::tag::mean, ba::tag::sum>, double> acc;
acc(10.2, ba::weight = 1.5);
acc(20.1, ba::weight = 100);
acc(30, ba::weight = 2);
std::cout << ba::mean(acc) << " " << ba::sum(acc) << std::endl;
return 0;
}
主要的不同表现在定义和输入阶段。首先是定义,相比之前的定义,加权的累加器增加了权重的类型(第三个模板参数)。其实第二个参数,也是有一些不同的,应该使用加权的特征,但是一些巧妙的设计,让它们看起来一致。
然后是在输入的阶段,输入阶段要增加一个参数,数据的权重。看起来有点像python了,但是区别还是很大的。它其实是输入了一个结构体,但是看起来的确很优雅。
进阶使用
以上就是累加器的简单使用,需要更进一步的使用,就可以自己定义累加器或者是特征了。