基于另一个向量c ++中的相似性的向量的条件平均

时间:2014-06-25 22:10:01

标签: c++ vector conditional average

最好举个例子。

让我们说矢量A包括:

A = {3  ,2 ,1 ,4  ,6 ,3 ,8 ,4}

和向量B包括:

B = {1.5,2 ,2 ,1.5,3 ,3 ,3 ,2}

向量B中的唯一值为{1.5, 2, 3}

我希望得到的矢量RESULT为:

RESULT[0] = Average(A given B=1.5) = Average(3,4)

RESULT[1] = Average(A given B=2 )  = Average(2,1,4)

RESULT[2] = Average(A given B=3 )  = Average(6,3,8)

计算此数据的最有效方法是什么。我自己的方法是循环遍历B的唯一元素,并为每个元素循环遍历每个B值,试图匹配该唯一数字,并在每次匹配中保持向量A的相应元素的总结,同时计算匹配的数量,以便我可以找到平均值。

这太慢了。因为我的矢量A是8M元素,矢量B是0.5M唯一值。

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:3)

这是一个懒惰的想法:以锁步方式遍历两个向量并将结果聚合在一个单独的容器中。例如:

#include <cassert>
#include <cmath>
#include <iostream>
#include <map>
#include <utility>

std::map<double, std::pair<int, std::size_t>> m;

assert(A.size() == B.size());

for (std::size_t i = 0; i != A.size(); ++i)
{
    assert(!std::isnan(B[i]));

    auto & p = m[B[i]];
    p.first += A[i];
    p.second += 1;
}

最后,您只需报告结果:

for (const auto & p : m)
    std::cout << "Average for bin " << p.first << " is "
              << static_cast<double>(p.second.first) / p.second.second
              << "\n";

(请注意,您的键值不能是NaN:在有序映射中,NaN不是严格排序的一部分;在无序映射中,它不会与自身进行比较。)

答案 1 :(得分:1)

你可以用(哈希)表做一个循环:看到它 Live On Coliru

int main()
{
    vector<int>    A = {3  ,2 ,1 ,4  ,6 ,3 ,8 ,4};
    vector<double> B = {1.5,2 ,2 ,1.5,3 ,3 ,3 ,2};

    assert(A.size() == B.size());

    struct accum { 
        uintmax_t sum = 0; 
        size_t number_of_samples = 0; 
        void sample(int val) { sum += val; ++number_of_samples; }
    };
    map<double, accum> average_state;

    for(size_t i = 0; i<B.size(); ++i)
        average_state[B[i]].sample(A[i]);

    for(auto& entry : average_state)
    {
        accum& state = entry.second;
        double average = static_cast<double>(state.sum) / state.number_of_samples;
        std::cout << "Bucket " << entry.first << "\taverage of " << state.number_of_samples << " samples:\t" << average << "\n";
    }
}

打印

Bucket 1.5  average of 2 samples:   3.5
Bucket 2    average of 3 samples:   2.33333
Bucket 3    average of 3 samples:   5.66667