Skip to content

Instantly share code, notes, and snippets.

@alexalemi
Created March 21, 2012 19:29
Show Gist options
  • Save alexalemi/2151722 to your computer and use it in GitHub Desktop.
Save alexalemi/2151722 to your computer and use it in GitHub Desktop.
Python Welford Algorithm
import math
class Welford(object):
""" Implements Welford's algorithm for computing a running mean
and standard deviation as described at:
http://www.johndcook.com/standard_deviation.html
can take single values or iterables
Properties:
mean - returns the mean
std - returns the std
meanfull- returns the mean and std of the mean
Usage:
>>> foo = Welford()
>>> foo(range(100))
>>> foo
<Welford: 49.5 +- 29.0114919759>
>>> foo([1]*1000)
>>> foo
<Welford: 5.40909090909 +- 16.4437417146>
>>> foo.mean
5.409090909090906
>>> foo.std
16.44374171455467
>>> foo.meanfull
(5.409090909090906, 0.4957974674244838)
"""
def __init__(self,lst=None):
self.k = 0
self.M = 0
self.S = 0
self.__call__(lst)
def update(self,x):
if x is None:
return
self.k += 1
newM = self.M + (x - self.M)*1./self.k
newS = self.S + (x - self.M)*(x - newM)
self.M, self.S = newM, newS
def consume(self,lst):
lst = iter(lst)
for x in lst:
self.update(x)
def __call__(self,x):
if hasattr(x,"__iter__"):
self.consume(x)
else:
self.update(x)
@property
def mean(self):
return self.M
@property
def meanfull(self):
return self.mean, self.std/math.sqrt(self.k)
@property
def std(self):
if self.k==1:
return 0
return math.sqrt(self.S/(self.k-1))
def __repr__(self):
return "<Welford: {} +- {}>".format(self.mean, self.std)
Copy link

ghost commented Jul 16, 2012

Works great and saved me a bit of time, thanks :)

@hamx0r
Copy link

hamx0r commented Apr 12, 2016

Great gist! moving self.k += 1 until after newM and newS are calculated adds robustness for cases where someone tries to use this with strings or other non-numeric types....the function will then throw an error before incrementing k, thus preserving the accuracy of the data within their Welford instance.

@ugiacoman
Copy link

Beautiful! You'd be surprised at how many incorrect versions of Welford are online, thanks!

@gerardsimons
Copy link

gerardsimons commented Feb 27, 2020

Nice code! One minor thing: not sure if returning an std of 0 is appropriate in the case of k=1 though as this is confusing when k != 0 but std = 0?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment