binomconf
Calculating Binomial Confidence Intervals in Python
Gives exact, optimal confidence intervals
from __future__ import division import math import random # only used for n=0 case from scipy import special def find_root(y_over_dy, start, steps=10, bounds=(None, None)): guess = start for i in xrange(steps): prev, guess = guess, guess - y_over_dy(guess) if bounds[0] is not None and guess < bounds[0]: guess = bounds[0] if bounds[1] is not None and guess > bounds[1]: guess = bounds[1] if guess == prev: break return guess def binomial_conf_interval(x, n, conf=0.95): assert 0 <= x <= n and 0 <= conf < 1 if n == 0: left = random.random()*(1 - conf) return left, left + conf bl = float(special.betaln(x+1, n-x+1)) def f(left_a): left = max(1e-8, float(special.betaincinv(x+1, n-x+1, left_a))) right = min(1-1e-8, float(special.betaincinv(x+1, n-x+1, left_a + conf))) top = math.exp( math.log(right)*(x+1) + math.log(1-right)*(n-x+1) + math.log(left) + math.log(1-left) - bl ) - math.exp( math.log(left)*(x+1) + math.log(1-left)*(n-x+1) + math.log(right) + math.log(1-right) - bl ) bottom = (x - n*right)*left*(1-left) - (x - n*left)*right*(1-right) return top/bottom left_a = find_root(f, (1-conf)/2, bounds=(0, 1-conf)) return ( float(special.betaincinv(x+1, n-x+1, left_a)), float(special.betaincinv(x+1, n-x+1, left_a + conf)), ) minmax = lambda x: (min(x), max(x)) def format_binomial_conf(x, n, conf=0.95, f=lambda x: x): if n == 0: return '???' left, right = minmax(map(f, binomial_conf_interval(x, n, conf))) return '~%.1f%% (%.f-%.f%%)' % (100*f(x/n), math.floor(100*left), math.ceil(100*right)) print "(95% confidence level)" print for x, n in [(1, 2), (0, 10), (3, 4), (1000, 1000), (0, 0)]: print "x =", x, "n =", n print binomial_conf_interval(x, n) print format_binomial_conf(x, n) printOutput:
(95% confidence level) x = 1 n = 2 (0.09429932405024612, 0.9057006759497539) ~50.0% (9-91%) x = 0 n = 10 (0.0, 0.23840419038085267) ~0.0% (0-24%) x = 3 n = 4 (0.3298504422802088, 0.9739692154994636) ~75.0% (32-98%) x = 1000 n = 1000 (0.9970117342468727, 1.0) ~100.0% (99-100%) x = 0 n = 0 (0.001202340017706206, 0.9512023400177062) ???