use*_*144 84 c++ algorithm statistics boost mean
有没有办法使用Boost计算含有样品的载体的平均值和标准偏差?
或者我是否必须创建一个累加器并将矢量输入其中?
mus*_*hil 202
我不知道Boost是否具有更多特定功能,但您可以使用标准库来完成.
鉴于std::vector<double> v
,这是天真的方式:
#include <numeric>
double sum = std::accumulate(v.begin(), v.end(), 0.0);
double mean = sum / v.size();
double sq_sum = std::inner_product(v.begin(), v.end(), v.begin(), 0.0);
double stdev = std::sqrt(sq_sum / v.size() - mean * mean);
Run Code Online (Sandbox Code Playgroud)
对于巨大或微小的值,这容易发生溢出或下溢.计算标准偏差的更好方法是:
double sum = std::accumulate(v.begin(), v.end(), 0.0);
double mean = sum / v.size();
std::vector<double> diff(v.size());
std::transform(v.begin(), v.end(), diff.begin(),
std::bind2nd(std::minus<double>(), mean));
double sq_sum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0);
double stdev = std::sqrt(sq_sum / v.size());
Run Code Online (Sandbox Code Playgroud)
更新 C++ 11:
要将呼叫std::transform
可以使用lambda函数,而不是被写入std::minus
和std::bind2nd
(现在已废弃):
std::transform(v.begin(), v.end(), diff.begin(), [mean](double x) { return x - mean; });
Run Code Online (Sandbox Code Playgroud)
Jos*_*fer 62
如果性能对您很重要,并且您的编译器支持lambdas,则可以更快更简单地进行stdev计算:在使用VS 2012的测试中,我发现以下代码比所选答案中给出的Boost代码快10倍以上; 使用musiphil提供的标准库,它比使用更安全版本的答案快5倍.
注意我正在使用样本标准偏差,因此下面的代码给出了略微不同的结果(为什么标准差中有一个减号)
double sum = std::accumulate(std::begin(v), std::end(v), 0.0);
double m = sum / v.size();
double accum = 0.0;
std::for_each (std::begin(v), std::end(v), [&](const double d) {
accum += (d - m) * (d - m);
});
double stdev = sqrt(accum / (v.size()-1));
Run Code Online (Sandbox Code Playgroud)
Dav*_*hme 50
使用累加器是计算Boost中的均值和标准差的方法.
accumulator_set<double, stats<tag::variance> > acc;
for_each(a_vec.begin(), a_vec.end(), bind<void>(ref(acc), _1));
cout << mean(acc) << endl;
cout << sqrt(variance(acc)) << endl;
Run Code Online (Sandbox Code Playgroud)
似乎以下优雅的递归解决方案尚未被提及,尽管它已经存在很长时间了。参考 Knuth 的《计算机编程艺术》,
mean_1 = x_1, variance_1 = 0; //initial conditions; edge case;
//for k >= 2,
mean_k = mean_k-1 + (x_k - mean_k-1) / k;
variance_k = variance_k-1 + (x_k - mean_k-1) * (x_k - mean_k);
Run Code Online (Sandbox Code Playgroud)
那么对于值列表n>=2
,标准差的估计值为:
stddev = std::sqrt(variance_n / (n-1)).
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助!
改进musiphil 的答案,您可以编写没有临时 vector 的标准偏差函数diff
,只需使用inner_product
具有 C++11 lambda 功能的单个调用:
double stddev(std::vector<double> const & func)
{
double mean = std::accumulate(func.begin(), func.end(), 0.0) / func.size();
double sq_sum = std::inner_product(func.begin(), func.end(), func.begin(), 0.0,
[](double const & x, double const & y) { return x + y; },
[mean](double const & x, double const & y) { return (x - mean)*(y - mean); });
return std::sqrt(sq_sum / func.size());
}
Run Code Online (Sandbox Code Playgroud)
我怀疑多次减法比使用额外的中间存储更便宜,我认为它更具可读性,但我还没有测试过性能。
归档时间: |
|
查看次数: |
131709 次 |
最近记录: |