Calculer la moyenne et l’écart type à partir d’un vecteur d’échantillons en C ++ en utilisant Boost

Existe-t-il un moyen de calculer la moyenne et l’écart type pour un vecteur contenant des échantillons à l’aide de Boost ?

Ou dois-je créer un accumulateur et y insérer le vecteur?

L’utilisation d’accumulateurs est le moyen de calculer les moyennes et les écarts types dans Boost .

accumulator_set > acc; for_each(a_vec.begin(), a_vec.end(), bind(ref(acc), _1)); cout << mean(acc) << endl; cout << sqrt(variance(acc)) << endl; 

Je ne sais pas si Boost a des fonctions plus spécifiques, mais vous pouvez le faire avec la bibliothèque standard.

Étant donné std::vector v , c’est la manière naïve:

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

Ceci est susceptible de déborder ou de sous déborder pour des valeurs énormes ou minuscules. Une façon légèrement meilleure de calculer l’écart type est la suivante:

 double sum = std::accumulate(v.begin(), v.end(), 0.0); double mean = sum / v.size(); std::vector diff(v.size()); std::transform(v.begin(), v.end(), diff.begin(), std::bind2nd(std::minus(), mean)); double sq_sum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0); double stdev = std::sqrt(sq_sum / v.size()); 

UPDATE pour C ++ 11:

L’appel à std::transform peut être écrit en utilisant une fonction lambda au lieu de std::minus et std::bind2nd (maintenant obsolète):

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

Si la performance est importante pour vous et que votre compilateur supporte lambdas, le calcul stdev peut être rendu plus rapide et plus simple: Dans les tests avec VS 2012, j’ai trouvé que le code suivant est plus rapide que le code Boost donné dans la réponse choisie ; c’est aussi 5 X plus rapide que la version plus sûre de la réponse en utilisant des bibliothèques standard données par musiphil.

Notez que j’utilise un écart-type, le code ci-dessous donne des résultats légèrement différents ( pourquoi il y a un moins un dans l’écart-type )

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

Ma réponse est similaire à celle de Josh Greifer mais généralisée à la covariance des échantillons. La variance de l’échantillon n’est que la covariance de l’échantillon, mais les deux entrées sont identiques. Cela inclut la corrélation de Bessel.

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

2x plus rapide que les versions précédentes – principalement parce que les boucles transform () et inner_product () sont jointes. Désolé pour mon raccourci / typedefs / macro: Flo = float. Cit = const itération. CR const ref. VFlo – vecteur. Testé dans 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); } 

En améliorant la réponse par musiphil ci – dessus , vous pouvez écrire une fonction d’écart-type sans le diff vectoriel temporaire, en utilisant simplement un seul appel inner_product avec les fonctionnalités lambda C ++ 11:

 double stddev(std::vector const & func) { double mean = std::accumulate(func.begin(), func.end(), 0.0) / func.size(); double sq_sum = std::inner_product(func.begin(), func.end(), func.begin(), 0.0, [](double const & x, double const & y) { return x + y; }, [mean](double const & x, double const & y) { return (x - mean)*(y - mean); }); return sq_sum / ( func.size() - 1 ); } 

Je pense que la soustraction à plusieurs resockets est moins chère que l’utilisation d’un stockage intermédiaire supplémentaire, et je pense que c’est plus lisible, mais je n’ai pas encore testé les performances.

Créez votre propre conteneur:

 template  class statList : public std::list { public: statList() : std::list::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(); } }; 

Il y a des limites, mais cela fonctionne à merveille lorsque vous savez ce que vous faites.

// signifie déviation en c ++

/ Un écart qui est une différence entre une valeur observée et la valeur réelle d’une quantité d’intérêt (telle qu’une moyenne de population) est une erreur et un écart qui représente la différence entre la valeur observée et une estimation de la valeur réelle une estimation peut être une moyenne de l’échantillon) est un résidu. Ces concepts sont applicables aux données aux intervalles et aux niveaux de mesure. /

 #include  #include  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>num[i]; sum+=num[i]; } ave=sum/cnt; for(i=0;i 

}