Last active
December 24, 2015 11:19
-
-
Save hbuschme/6790387 to your computer and use it in GitHub Desktop.
Incrementally calculate sample mean, std, and var.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import division | |
import numbers | |
import numpy as np | |
class IncrementalMeanStd(object): | |
'''Incremental calculation of sample mean, std, and var. | |
Based on http://www.johndcook.com/standard_deviation.html | |
''' | |
def __init__(self): | |
super(IncrementalMeanStd, self).__init__() | |
self._mk = 0 # mean_k | |
self._mk1 = 0 # mean_{k-1} | |
self._sk = 0 # s_k | |
self._k = 0 # k | |
def _update_mean(self, x): | |
'''Update sample mean given new sample x.''' | |
if self._k == 1: | |
return x | |
else: | |
return self._mk + (x - self._mk) / self._k | |
def _update_var(self, x): | |
'''Update sample var given new sample x.''' | |
if self._k == 1: | |
if isinstance(x, (np.number, numbers.Number)): | |
return 0 | |
elif isinstance(x, np.ndarray): | |
return np.zeros_like(x) | |
else: | |
return self._sk + (x - self._mk1) * (x - self._mk) | |
def add(self, x): | |
'''Add a new sample and update calculation.''' | |
self._k += 1 | |
self._mk1 = self._mk | |
self._mk = self._update_mean(x) | |
self._sk = self._update_var(x) | |
@property | |
def mean(self): | |
'''Sample mean.''' | |
return self._mk | |
@property | |
def std(self): | |
'''Sample std.''' | |
return np.sqrt(self.var) | |
@property | |
def var(self): | |
'''Sample var.''' | |
return self._sk / self._k | |
if __name__ == '__main__': | |
# Test | |
ims = IncrementalMeanStd() | |
l = range(10) | |
for x in l: | |
ims.add(x) | |
print(ims.mean, ims.std, ims.var) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment