boost++::weighted_median и eigen::vectorXf --newbie

Я хотел бы получить weighted_median несортированного объекта переменной длины, собственного объекта c++ vectorXf. Кажется, я могу использовать функцию boost weighted_median из библиотеки статистических аккумуляторов boost, чтобы сделать это эффективно [?].

По сути, я пытаюсь сделать что-то очень похожее на то, что сделано здесь. Я не уверен, что аккумулятор boost является подходящей структурой для этой задачи (если нет, пожалуйста, посоветуйте!), но я не нашел другой реализации взвешенной медианы O (n) на полке.

На данный момент мой вопрос заключается в том, есть ли способ заменить приведенный ниже цикл for(int i=0;i‹100;i++) более элегантной конструкцией?

P.S. я видел этот ТАК вопрос, но не совсем понятно, как включить ответ там к рабочему решению.

#include <Eigen/Dense>
#include <iostream>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/median.hpp>
#include <boost/accumulators/statistics/weighted_median.hpp>
using namespace boost::accumulators;    
using namespace Eigen;

int main(){
    accumulator_set<float, stats<tag::median > > acc1;
    accumulator_set<float, stats<tag::median >,int> acc2;

    VectorXi rw=VectorXi::Random(100);
    VectorXf rn=VectorXf::Random(100);

    rw=rw.cwiseAbs();
    for(int i=0;i<100;i++){
        acc1(rn(i));
        acc2(rn(i),weight=rw(i));
    }

  std::cout << "         Median: " << median(acc1) << std::endl;
  std::cout << "Weighted Median: " << median(acc2) << std::endl;

  return 0;
}

person user189035    schedule 21.06.2012    source источник


Ответы (1)


То, что вы пытаетесь сделать, это использовать аккумуляторы повышения для накопления значений в каком-то контейнере. Вы заметите, что даже передача std::vector<float> в аккумулятор не сработает. Аккумуляторы просто не предназначены для такого использования. Конечно, вы можете использовать аккумуляторы для накопления векторных или матричных значений, но это не то, что вам здесь нужно.

Вы можете использовать std::for_each, чтобы избавиться от явного цикла, вот и все:

// median
using boost::bind;
using boost::ref;
std::for_each(rn.data(), rn.data()+rn.rows(), bind<void>( ref(acc1), _1 ) );

вопрос, на который вы ссылаетесь, больше не актуален в последней версии Eigen3. . Приведенный там код работает нормально и дает правильные результаты.

person Kuba hasn't forgotten Monica    schedule 21.06.2012
comment
Я не знаю, есть ли такой же чистый способ сделать это с именованными параметрами, связанными со взвешенной медианой. Гуру по продвижению, отзовитесь. - person Kuba hasn't forgotten Monica; 22.06.2012