# Date 1222976988 25200
# Branch trunk
# Node ID e87acb829208e66d1ea498c438f85815ea3cbd8d
# Parent b7821cb46c6262838adf8c0b0547d00b512375f9
# Parent fc819b27a2fa6c2d2260ece2a45f25f47055cf9e
Population standard deviation contributed by Lorenzo Catucci.
diff git a/CHANGELOG b/CHANGELOG
 a/CHANGELOG
+++ b/CHANGELOG
@@ 15,13 +15,9 @@
 Options tuple contains Option objects for select/checkbox/radio groups.
select() now uses this automatically.
 checkbox() and radio() now have a ``label`` argument.
* webhelpers.html.form_layout:
  THIS MODULE IS EXPERIMENTAL AND SUBJECT TO CHANGE OR DELETION. If you
 want to use it in an application, please copy it to the application.
 Also see the module docstring for known problems.
  field() provides a simple based layout for a form widget with its
 label, requiredness, and optional hint and error message.
  form_legend() returns a message about required fields.
+* webhelpers.number:
+  Population standard deviation contributed by Lorenzo Catucci.
+* webhelpers.html.form_layout: form field layout (PRELIMINARY, UNSTABLE).
0.6.1 (7/31/2008)
* Include a faster version of cgi.escape for use by the literal object.
diff git a/webhelpers/number.py b/webhelpers/number.py
 a/webhelpers/number.py
+++ b/webhelpers/number.py
@@ 77,9 +77,10 @@
high = s[center+1]
return mean([low, high])
def standard_deviation(r):
+def standard_deviation(r, sample=True):
"""Standard deviation, `from the Python Cookbook
`_
+ Population mode contributed by Lorenzo Catucci.
Standard deviation shows the variability within a sequence of numbers.
A small standard deviation shows the numbers are close to the same. A
@@ 88,6 +89,13 @@
used to detect whether the average has been skewed by a few extremely high
or extremely low values.
+ By default the helper computes the unbiased estimate
+ for the population standard deviation, by applying an unbiasing
+ factor of sqrt(N/(N1)).
+
+ If you'd rather have the function compute the population standard
+ deviation, pass ``sample=False``.
+
The following examples are taken from Wikipedia.
http://en.wikipedia.org/wiki/Standard_deviation
@@ 97,9 +105,16 @@
5.773502691896258...
>>> standard_deviation([6, 6, 8, 8])
1.1547005383792515
+ >>> standard_deviation([0, 0, 14, 14], sample=False)
+ 7.0
+ >>> standard_deviation([0, 6, 8, 14], sample=False)
+ 5.0
+ >>> standard_deviation([6, 6, 8, 8], sample=False)
+ 1.0
 (Wikipedia reports 7, 5, and 1 respectively. Some of the difference is
 due to rounding, but the rest may be a bug?)
+ (The results reported in Wikipedia are those expected for whole
+ population statistics and therefore are equal to the ones we get
+ by setting ``sample=False`` in the later tests.)
.. codeblock:: pycon
@@ 107,11 +122,15 @@
# Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
>>> standard_deviation([70, 70, 70, 75, 80, 85, 90, 95, 90, 80, 75, 70]) # doctest: +ELLIPSIS
9.003366373785...
+ >>> standard_deviation([70, 70, 70, 75, 80, 85, 90, 95, 90, 80, 75, 70], sample=False) # doctest: +ELLIPSIS
+ 8.620067027323...
 # Fictitious average mothly temperatures in Montana.
+ # Fictitious average monthly temperatures in Montana.
# Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
>>> standard_deviation([32, 10, 20, 30, 60, 90, 100, 80, 60, 30, 10, 32]) # doctest: +ELLIPSIS
45.1378360405574...
+ >>> standard_deviation([32, 10, 20, 30, 60, 90, 100, 80, 60, 30, 10, 32], sample=False) # doctest: +ELLIPSIS
+ 43.2161878106906...
Most natural and random phenomena follow the normal distribution (aka the
bell curve), which says that most values are close to average but a few are
@@ 124,18 +143,14 @@
and "A" (perfect) to the 0.25% higher than 2 stdevs. Those between 1 and 2
stdevs below get a "D" (poor), and those below 2 stdevs... we won't talk
about them.

 a large standard
 i.e., how far they deviate from the average.
 If all numbers are the same, the standard deviation is zero. If the
 numbers are widely different from average, no matter whether above or
 below, the standard deviation will be high. Most natural distributions
 follow the bell curve and have a standard deviation of 1.
"""
avg = average(r)
sdsq = sum([(i  avg) ** 2 for i in r])
 return (sdsq / (len(r)  1 or 1)) ** 0.5

+ if sample:
+ normal_denom=len(r)  1 or 1
+ else:
+ normal_denom=len(r)
+ return (sdsq / normal_denom) ** 0.5
class SimpleStats(object):
"""Calculate a few simple stats on data.