Frage Berechnen Sie Mittelwert und Standardabweichung von einem Vektor von Samples in C ++ mit Boost


Gibt es eine Möglichkeit, den Mittelwert und die Standardabweichung für einen Vektor, der Proben enthält, zu berechnen? Boost?

Oder muss ich einen Akkumulator erstellen und den Vektor hineinführen?


75
2017-09-30 21:59


Ursprung


Antworten:


Akkus verwenden ist der Weg zur Berechnung von Mittelwerten und Standardabweichungen in 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;


42
2017-09-30 22:48



Ich weiß nicht, ob Boost spezifischere Funktionen hat, aber Sie können es mit der Standardbibliothek tun.

Gegeben std::vector<double> v, das ist der naive Weg:

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

Dies ist anfällig für Überlauf oder Unterlauf für große oder kleine Werte. Ein etwas besserer Weg zur Berechnung der Standardabweichung ist:

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

AKTUALISIEREN für C ++ 11:

Der Anruf zu std::transform kann mit einer Lambda-Funktion anstelle von geschrieben werden std::minus und std::bind2nd(jetzt veraltet):

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

175
2017-09-30 22:42



Wenn die Leistung für Sie wichtig ist und Ihr Compiler lambdas unterstützt, kann die stdev-Berechnung schneller und einfacher durchgeführt werden: In Tests mit VS 2012 habe ich festgestellt, dass der folgende Code 10 x schneller ist als der in der gewählten Antwort angegebene Boost-Code ; Es ist auch 5 X schneller als die sicherere Version der Antwort mit Standard-Bibliotheken von Musiphil gegeben.

Hinweis: Ich verwende die Standardabweichung für die Stichprobe, daher gibt der folgende Code leicht abweichende Ergebnisse (Warum gibt es einen Minus One in Standardabweichungen?)

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



Meine Antwort ist ähnlich wie Josh Greifer, aber verallgemeinert, um die Kovarianz zu testen. Stichprobenvarianz ist nur Stichprobenkovarianz, aber mit den zwei Eingaben identisch. Dies beinhaltet die Korrelation von 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



2x schneller als die zuvor genannten Versionen - vor allem weil die Schleifen transform () und inner_product () zusammengefügt sind. Entschuldige meine Verknüpfung / typedefs / macro: Flo = float. Cit = konstante Iteration. CR const ref. VFlo - Vektor. Getestet in 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



Erstelle deinen eigenen Container:

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

Es hat einige Einschränkungen, aber es funktioniert wunderbar, wenn Sie wissen, was Sie tun.


-2
2017-08-08 22:50



// bedeutet Abweichung in C ++

/Eine Abweichung, die eine Differenz zwischen einem beobachteten Wert und dem wahren Wert einer interessierenden Größe ist (z. B. ein Populationsmittelwert), ist ein Fehler und eine Abweichung, die die Differenz zwischen dem beobachteten Wert und einer Schätzung des wahren Werts (wie z Schätzung kann ein Stichprobenmittel sein) ist ein Residuum. Diese Konzepte sind für Daten in den Intervall- und Verhältnisstufen der Messung anwendbar./

#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