如何用迭代器和lambda函数计算标准差

时间:2015-02-20 17:16:34

标签: c++ lambda iterator

在得知可以计算存储在std::vector< std::vector<double> > data中的数据平均值后,可以通过以下方式完成:

void calculate_mean(std::vector<std::vector<double>>::iterator dataBegin,
                    std::vector<std::vector<double>>::iterator dataEnd, 
                    std::vector<double>& rowmeans) {
    auto Mean = [](std::vector<double> const& vec) {
                    return std::accumulate(vec.begin(), vec.end(), 0.0) / vec.size(); };
    std::transform(dataBegin, dataEnd, rowmeans.begin(), Mean);
}

我创建了一个函数,它接受数据向量的迭代器的开始和结束来计算平均值,std::vector<double>是我存储结果的位置。 我的第一个问题是,在使用向量时如何处理函数的返回值。我的意思是在这种情况下我创建一个Alias并以这种方式修改我在调用此函数之前初始化的向量,因此没有复制回来这很好。这是一个很好的编程实践吗?

其次我的主要问题是,如何调整这个功能,以便以类似的方式计算每一行的标准差。我真的很努力,但它只是给了一个很大的混乱,没有什么工作正常。因此,如果有人立即看到它如何做到这一点,我会很高兴,以获得洞察力。谢谢。

编辑:解决方案

所以这是我解决问题的方法。给定std::vector< vector<double> > data (rows, std::vector<double>(columns)),数据存储在行中。以下函数同时计算每行的样本标准差。

auto begin = data.begin();
auto end = data.end();
std::vector<double> std;
std.resize(data.size());

void calculate_std(std::vector<std::vector<double>>::iterator dataBegin,
                   std::vector<std::vector<double>>::iterator dataEnd,
                   std::vector<double>& rowstds){

    auto test = [](std::vector<double> const& vec) {
                    double sum = std::accumulate(vec.begin(), vec.end(), 0.0);
                    double mean = sum / vec.size(); 
                    double stdSum = 0.0;
                    auto Std = [&](const double x) { stdSum += (x - mean) * (x - mean); }; 
                    std::for_each(vec.begin(), vec.end(), Std);
                    return sqrt(stdSum / (vec.size() - 1)); 
    };
    std::transform(dataBegin, dataEnd, rowstds.begin(), test);

}  

我测试了它,它工作得很好。因此,如果有人有一些改进建议,请告诉我。这段代码是否具有良好的性能?

2 个答案:

答案 0 :(得分:0)

您会找到相对常见的惯例,用输入参数优先编写函数,然后是输入/输出参数。 输出参数(使用函数的返回值写入)通常是指向数据或引用的指针。 从这个角度来看,你的解决方案看起来很完美。

来源: Google's C++ coding conventions

答案 1 :(得分:0)

  

我的意思是在这种情况下我创建一个Alias并以这种方式修改我在调用此函数之前初始化的向量,因此没有复制回来这很好。这是一个很好的编程实践吗?

不,您应该使用本地vector<double>变量并按值返回。任何值得使用的编译器都是optimize away the copying/moving,并且如果由于某种原因它无法完全忽略复制/移动,则需要任何符合要求的C ++ 11编译器来执行移动。

您编写的代码对调用者施加了不明显的附加要求。例如,rowmeans必须包含足够的元素来存储均值或未定义的行为结果。