Ho bisogno di sapere se un numero rispetto ad un insieme di numeri è al di fuori del 1 stdDev dalla media, ecc ..Come si determina la deviazione standard (stddev) di un insieme di valori?
risposta
Mentre la somma dei quadrati algoritmo funziona bene la maggior parte del tempo, può causare grossi guai se si tratta di numeri molto grandi. Che, fondamentalmente, può finire con una variazione negativa ...
Inoltre, non mai, mai, mai, calcolare un^2 come pow (a, 2), a * a è quasi certamente più veloce.
Di gran lunga il miglior modo di calcolare una deviazione standard è Welford's method. Il mio C è molto arrugginito, ma potrebbe essere simile:
public static double StandardDeviation(List<double> valueList)
{
double M = 0.0;
double S = 0.0;
int k = 1;
foreach (double value in valueList)
{
double tmpM = M;
M += (value - tmpM)/k;
S += (value - tmpM) * (value - M);
k++;
}
return Math.Sqrt(S/(k-2));
}
Se si dispone di tutta la popolazione(in contrapposizione ad un campione di popolazione), quindi utilizzare return Math.Sqrt(S/(k-1));
.
EDIT: Ho aggiornato il codice in base alle osservazioni di Jason ...
EDIT: Ho anche aggiornato il codice in base alle osservazioni di Alex ...
+1: ho letto il commento di Knuth su questo, ma non ho mai saputo che si chiamava metodo di Welford. Per tua informazione puoi eliminare il caso k == 1, funziona e basta. –
OH: e stai dimenticando il divide per N o divide per N-1 alla fine. –
Ora guarda cosa hai fatto. Mi hai dato qualcosa di nuovo da imparare. Tu bestia. – dmckee
È possibile evitare di fare due passaggi sui dati accumulando la media e media-square
cnt = 0
mean = 0
meansqr = 0
loop over array
cnt++
mean += value
meansqr += value*value
mean /= cnt
meansqr /= cnt
e formando
sigma = sqrt(meansqr - mean^2)
Un fattore di cnt/(cnt-1)
è spesso opportuno pure.
BTW-- Il primo passaggio sui dati nelle risposte Demi e McWafflestix sono nascosti nelle chiamate a Average
. Questo tipo di cose è certamente banale in una piccola lista, ma se la lista supera la dimensione della cache, o anche il working set, questo diventa un affare.
La tua formula è sbagliata. Dovrebbe essere sigma = sqrt (meansqr - mean^2) Leggete attentamente questa pagina http://en.wikipedia.org/wiki/Standard_deviation per vedere il vostro errore. – leif
@leif: Sì. E avrei dovuto notare anche il problema dimensionale. – dmckee
-1: matematicamente corretto, ma numericamente questo è male. –
Codice frammento:
public static double StandardDeviation(List<double> valueList)
{
if (valueList.Count < 2) return 0.0;
double sumOfSquares = 0.0;
double average = valueList.Average(); //.NET 3.0
foreach (double value in valueList)
{
sumOfSquares += Math.Pow((value - average), 2);
}
return Math.Sqrt(sumOfSquares/(valueList.Count - 1));
}
Dividere per Conteggio - 1 o Conteggio dipende dal fatto che stiamo parlando di un'intera popolazione o di un campione, sì? Sembra che OP stia parlando di una popolazione conosciuta ma non del tutto chiara. –
Questo è corretto - questo è per la varianza campionaria. Apprezzo il momento saliente – Demi
Il tuo codice si arresta in modo anomalo per il caso legittimo di un elenco con un valore. – SPWorley
/// <summary>
/// Calculates standard deviation, same as MATLAB std(X,0) function
/// <seealso cref="http://www.mathworks.co.uk/help/techdoc/ref/std.html"/>
/// </summary>
/// <param name="values">enumumerable data</param>
/// <returns>Standard deviation</returns>
public static double GetStandardDeviation(this IEnumerable<double> values)
{
//validation
if (values == null)
throw new ArgumentNullException();
int lenght = values.Count();
//saves from devision by 0
if (lenght == 0 || lenght == 1)
return 0;
double sum = 0.0, sum2 = 0.0;
for (int i = 0; i < lenght; i++)
{
double item = values.ElementAt(i);
sum += item;
sum2 += item * item;
}
return Math.Sqrt((sum2 - sum * sum/lenght)/(lenght - 1));
}
Ho trovato che la risposta utile di Rob non corrispondeva esattamente a quello che stavo vedendo usando Excel. Per abbinare eccellere, ho passato la media per valueList nel calcolo di StandardDeviation.
Ecco i miei due centesimi ... e chiaramente è possibile calcolare la media mobile (ma) da valueList all'interno della funzione, ma mi è capitato di avere già prima di aver bisogno dello standardDeviation.
public double StandardDeviation(List<double> valueList, double ma)
{
double xMinusMovAvg = 0.0;
double Sigma = 0.0;
int k = valueList.Count;
foreach (double value in valueList){
xMinusMovAvg = value - ma;
Sigma = Sigma + (xMinusMovAvg * xMinusMovAvg);
}
return Math.Sqrt(Sigma/(k - 1));
}
La risposta accettata da Jaime è grande, tranne che è necessario dividere per k-2 nell'ultima riga (è necessario dividere per "number_of_elements-1"). Meglio ancora, avviare k a 0:
public static double StandardDeviation(List<double> valueList)
{
double M = 0.0;
double S = 0.0;
int k = 0;
foreach (double value in valueList)
{
k++;
double tmpM = M;
M += (value - tmpM)/k;
S += (value - tmpM) * (value - M);
}
return Math.Sqrt(S/(k-1));
}
Con i metodi di estensione.
using System;
using System.Collections.Generic;
namespace SampleApp
{
internal class Program
{
private static void Main()
{
List<double> data = new List<double> {1, 2, 3, 4, 5, 6};
double mean = data.Mean();
double variance = data.Variance();
double sd = data.StandardDeviation();
Console.WriteLine("Mean: {0}, Variance: {1}, SD: {2}", mean, variance, sd);
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
public static class MyListExtensions
{
public static double Mean(this List<double> values)
{
return values.Count == 0 ? 0 : values.Mean(0, values.Count);
}
public static double Mean(this List<double> values, int start, int end)
{
double s = 0;
for (int i = start; i < end; i++)
{
s += values[i];
}
return s/(end - start);
}
public static double Variance(this List<double> values)
{
return values.Variance(values.Mean(), 0, values.Count);
}
public static double Variance(this List<double> values, double mean)
{
return values.Variance(mean, 0, values.Count);
}
public static double Variance(this List<double> values, double mean, int start, int end)
{
double variance = 0;
for (int i = start; i < end; i++)
{
variance += Math.Pow((values[i] - mean), 2);
}
int n = end - start;
if (start > 0) n -= 1;
return variance/(n);
}
public static double StandardDeviation(this List<double> values)
{
return values.Count == 0 ? 0 : values.StandardDeviation(0, values.Count);
}
public static double StandardDeviation(this List<double> values, int start, int end)
{
double mean = values.Mean(start, end);
double variance = values.Variance(mean, start, end);
return Math.Sqrt(variance);
}
}
}
10 volte più veloce soluzione che Jaime di, ma essere consapevoli che, come Jaime rilevare:
"Mentre la somma dei dell'algoritmo piazze funziona bene la maggior parte del tempo, possono causare grossi guai se si tratta di molto grandi numeri. È fondamentalmente può finire con una variazione negativa"
Se pensate di avere a che fare con numeri molto grandi o una grande quantità di numeri, dovreste calcolare usando entrambi i metodi, se i risultati sono uguali, sapete per certo che potete usare il "mio" metodo per voi .
public static double StandardDeviation(double[] data)
{
double stdDev = 0;
double sumAll = 0;
double sumAllQ = 0;
//Sum of x and sum of x²
for (int i = 0; i < data.Length; i++)
{
double x = data[i];
sumAll += x;
sumAllQ += x * x;
}
//Mean (not used here)
//double mean = 0;
//mean = sumAll/(double)data.Length;
//Standard deviation
stdDev = System.Math.Sqrt(
(sumAllQ -
(sumAll * sumAll)/data.Length) *
(1.0d/(data.Length - 1))
);
return stdDev;
}
La libreria Math.NET prevede questo per voi a della scatola.
PM> Installa-Package MathNet.Numerics
var populationStdDev = new List<double>(1d, 2d, 3d, 4d, 5d).PopulationStandardDeviation();
var sampleStdDev = new List<double>(2d, 3d, 4d).StandardDeviation();
Vedere http://numerics.mathdotnet.com/docs/DescriptiveStatistics.html per ulteriori informazioni.
Il problema con tutte le altre risposte è che presuppongono che i tuoi dati sono in un grande array. Se i tuoi dati arrivano al volo, questo sarebbe un approccio migliore. Questa classe funziona indipendentemente da come o se si memorizzano i dati. Ti dà anche la possibilità di scegliere il metodo Waldorf o il metodo della somma dei quadrati. Entrambi i metodi funzionano con un singolo passaggio.
public final class StatMeasure {
private StatMeasure() {}
public interface Stats1D {
/** Add a value to the population */
void addValue(double value);
/** Get the mean of all the added values */
double getMean();
/** Get the standard deviation from a sample of the population. */
double getStDevSample();
/** Gets the standard deviation for the entire population. */
double getStDevPopulation();
}
private static class WaldorfPopulation implements Stats1D {
private double mean = 0.0;
private double sSum = 0.0;
private int count = 0;
@Override
public void addValue(double value) {
double tmpMean = mean;
double delta = value - tmpMean;
mean += delta/++count;
sSum += delta * (value - mean);
}
@Override
public double getMean() { return mean; }
@Override
public double getStDevSample() { return Math.sqrt(sSum/(count - 1)); }
@Override
public double getStDevPopulation() { return Math.sqrt(sSum/(count)); }
}
private static class StandardPopulation implements Stats1D {
private double sum = 0.0;
private double sumOfSquares = 0.0;
private int count = 0;
@Override
public void addValue(double value) {
sum += value;
sumOfSquares += value * value;
count++;
}
@Override
public double getMean() { return sum/count; }
@Override
public double getStDevSample() {
return (float) Math.sqrt((sumOfSquares - ((sum * sum)/count))/(count - 1));
}
@Override
public double getStDevPopulation() {
return (float) Math.sqrt((sumOfSquares - ((sum * sum)/count))/count);
}
}
/**
* Returns a way to measure a population of data using Waldorf's method.
* This method is better if your population or values are so large that
* the sum of x-squared may overflow. It's also probably faster if you
* need to recalculate the mean and standard deviation continuously,
* for example, if you are continually updating a graphic of the data as
* it flows in.
*
* @return A Stats1D object that uses Waldorf's method.
*/
public static Stats1D getWaldorfStats() { return new WaldorfPopulation(); }
/**
* Return a way to measure the population of data using the sum-of-squares
* method. This is probably faster than Waldorf's method, but runs the
* risk of data overflow.
*
* @return A Stats1D object that uses the sum-of-squares method
*/
public static Stats1D getSumOfSquaresStats() { return new StandardPopulation(); }
}
- 1. Come si calcola la deviazione standard tra le misure ponderate?
- 2. Calcolo della deviazione standard degli angoli?
- 3. Java Stream - Deviazione standard
- 4. Deviazione standard per DF, panda
- 5. Deviazione standard dell'elenco generico?
- 6. Deviazione standard in NumPy
- 7. Consumo di memoria della funzione NumPy per la deviazione standard
- 8. Deviazione standard della colonna R
- 9. Come posso calcolare la mediana e la deviazione standard di un flusso di numeri in Perl?
- 10. Ordinamento un insieme di valori
- 11. Obj-C: calcola la deviazione standard di un NSArray di oggetti NSNumber?
- 12. deviazione standard rapida con i pesi
- 13. Come si determina la lunghezza di un Fixnum in Ruby?
- 14. Come si determina la lunghezza di un carattere senza segno *?
- 15. Calcolo della media ponderata e deviazione standard
- 16. Calcola la deviazione standard dei dati raggruppati in Spark DataFrame
- 17. Come calcolare in modo efficiente una deviazione standard in movimento
- 18. Aggiungi barre di errore per mostrare la deviazione standard su un terreno in R
- 19. Valutazione della deviazione assoluta media di un insieme di numeri in Oracle
- 20. Adattamento di una distribuzione bimodale a un insieme di valori
- 21. Can Random.nextgaussian() può campionare valori da una distribuzione con media diversa e deviazione standard?
- 22. Come si determina la variante di colore più scuro o più chiaro di un determinato colore?
- 23. Deviazione di chiamata Twilio
- 24. Come omettere i valori NA mentre si incollano insieme numerosi valori di colonna?
- 25. Deviazione di chiamata
- 26. Calcolo efficiente della deviazione standard cumulativa della matrice in
- 27. Determina la rotazione di un CALayer
- 28. Come si determina l'autore di un pacchetto R?
- 29. PHP: come si determina ogni ennesima iterazione di un ciclo?
- 30. Statistiche semplici - Pacchetti Java per calcolare media, deviazione standard, ecc.
Questo sembra mancare il tag compiti a casa .... – overslacked
prego prego soddisfa prego non date per scontato l'OP è una domanda a scopo di compiti a casa, piuttosto che per un progetto "reale" o di auto-miglioramento . Chiediglielo. –
in realtà non sto chiedendo i compiti a casa, ma se aiuta le persone che stanno facendo i compiti a trovare la risposta, per favore aggiungi il tag –