Écart type d'une liste


103

Je veux trouver la moyenne et l'écart type des 1er, 2ème, ... chiffres de plusieurs listes (Z). Par exemple, j'ai

A_rank=[0.8,0.4,1.2,3.7,2.6,5.8]
B_rank=[0.1,2.8,3.7,2.6,5,3.4]
C_Rank=[1.2,3.4,0.5,0.1,2.5,6.1]
# etc (up to Z_rank )...

Maintenant , je veux prendre la moyenne et std de *_Rank[0]la moyenne et de std *_Rank[1], etc.
(ex: moyenne et std du 1er chiffre de tous les (A..Z) listes _rank,
la moyenne et std du 2ème chiffre de toutes les listes (A..Z) _rank;
la moyenne et la norme du 3ème chiffre ...; etc).


13
Bonjour, viral. Stack Overflow fonctionne mieux comme site de questions et réponses . Vous posez une question et tout le monde fournit des réponses. Votre message ne contient que des déclarations, pas de questions. Vous avez une question de programmation spécifique? Pour le dire autrement, qu'avez-vous essayé jusqu'à présent et où êtes-vous coincé?
Robᵩ

2
Pourquoi ces listes ne sont-elles pas dans un dictionnaire ou quelque chose du genre?
Waleed Khan

Désolé si je n'ai pas transmis la question correctement. Je veux prendre la moyenne de A_rank [0] (0.8), B_rank [0] (0.1), C_rank [0] (1.2), ... Z_rank [0]. idem pour A_rank [1] (0.4), B_rank [1] (2.8), C_rank [1] (3.4), ... Z_rank [1].
physics_for_all

Réponses:


150

Depuis Python 3.4 / PEP450, il existe un statistics moduledans la bibliothèque standard, qui a une méthodestdev pour calculer l'écart type des itérables comme le vôtre:

>>> A_rank = [0.8, 0.4, 1.2, 3.7, 2.6, 5.8]
>>> import statistics
>>> statistics.stdev(A_rank)
2.0634114147853952

38
Il convient de souligner que cela pstddevdevrait probablement être utilisé à la place si votre liste représente la population entière (c'est-à-dire que la liste n'est pas un échantillon d'une population). stddevest calculé à l'aide de la variance de l'échantillon et surestimera la moyenne de la population.
Alex Riley

4
Les fonctions sont en fait appelés stdevet pstdev, ne pas utiliser stdpour standardcomme on pouvait s'y attendre. Je n'ai pas pu modifier le message car les modifications doivent modifier au moins 6 caractères ...
mknaf

104

Je mettrais A_Ranket al dans un tableau NumPy 2D , puis utiliserais numpy.mean()et numpy.std()pour calculer les moyennes et les écarts types:

In [17]: import numpy

In [18]: arr = numpy.array([A_rank, B_rank, C_rank])

In [20]: numpy.mean(arr, axis=0)
Out[20]: 
array([ 0.7       ,  2.2       ,  1.8       ,  2.13333333,  3.36666667,
        5.1       ])

In [21]: numpy.std(arr, axis=0)
Out[21]: 
array([ 0.45460606,  1.29614814,  1.37355985,  1.50628314,  1.15566239,
        1.2083046 ])

2
le résultat de numpy.std n'est pas correct. Compte tenu de ces valeurs: 20,31,50,69,80 et mis dans Excel en utilisant STDEV.S (A1: A5), le résultat est 25,109 PAS 22,45.
Jim Clermonts

22
@JimClermonts Cela n'a rien à voir avec l'exactitude. Que ddof = 0 (par défaut, interpréter les données comme population) ou ddof = 1 (interpréter comme des échantillons, c'est-à-dire estimer la vraie variance) dépend de ce que vous faites.
runDOSrun

17
Pour clarifier davantage le point de @ runDOSrun, la fonction Excel STDEV.P()et la fonction Numpy std(ddof=0)calculent la population sd, ou l' échantillon non corrigé sd, tandis que la fonction Excel STDEV.S()et la fonction Numpy std(ddof=1)calculent l' échantillon (corrigé) sd, qui équivaut à sqrt (N / (N-1) ) fois la population sd, où N est le nombre de points. Voir plus: en.m.wikipedia.org/wiki/…
binaryfunt

52

Voici du code pur Python que vous pouvez utiliser pour calculer la moyenne et l'écart type.

Tout le code ci-dessous est basé sur le statisticsmodule en Python 3.4+.

def mean(data):
    """Return the sample arithmetic mean of data."""
    n = len(data)
    if n < 1:
        raise ValueError('mean requires at least one data point')
    return sum(data)/n # in Python 2 use sum(data)/float(n)

def _ss(data):
    """Return sum of square deviations of sequence data."""
    c = mean(data)
    ss = sum((x-c)**2 for x in data)
    return ss

def stddev(data, ddof=0):
    """Calculates the population standard deviation
    by default; specify ddof=1 to compute the sample
    standard deviation."""
    n = len(data)
    if n < 2:
        raise ValueError('variance requires at least two data points')
    ss = _ss(data)
    pvar = ss/(n-ddof)
    return pvar**0.5

Remarque: pour une précision améliorée lors de la sommation des flottants, le statisticsmodule utilise une fonction personnalisée _sumplutôt que celle intégrée sumque j'ai utilisée à sa place.

Maintenant, nous avons par exemple:

>>> mean([1, 2, 3])
2.0
>>> stddev([1, 2, 3]) # population standard deviation
0.816496580927726
>>> stddev([1, 2, 3], ddof=1) # sample standard deviation
0.1

1
Cela ne devrait-il pas être le cas pvar=ss/(n-1)?
Ranjith Ramachandra

2
@Ranjith: si vous souhaitez calculer la variance de l' échantillon (ou échantillon SD), vous pouvez utiliser n-1. Le code ci-dessus est pour la population SD (il y a donc des ndegrés de liberté).
Alex Riley

Bonjour Alex, pourriez-vous s'il vous plaît publier une fonction pour calculer l'écart type de l'échantillon? Je suis limité avec Python2.6, donc je dois relayer cette fonction.
Venu S

@VenuS: Bonjour, j'ai édité la stddevfonction afin qu'elle puisse calculer les écarts types de l'échantillon et de la population.
Alex Riley

22

Dans Python 2.7.1, vous pouvez calculer l'écart type en utilisant numpy.std()pour:

  • Population std : Utilisez simplement numpy.std()sans argument supplémentaire en plus de votre liste de données.
  • Exemple de std : vous devez passer ddof (c'est-à-dire Delta Degrees of Freedom) défini sur 1, comme dans l'exemple suivant:

numpy.std (<votre-liste>, ddof = 1 )

Le diviseur utilisé dans les calculs est N - ddof , où N représente le nombre d'éléments. Par défaut, ddof est égal à zéro.

Il calcule l'échantillon std plutôt que population std.



8

En utilisant python, voici quelques méthodes:

import statistics as st

n = int(input())
data = list(map(int, input().split()))

Approach1 - utilisation d'une fonction

stdev = st.pstdev(data)

Approche2: calculer la variance et en prendre la racine carrée

variance = st.pvariance(data)
devia = math.sqrt(variance)

Approche 3: utiliser les mathématiques de base

mean = sum(data)/n
variance = sum([((x - mean) ** 2) for x in X]) / n
stddev = variance ** 0.5

print("{0:0.1f}".format(stddev))

Remarque:

  • variance calcule la variance de l'échantillon de population
  • pvariance calcule la variance de la population entière
  • différences similaires entre stdevetpstdev

5

code python pur:

from math import sqrt

def stddev(lst):
    mean = float(sum(lst)) / len(lst)
    return sqrt(float(reduce(lambda x, y: x + y, map(lambda x: (x - mean) ** 2, lst))) / len(lst))

10
Il n'y a rien de «pur» dans ce 1-liner. Beurk. Voici une version plus pythonique:sqrt(sum((x - mean)**2 for x in lst) / len(lst))
DBrowne

3

Les autres réponses couvrent suffisamment comment faire du développement std en python, mais personne n'explique comment faire la traversée bizarre que vous avez décrite.

Je vais supposer que AZ est la population entière. Sinon, voyez la réponse d' Ome sur la façon de déduire à partir d'un échantillon.

Donc, pour obtenir l'écart type / la moyenne du premier chiffre de chaque liste, vous auriez besoin de quelque chose comme ceci:

#standard deviation
numpy.std([A_rank[0], B_rank[0], C_rank[0], ..., Z_rank[0]])

#mean
numpy.mean([A_rank[0], B_rank[0], C_rank[0], ..., Z_rank[0]])

Pour raccourcir le code et le généraliser à n'importe quel nième chiffre, utilisez la fonction suivante que j'ai générée pour vous:

def getAllNthRanks(n):
    return [A_rank[n], B_rank[n], C_rank[n], D_rank[n], E_rank[n], F_rank[n], G_rank[n], H_rank[n], I_rank[n], J_rank[n], K_rank[n], L_rank[n], M_rank[n], N_rank[n], O_rank[n], P_rank[n], Q_rank[n], R_rank[n], S_rank[n], T_rank[n], U_rank[n], V_rank[n], W_rank[n], X_rank[n], Y_rank[n], Z_rank[n]] 

Maintenant, vous pouvez simplement obtenir le stdd et la moyenne de tous les nièmes endroits de A à Z comme ceci:

#standard deviation
numpy.std(getAllNthRanks(n))

#mean
numpy.mean(getAllNthRanks(n))

Pour toute personne intéressée, j'ai généré la fonction en utilisant ce one-liner désordonné:str([chr(x)+'_rank[n]' for x in range(65,65+26)]).replace("'", "")
Samy Bencherif
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.