Skip to content

Instantly share code, notes, and snippets.

@puterleat
Created January 23, 2012 22:41
Show Gist options
  • Save puterleat/1665911 to your computer and use it in GitHub Desktop.
Save puterleat/1665911 to your computer and use it in GitHub Desktop.
from __future__ import division
import itertools
from scipy import stats
import numpy as np
from collections import Counter
# Define some functions to use later
def form_lineup(delta, foils, felons):
foils = [i for i in stats.norm.rvs(loc=0, scale=1, size=foils)]
if felons > 0:
felons = [i for i in stats.norm.rvs(loc=delta, scale=1, size=felons)]
else:
felons = []
return foils, felons
def worst_is_a_felon(lineup):
foils, felons = lineup
if len(felons)==0:
return False
return bool(max(felons) > max(foils))
def punters_worst_first(lineup):
all = list(itertools.chain(*lineup))
all.sort()
all.reverse()
return all
def worst_meets_criterion(lineup, criterion):
all = punters_worst_first(lineup)
return bool(all[0] > criterion)
def exceeds_margin(lineup, margin):
all = punters_worst_first(lineup)
return bool(all[0] - all[1] > margin)
def beats_average_by(lineup, margin):
all = punters_worst_first(lineup)
worst = all[0]
rest = all[1:]
av_rest = np.average(rest)
return bool(worst - av_rest > margin)
def categorise_lineup(lineup, criterion, win_function, margin):
a = worst_meets_criterion(lineup, criterion) and win_function(lineup, margin)
b = worst_is_a_felon(lineup)
if a and b:
return 'hit'
if a:
return 'false_alarm'
# DEFINE SOME PARAMETERS
criterion = 1.5
delta = 3
nfelons = 1
nfoils = 5
reps = 1000
prob_felon = .5
prob_no_felon = 1 - prob_felon
win_function = exceeds_margin # this might seem odd, but you choose the function to apply by assigning it to this variable
# GENERATE SOME LINEUPS
lineups_with_felons = [form_lineup(delta=delta, foils=nfoils, felons=nfelons) for i in range(0, int(reps * prob_felon))]
lineups_without = [form_lineup(delta=delta, foils=nfoils+nfelons, felons=0) for i in range(0, int(reps * prob_no_felon))]
lineups = list(itertools.chain(lineups_with_felons, lineups_without))
# SIMULATE AT DIFFERENT VALUES OF MARGIN
for margin in [x * 0.3 for x in range(0, 10)]:
c = Counter([categorise_lineup(i, criterion, win_function, margin) for i in lineups])
n = len(lineups)
phit = c['hit']/n
pfa = c['false_alarm']/n
dprime=stats.norm.ppf(phit) - stats.norm.ppf(pfa) # norm.ppf is NORMSINV in excel
print "margin: %g \t phit: %g \t pfa: %g \t dprime: %g" % (margin, phit, pfa, dprime)
# outputs:
# margin: 0 phit: 0.463 pfa: 0.181 dprime: 0.818682
# margin: 0.3 phit: 0.455 pfa: 0.157 dprime: 0.893826
# margin: 0.6 phit: 0.438 pfa: 0.123 dprime: 1.00408
# margin: 0.9 phit: 0.412 pfa: 0.078 dprime: 1.19625
# margin: 1.2 phit: 0.369 pfa: 0.045 dprime: 1.36089
# margin: 1.5 phit: 0.322 pfa: 0.023 dprime: 1.53328
# margin: 1.8 phit: 0.27 pfa: 0.015 dprime: 1.55728
# margin: 2.1 phit: 0.215 pfa: 0.007 dprime: 1.66807
# margin: 2.4 phit: 0.17 pfa: 0.003 dprime: 1.79362
# margin: 2.7 phit: 0.126 pfa: 0.002 dprime: 1.73266
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment