Pregunta Calcular la media y la desviación estándar de un vector de muestras en C ++ utilizando Boost


¿Hay alguna manera de calcular la media y la desviación estándar para un vector que contiene muestras usando Aumentar?

¿O tengo que crear un acumulador y alimentar el vector en él?


75
2017-09-30 21:59


origen


Respuestas:


Usando acumuladores es la forma de calcular los medios y las desviaciones estándar en Aumentar.

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;


42
2017-09-30 22:48



No sé si Boost tiene funciones más específicas, pero puede hacerlo con la biblioteca estándar.

Dado std::vector<double> v, esta es la manera ingenua:

#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);

Esto es susceptible de desbordamiento o subdesbordamiento para valores grandes o pequeños. Una forma ligeramente mejor de calcular la desviación estándar es:

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());

ACTUALIZAR para C ++ 11:

La llamada a std::transform se puede escribir usando una función lambda en lugar de std::minus y std::bind2nd(ahora desaprobado):

std::transform(v.begin(), v.end(), diff.begin(), [mean](double x) { return x - mean; });

175
2017-09-30 22:42



Si el rendimiento es importante para usted, y su compilador es compatible con lambdas, el cálculo stdev puede hacerse más rápido y sencillo: en pruebas con VS 2012 descubrí que el código siguiente es 10 veces más rápido que el código Boost proporcionado en la respuesta elegida ; también es 5 veces más rápido que la versión más segura de la respuesta usando bibliotecas estándar dadas por musiphil.

Tenga en cuenta que estoy usando la desviación estándar de la muestra, por lo que el siguiente código da resultados ligeramente diferentes (Por qué hay un Minus One en las desviaciones estándar)

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));

53
2017-09-13 12:01



Mi respuesta es similar a la de Josh Greifer, pero se generalizó para muestrear la covarianza. La varianza muestral es simplemente covarianza muestral pero con las dos entradas idénticas. Esto incluye la correlación de Bessel.

    template <class Iter> typename Iter::value_type cov(const Iter &x, const Iter &y)
    {
        double sum_x = std::accumulate(std::begin(x), std::end(x), 0.0);
        double sum_y = std::accumulate(std::begin(y), std::end(y), 0.0);

        double mx =  sum_x / x.size();
        double my =  sum_y / y.size();

        double accum = 0.0;

        for (auto i = 0; i < x.size(); i++)
        {
            accum += (x.at(i) - mx) * (y.at(i) - my);
        }

        return accum / (x.size() - 1);
    }

1
2018-04-22 12:38



2 veces más rápido que las versiones antes mencionadas, principalmente porque se unen los bucles transform () y inner_product (). Lo siento por mi atajo / typedefs / macro: Flo = float. Cit = const iteration. CR const ref. VFlo - vector. Probado en VS2010

Flo     stdDev2(VFlo CR crVec) {
    SZ  n = crVec.size();                               if (n < 2) return 0.0f;
    Flo fSqSum = 0.0f, fSum = 0.0f;
    Cit(VFlo, crVec) {
        Flo f   = *cx;
        fSqSum  += f * f; 
        fSum    += f;
    } 
    Flo fSumSq      = fSum * fSum;
    Flo fSumSqDivN  = fSumSq / n;
    Flo fSubSqSum   = fSqSum - fSumSqDivN;
    Flo preSqrt     = fSubSqSum / (n-1);
    return  sqrt(preSqrt);
}

0
2017-10-25 02:46



Crea tu propio contenedor:

template <class T>
class statList : public std::list<T>
{
    public:
        statList() : std::list<T>::list() {}
        ~statList() {}
        T mean() {
           return accumulate(begin(),end(),0.0)/size();
        }
        T stddev() {
           T diff_sum = 0;
           T m = mean();
           for(iterator it= begin(); it != end(); ++it)
               diff_sum += ((*it - m)*(*it -m));
           return diff_sum/size();
        }
};

Tiene algunas limitaciones, pero funciona muy bien cuando sabes lo que estás haciendo.


-2
2017-08-08 22:50



// significa desviación en c ++

/Una desviación que es una diferencia entre un valor observado y el valor verdadero de una cantidad de interés (como una media poblacional) es un error y una desviación que es la diferencia entre el valor observado y una estimación del valor verdadero (tal la estimación puede ser una media muestral) es un residuo. Estos conceptos son aplicables para los datos en los niveles de medición de intervalos y proporciones./

#include <iostream>
#include <conio.h>
using namespace std;

/* run this program using the console pauser or add your own getch,     system("pause") or input loop */

int main(int argc, char** argv)
{
int i,cnt;
cout<<"please inter count:\t";
cin>>cnt;
float *num=new float [cnt];
float   *s=new float [cnt];
float sum=0,ave,M,M_D;

for(i=0;i<cnt;i++)
{
    cin>>num[i];
    sum+=num[i];    
}
ave=sum/cnt;
for(i=0;i<cnt;i++)
{
s[i]=ave-num[i];    
if(s[i]<0)
{
s[i]=s[i]*(-1); 
}
cout<<"\n|ave - number| = "<<s[i];  
M+=s[i];    
}
M_D=M/cnt;
cout<<"\n\n Average:             "<<ave;
cout<<"\n M.D(Mean Deviation): "<<M_D;
getch();
return 0;

}


-6
2017-08-07 08:24