├── .gitignore ├── README.md ├── book ├── Makefile ├── back.png ├── book.tex ├── custom.css ├── figs │ ├── dungeons1.eps │ ├── dungeons1.pdf │ ├── dungeons2.eps │ ├── dungeons2.pdf │ ├── dungeons3.eps │ ├── dungeons3.pdf │ ├── euro1.eps │ ├── euro1.pdf │ ├── euro2.eps │ ├── euro2.pdf │ ├── euro3.eps │ ├── euro3.pdf │ ├── hockey0.eps │ ├── hockey0.pdf │ ├── hockey1.eps │ ├── hockey1.pdf │ ├── hockey2.eps │ ├── hockey2.pdf │ ├── hockey3.eps │ ├── hockey3.pdf │ ├── jaynes1.eps │ ├── jaynes1.pdf │ ├── jaynes2.eps │ ├── jaynes2.pdf │ ├── kidney1.eps │ ├── kidney1.pdf │ ├── kidney2.eps │ ├── kidney2.pdf │ ├── kidney3.eps │ ├── kidney3.pdf │ ├── kidney4.eps │ ├── kidney4.pdf │ ├── kidney5.eps │ ├── kidney5.pdf │ ├── kidney6.eps │ ├── kidney6.pdf │ ├── kidney7.eps │ ├── kidney7.pdf │ ├── kidney8.eps │ ├── kidney8.pdf │ ├── paintball.eps │ ├── paintball.pdf │ ├── paintball1.eps │ ├── paintball1.pdf │ ├── paintball2.eps │ ├── paintball2.pdf │ ├── paintball3.eps │ ├── paintball3.pdf │ ├── paintball4.eps │ ├── paintball4.pdf │ ├── paintball5.eps │ ├── paintball5.pdf │ ├── price1.eps │ ├── price1.pdf │ ├── price2.eps │ ├── price2.pdf │ ├── price3.eps │ ├── price3.pdf │ ├── price4.eps │ ├── price4.pdf │ ├── price5.eps │ ├── price5.pdf │ ├── price6.eps │ ├── price6.pdf │ ├── redline0.eps │ ├── redline0.pdf │ ├── redline1.eps │ ├── redline1.pdf │ ├── redline2.eps │ ├── redline2.pdf │ ├── redline3.eps │ ├── redline3.pdf │ ├── redline4.eps │ ├── redline4.pdf │ ├── redline5.eps │ ├── redline5.pdf │ ├── sat_calibrate.eps │ ├── sat_calibrate.pdf │ ├── sat_join.eps │ ├── sat_join.pdf │ ├── sat_joint.eps │ ├── sat_joint.pdf │ ├── sat_normal.eps │ ├── sat_normal.pdf │ ├── sat_posteriors.eps │ ├── sat_posteriors.pdf │ ├── sat_posteriors2.eps │ ├── sat_posteriors2.pdf │ ├── sat_posteriors_eff.eps │ ├── sat_posteriors_eff.pdf │ ├── sat_posteriors_p_corr.eps │ ├── sat_posteriors_p_corr.pdf │ ├── sat_prior.eps │ ├── sat_prior.pdf │ ├── sat_prior2.eps │ ├── sat_prior2.pdf │ ├── species-cdf-B1558.G.eps │ ├── species-cdf-B1558.G.pdf │ ├── species-cond-B1242.eps │ ├── species-cond-B1242.pdf │ ├── species-cond-B1246.eps │ ├── species-cond-B1246.pdf │ ├── species-frac-B1242.eps │ ├── species-frac-B1242.pdf │ ├── species-frac-B1246.eps │ ├── species-frac-B1246.pdf │ ├── species-l-cal.eps │ ├── species-l-cal.pdf │ ├── species-l-val.eps │ ├── species-l-val.pdf │ ├── species-l.eps │ ├── species-l.pdf │ ├── species-madd.eps │ ├── species-madd.pdf │ ├── species-n-cal.eps │ ├── species-n-cal.pdf │ ├── species-n.eps │ ├── species-n.pdf │ ├── species-ndist-B1242.eps │ ├── species-ndist-B1242.pdf │ ├── species-ndist-B1246.eps │ ├── species-ndist-B1246.pdf │ ├── species-prev-B1242.eps │ ├── species-prev-B1242.pdf │ ├── species-prev-B1246.eps │ ├── species-prev-B1246.pdf │ ├── species-q-cal.eps │ ├── species-q-cal.pdf │ ├── species-q-val.eps │ ├── species-q-val.pdf │ ├── species-q.eps │ ├── species-q.pdf │ ├── species-rare-B1242.eps │ ├── species-rare-B1242.pdf │ ├── species-rare-B1246.eps │ ├── species-rare-B1246.pdf │ ├── species.cond.B1242.eps │ ├── species.cond.B1242.pdf │ ├── species.frac.B1242.eps │ ├── species.frac.B1242.pdf │ ├── species.frac.eps │ ├── species.frac.pdf │ ├── species.ndist.B1242.eps │ ├── species.ndist.B1242.pdf │ ├── species.prev.B1242.eps │ ├── species.prev.B1242.pdf │ ├── species.rare.B1242.eps │ ├── species.rare.B1242.pdf │ ├── species.rare.eps │ ├── species.rare.pdf │ ├── species1.eps │ ├── species1.pdf │ ├── species2.eps │ ├── species2.pdf │ ├── species4.eps │ ├── species4.pdf │ ├── species5-cal.eps │ ├── species5-cal.pdf │ ├── species5-val.eps │ ├── species5-val.pdf │ ├── species5.eps │ ├── species5.pdf │ ├── species6.eps │ ├── species6.pdf │ ├── train1.eps │ ├── train1.pdf │ ├── train2.eps │ ├── train2.pdf │ ├── train3.eps │ ├── train3.pdf │ ├── train4.eps │ ├── train4.pdf │ ├── variability_cv.eps │ ├── variability_cv.pdf │ ├── variability_posterior_female.eps │ ├── variability_posterior_female.pdf │ ├── variability_posterior_male.eps │ └── variability_posterior_male.pdf ├── footer.html ├── header.html ├── hevea.sty ├── htmlonly ├── kidney_table.tex ├── kidney_table2.tex ├── latexonly ├── localdef.py ├── macros.hva ├── next.png └── up.png └── code ├── CDBRFS08.ASC.gz ├── brfss.py ├── columns.py ├── cookie.py ├── cookie2.py ├── correlation.py ├── dice.py ├── dungeons.py ├── euro.py ├── euro2.py ├── euro3.py ├── hockey.py ├── hockey_data.csv ├── jaynes.py ├── journal.pone.0047712.s001.csv ├── kidney.py ├── m_and_m.py ├── monty.py ├── monty2.py ├── myplot.py ├── paintball.py ├── price.py ├── redline.py ├── redline_data.py ├── sat.py ├── sat_ranks.csv ├── sat_scale.csv ├── showcases.2011.csv ├── showcases.2012.csv ├── species.py ├── survey.py ├── thinkbayes.py ├── thinkplot.py ├── thinkstats.py ├── train.py ├── train2.py ├── train3.py └── variability.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | 21 | # Installer logs 22 | pip-log.txt 23 | 24 | # Unit test / coverage reports 25 | .coverage 26 | .tox 27 | nosetests.xml 28 | 29 | # Translations 30 | *.mo 31 | 32 | # Mr Developer 33 | .mr.developer.cfg 34 | .project 35 | .pydevproject 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ThinkBayes 2 | ========== 3 | 4 | Code repository for Think Bayes: Bayesian Statistics Made Simple 5 | by Allen B. Downey 6 | 7 | Available from Green Tea Press at http://thinkbayes.com. 8 | 9 | Published by O'Reilly Media, October 2013. 10 | 11 | -------------------------------------------------------------------------------- /book/Makefile: -------------------------------------------------------------------------------- 1 | PDFFLAGS = -dCompatibilityLevel=1.4 -dPDFSETTINGS=/prepress \ 2 | -dCompressPages=true -dUseFlateCompression=true \ 3 | -dEmbedAllFonts=true -dSubsetFonts=true -dMaxSubsetPct=100 4 | 5 | 6 | all: book.tex 7 | pdflatex book 8 | makeindex book.idx 9 | pdflatex book 10 | mv book.pdf thinkbayes.pdf 11 | evince thinkbayes.pdf 12 | 13 | HEVEABUILDLOG=build.log 14 | 15 | hevea: 16 | sed 's/\(figs\/[^.]*\).\(pdf\|png\)/\1.eps/' book.tex > thinkbayes.tex 17 | rm -rf html 18 | mkdir html 19 | hevea macros.hva -O -e latexonly htmlonly thinkbayes 2>&1 | tee ${HEVEABUILDLOG} 20 | # the following greps are a kludge to prevent imagen from seeing 21 | # the definitions in latexonly, and to avoid headers on the images 22 | grep -v latexonly thinkbayes.image.tex > a; mv a thinkbayes.image.tex 23 | sed s/\\\\usepackage{fancyhdr}// < thinkbayes.image.tex > a; mv a thinkbayes.image.tex 24 | imagen -png thinkbayes 25 | hacha thinkbayes.html 26 | cp up.png next.png back.png html 27 | cp custom.css thinkbayes.css 28 | mv index.html thinkbayes.css thinkbayes*.html thinkbayes*.png *motif.gif html 29 | 30 | DEST = /home/downey/public_html/greent/thinkbayes 31 | 32 | distrib: 33 | rm -rf dist 34 | mkdir dist 35 | rsync -a thinkbayes.pdf html dist 36 | rsync -a dist/* $(DEST) 37 | chmod -R o+r $(DEST)/* 38 | cd $(DEST)/..; sh back 39 | 40 | plastex: 41 | # Before running plastex, we need the current directory in PYTHONPATH 42 | # export PYTHONPATH=$PYTHONPATH:. 43 | rm -rf /home/downey/thinkbayes/trunk/book/.svn 44 | plastex --renderer=DocBook --theme=book --image-resolution=300 --filename=book.xml book.tex 45 | rm -rf /home/downey/thinkbayes/trunk/book/.svn 46 | 47 | xxe: 48 | xmlcopyeditor ~/ThinkBayes/book/book/book.xml & 49 | 50 | lint: 51 | xmllint -noout book/book.xml 52 | 53 | OREILLY = atlas 54 | 55 | oreilly: 56 | rsync -a book/ $(OREILLY) 57 | rsync -a figs/* $(OREILLY)/figs/ 58 | cd $(OREILLY); git add . 59 | cd $(OREILLY); git commit -m "Automated check in." 60 | cd $(OREILLY); git push 61 | 62 | clean: 63 | rm -f *~ *.aux *.log *.dvi *.idx *.ilg *.ind *.toc 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /book/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/back.png -------------------------------------------------------------------------------- /book/custom.css: -------------------------------------------------------------------------------- 1 | 2 | div#main { 3 | display: grid; 4 | grid-template-columns: 1fr; 5 | grid-auto-rows: minmax(100px, auto); 6 | grid-gap: 10px; 7 | gap: 10px; 8 | } 9 | div#colorbar { 10 | display: none; 11 | /* background: #DC143C; */ 12 | } 13 | div#content { 14 | min-width: 0; 15 | padding: 10px; 16 | } 17 | div#content p:first-of-type { 18 | margin-top: 0; 19 | } 20 | h1, h2, h3, h4, h5, h6 { 21 | margin-bottom: 0; 22 | } 23 | h1 span, h2 span, h3 span, h4 span, h5 span, h6 span { 24 | display: block; 25 | } 26 | 27 | img { 28 | max-width: 100% 29 | } 30 | pre.verbatim { 31 | overflow-x: auto; 32 | max-width: 100%; 33 | } 34 | 35 | /* navarrow links */ 36 | img.navarrow { 37 | padding: 0 5px; 38 | text-decoration: none; 39 | color: #DC143C; 40 | } 41 | 42 | body > a, body > a:link { 43 | color: #DC143C; 44 | } 45 | body > a:hover { 46 | text-decoration: underline; 47 | } 48 | 49 | body div#content a, body div#sidebar a { 50 | text-decoration: underline; 51 | } 52 | 53 | img.prevarrow:after { 54 | content: " 🡄" 55 | } 56 | img.uparrow:after { 57 | content: " 🡅" 58 | } 59 | img.nextarrow:after { 60 | content: " 🡆" 61 | } 62 | /* end navarrow links */ 63 | 64 | div.notice { 65 | background-color: #f0f0f0; 66 | padding: 8px; 67 | border: 1px solid #d0d0d0; 68 | margin-bottom: 12px; 69 | } 70 | 71 | @media (max-width: 800px) { 72 | body > hr:first-of-type { 73 | color: #DC143C; 74 | background-color: #DC143C; 75 | height: 12px; 76 | margin-bottom: 0px; 77 | border: 0; 78 | } 79 | div#content { 80 | padding: 10px 2px; 81 | } 82 | } 83 | 84 | @media (min-width: 800px) { 85 | hr { border: 0; } 86 | div#colorbar { 87 | display: block; 88 | } 89 | div#main { 90 | grid-template-columns: 1fr 5fr 200px; 91 | } 92 | div#content { 93 | max-width: 600px; 94 | } 95 | div#sidebar { 96 | max-width: 200px; 97 | padding: 0px 10px; 98 | } 99 | img.prevarrow { 100 | margin-left: 15%; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /book/figs/dungeons1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/dungeons1.pdf -------------------------------------------------------------------------------- /book/figs/dungeons2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/dungeons2.pdf -------------------------------------------------------------------------------- /book/figs/dungeons3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/dungeons3.pdf -------------------------------------------------------------------------------- /book/figs/euro1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/euro1.pdf -------------------------------------------------------------------------------- /book/figs/euro2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/euro2.pdf -------------------------------------------------------------------------------- /book/figs/euro3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/euro3.pdf -------------------------------------------------------------------------------- /book/figs/hockey0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/hockey0.pdf -------------------------------------------------------------------------------- /book/figs/hockey1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/hockey1.pdf -------------------------------------------------------------------------------- /book/figs/hockey2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/hockey2.pdf -------------------------------------------------------------------------------- /book/figs/hockey3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/hockey3.pdf -------------------------------------------------------------------------------- /book/figs/jaynes1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/jaynes1.pdf -------------------------------------------------------------------------------- /book/figs/jaynes2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/jaynes2.pdf -------------------------------------------------------------------------------- /book/figs/kidney1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/kidney1.pdf -------------------------------------------------------------------------------- /book/figs/kidney2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/kidney2.pdf -------------------------------------------------------------------------------- /book/figs/kidney3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/kidney3.pdf -------------------------------------------------------------------------------- /book/figs/kidney4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/kidney4.pdf -------------------------------------------------------------------------------- /book/figs/kidney5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/kidney5.pdf -------------------------------------------------------------------------------- /book/figs/kidney6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/kidney6.pdf -------------------------------------------------------------------------------- /book/figs/kidney7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/kidney7.pdf -------------------------------------------------------------------------------- /book/figs/kidney8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/kidney8.pdf -------------------------------------------------------------------------------- /book/figs/paintball.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/paintball.pdf -------------------------------------------------------------------------------- /book/figs/paintball1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/paintball1.pdf -------------------------------------------------------------------------------- /book/figs/paintball2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/paintball2.pdf -------------------------------------------------------------------------------- /book/figs/paintball3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/paintball3.pdf -------------------------------------------------------------------------------- /book/figs/paintball4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/paintball4.pdf -------------------------------------------------------------------------------- /book/figs/paintball5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/paintball5.pdf -------------------------------------------------------------------------------- /book/figs/price1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/price1.pdf -------------------------------------------------------------------------------- /book/figs/price2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/price2.pdf -------------------------------------------------------------------------------- /book/figs/price3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/price3.pdf -------------------------------------------------------------------------------- /book/figs/price4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/price4.pdf -------------------------------------------------------------------------------- /book/figs/price5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/price5.pdf -------------------------------------------------------------------------------- /book/figs/price6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/price6.pdf -------------------------------------------------------------------------------- /book/figs/redline0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/redline0.pdf -------------------------------------------------------------------------------- /book/figs/redline1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/redline1.pdf -------------------------------------------------------------------------------- /book/figs/redline2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/redline2.pdf -------------------------------------------------------------------------------- /book/figs/redline3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/redline3.pdf -------------------------------------------------------------------------------- /book/figs/redline4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/redline4.pdf -------------------------------------------------------------------------------- /book/figs/redline5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/redline5.pdf -------------------------------------------------------------------------------- /book/figs/sat_calibrate.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/sat_calibrate.pdf -------------------------------------------------------------------------------- /book/figs/sat_join.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/sat_join.pdf -------------------------------------------------------------------------------- /book/figs/sat_joint.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/sat_joint.pdf -------------------------------------------------------------------------------- /book/figs/sat_normal.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/sat_normal.pdf -------------------------------------------------------------------------------- /book/figs/sat_posteriors.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/sat_posteriors.pdf -------------------------------------------------------------------------------- /book/figs/sat_posteriors2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/sat_posteriors2.pdf -------------------------------------------------------------------------------- /book/figs/sat_posteriors_eff.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/sat_posteriors_eff.pdf -------------------------------------------------------------------------------- /book/figs/sat_posteriors_p_corr.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/sat_posteriors_p_corr.pdf -------------------------------------------------------------------------------- /book/figs/sat_prior.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/sat_prior.pdf -------------------------------------------------------------------------------- /book/figs/sat_prior2.eps: -------------------------------------------------------------------------------- 1 | %!PS-Adobe-3.0 EPSF-3.0 2 | %%Title: sat_prior2.eps 3 | %%Creator: matplotlib version 0.99.1.1, http://matplotlib.sourceforge.net/ 4 | %%CreationDate: Tue Aug 23 12:03:18 2011 5 | %%Orientation: portrait 6 | %%BoundingBox: 18 180 594 612 7 | %%EndComments 8 | %%BeginProlog 9 | /mpldict 8 dict def 10 | mpldict begin 11 | /m { moveto } bind def 12 | /l { lineto } bind def 13 | /r { rlineto } bind def 14 | /c { curveto } bind def 15 | /cl { closepath } bind def 16 | /box { 17 | m 18 | 1 index 0 r 19 | 0 exch r 20 | neg 0 r 21 | cl 22 | } bind def 23 | /clipbox { 24 | box 25 | clip 26 | newpath 27 | } bind def 28 | %!PS-Adobe-3.0 Resource-Font 29 | %%Title: DejaVu Sans 30 | %%Copyright: Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. DejaVu changes are in public domain 31 | %%Creator: Converted from TrueType by PPR 32 | 25 dict begin 33 | /_d{bind def}bind def 34 | /_m{moveto}_d 35 | /_l{lineto}_d 36 | /_cl{closepath eofill}_d 37 | /_c{curveto}_d 38 | /_sc{7 -1 roll{setcachedevice}{pop pop pop pop pop pop}ifelse}_d 39 | /_e{exec}_d 40 | /FontName /DejaVuSans def 41 | /PaintType 0 def 42 | /FontMatrix[.001 0 0 .001 0 0]def 43 | /FontBBox[-1020 -349 1681 1167]def 44 | /FontType 3 def 45 | /Encoding StandardEncoding def 46 | /FontInfo 10 dict dup begin 47 | /FamilyName (DejaVu Sans) def 48 | /FullName (DejaVu Sans) def 49 | /Notice (Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. DejaVu changes are in public domain ) def 50 | /Weight (Book) def 51 | /Version (Version 2.30) def 52 | /ItalicAngle 0.0 def 53 | /isFixedPitch false def 54 | /UnderlinePosition -130 def 55 | /UnderlineThickness 90 def 56 | end readonly def 57 | /CharStrings 14 dict dup begin 58 | /period{318 0 107 0 210 124 _sc 59 | 107 124 _m 60 | 210 124 _l 61 | 210 0 _l 62 | 107 0 _l 63 | 107 124 _l 64 | _cl}_d 65 | /zero{636 0 66 -13 570 742 _sc 66 | 318 664 _m 67 | 267 664 229 639 203 589 _c 68 | 177 539 165 464 165 364 _c 69 | 165 264 177 189 203 139 _c 70 | 229 89 267 64 318 64 _c 71 | 369 64 407 89 433 139 _c 72 | 458 189 471 264 471 364 _c 73 | 471 464 458 539 433 589 _c 74 | 407 639 369 664 318 664 _c 75 | 318 742 _m 76 | 399 742 461 709 505 645 _c 77 | 548 580 570 486 570 364 _c 78 | 570 241 548 147 505 83 _c 79 | 461 19 399 -13 318 -13 _c 80 | 236 -13 173 19 130 83 _c 81 | 87 147 66 241 66 364 _c 82 | 66 486 87 580 130 645 _c 83 | 173 709 236 742 318 742 _c 84 | _cl}_d 85 | /one{636 0 110 0 544 729 _sc 86 | 124 83 _m 87 | 285 83 _l 88 | 285 639 _l 89 | 110 604 _l 90 | 110 694 _l 91 | 284 729 _l 92 | 383 729 _l 93 | 383 83 _l 94 | 544 83 _l 95 | 544 0 _l 96 | 124 0 _l 97 | 124 83 _l 98 | _cl}_d 99 | /two{{636 0 73 0 536 742 _sc 100 | 192 83 _m 101 | 536 83 _l 102 | 536 0 _l 103 | 73 0 _l 104 | 73 83 _l 105 | 110 121 161 173 226 239 _c 106 | 290 304 331 346 348 365 _c 107 | 380 400 402 430 414 455 _c 108 | 426 479 433 504 433 528 _c 109 | 433 566 419 598 392 622 _c 110 | 365 646 330 659 286 659 _c 111 | 255 659 222 653 188 643 _c 112 | 154 632 117 616 78 594 _c 113 | 78 694 _l 114 | 118 710 155 722 189 730 _c 115 | 223 738 255 742 284 742 _c 116 | 359 742 419 723 464 685 _c 117 | 509 647 532 597 532 534 _c 118 | 532 504 526 475 515 449 _c 119 | 504 422 484 390 454 354 _c 120 | 446 344 420 317 376 272 _c 121 | 332 227 271 164 192 83 _c 122 | _cl}_e}_d 123 | /four{636 0 49 0 580 729 _sc 124 | 378 643 _m 125 | 129 254 _l 126 | 378 254 _l 127 | 378 643 _l 128 | 352 729 _m 129 | 476 729 _l 130 | 476 254 _l 131 | 580 254 _l 132 | 580 172 _l 133 | 476 172 _l 134 | 476 0 _l 135 | 378 0 _l 136 | 378 172 _l 137 | 49 172 _l 138 | 49 267 _l 139 | 352 729 _l 140 | _cl}_d 141 | /six{{636 0 70 -13 573 742 _sc 142 | 330 404 _m 143 | 286 404 251 388 225 358 _c 144 | 199 328 186 286 186 234 _c 145 | 186 181 199 139 225 109 _c 146 | 251 79 286 64 330 64 _c 147 | 374 64 409 79 435 109 _c 148 | 461 139 474 181 474 234 _c 149 | 474 286 461 328 435 358 _c 150 | 409 388 374 404 330 404 _c 151 | 526 713 _m 152 | 526 623 _l 153 | 501 635 476 644 451 650 _c 154 | 425 656 400 659 376 659 _c 155 | 310 659 260 637 226 593 _c 156 | 192 549 172 482 168 394 _c 157 | 187 422 211 444 240 459 _c 158 | 269 474 301 482 336 482 _c 159 | 409 482 467 459 509 415 _c 160 | 551 371 573 310 573 234 _c 161 | 573 159 550 99 506 54 _c 162 | 462 9 403 -13 330 -13 _c 163 | 246 -13 181 19 137 83 _c 164 | 92 147 70 241 70 364 _c 165 | 70 479 97 571 152 639 _c 166 | 206 707 280 742 372 742 _c 167 | }_e{396 742 421 739 447 735 _c 168 | 472 730 498 723 526 713 _c 169 | _cl}_e}_d 170 | /eight{{636 0 68 -13 568 742 _sc 171 | 318 346 _m 172 | 271 346 234 333 207 308 _c 173 | 180 283 167 249 167 205 _c 174 | 167 161 180 126 207 101 _c 175 | 234 76 271 64 318 64 _c 176 | 364 64 401 76 428 102 _c 177 | 455 127 469 161 469 205 _c 178 | 469 249 455 283 429 308 _c 179 | 402 333 365 346 318 346 _c 180 | 219 388 _m 181 | 177 398 144 418 120 447 _c 182 | 96 476 85 511 85 553 _c 183 | 85 611 105 657 147 691 _c 184 | 188 725 245 742 318 742 _c 185 | 390 742 447 725 489 691 _c 186 | 530 657 551 611 551 553 _c 187 | 551 511 539 476 515 447 _c 188 | 491 418 459 398 417 388 _c 189 | 464 377 501 355 528 323 _c 190 | 554 291 568 251 568 205 _c 191 | 568 134 546 80 503 43 _c 192 | 459 5 398 -13 318 -13 _c 193 | 237 -13 175 5 132 43 _c 194 | 89 80 68 134 68 205 _c 195 | 68 251 81 291 108 323 _c 196 | 134 355 171 377 219 388 _c 197 | }_e{183 544 _m 198 | 183 506 194 476 218 455 _c 199 | 242 434 275 424 318 424 _c 200 | 360 424 393 434 417 455 _c 201 | 441 476 453 506 453 544 _c 202 | 453 582 441 611 417 632 _c 203 | 393 653 360 664 318 664 _c 204 | 275 664 242 653 218 632 _c 205 | 194 611 183 582 183 544 _c 206 | _cl}_e}_d 207 | /C{{698 0 56 -13 644 742 _sc 208 | 644 673 _m 209 | 644 569 _l 210 | 610 599 575 622 537 638 _c 211 | 499 653 460 661 418 661 _c 212 | 334 661 270 635 226 584 _c 213 | 182 533 160 460 160 364 _c 214 | 160 268 182 194 226 143 _c 215 | 270 92 334 67 418 67 _c 216 | 460 67 499 74 537 90 _c 217 | 575 105 610 128 644 159 _c 218 | 644 56 _l 219 | 609 32 572 15 534 4 _c 220 | 496 -7 455 -13 412 -13 _c 221 | 302 -13 215 20 151 87 _c 222 | 87 154 56 246 56 364 _c 223 | 56 481 87 573 151 641 _c 224 | 215 708 302 742 412 742 _c 225 | 456 742 497 736 535 725 _c 226 | 573 713 610 696 644 673 _c 227 | _cl}_e}_d 228 | /D{770 0 98 0 711 729 _sc 229 | 197 648 _m 230 | 197 81 _l 231 | 316 81 _l 232 | 416 81 490 103 537 149 _c 233 | 583 195 607 267 607 365 _c 234 | 607 463 583 534 537 580 _c 235 | 490 625 416 648 316 648 _c 236 | 197 648 _l 237 | 98 729 _m 238 | 301 729 _l 239 | 442 729 546 699 612 641 _c 240 | 678 582 711 490 711 365 _c 241 | 711 239 677 147 611 88 _c 242 | 545 29 441 0 301 0 _c 243 | 98 0 _l 244 | 98 729 _l 245 | _cl}_d 246 | /F{575 0 98 0 517 729 _sc 247 | 98 729 _m 248 | 517 729 _l 249 | 517 646 _l 250 | 197 646 _l 251 | 197 431 _l 252 | 486 431 _l 253 | 486 348 _l 254 | 197 348 _l 255 | 197 0 _l 256 | 98 0 _l 257 | 98 729 _l 258 | _cl}_d 259 | /i{278 0 94 0 184 760 _sc 260 | 94 547 _m 261 | 184 547 _l 262 | 184 0 _l 263 | 94 0 _l 264 | 94 547 _l 265 | 94 760 _m 266 | 184 760 _l 267 | 184 646 _l 268 | 94 646 _l 269 | 94 760 _l 270 | _cl}_d 271 | /o{612 0 55 -13 557 560 _sc 272 | 306 484 _m 273 | 258 484 220 465 192 427 _c 274 | 164 389 150 338 150 273 _c 275 | 150 207 163 156 191 118 _c 276 | 219 80 257 62 306 62 _c 277 | 354 62 392 80 420 118 _c 278 | 448 156 462 207 462 273 _c 279 | 462 337 448 389 420 427 _c 280 | 392 465 354 484 306 484 _c 281 | 306 560 _m 282 | 384 560 445 534 490 484 _c 283 | 534 433 557 363 557 273 _c 284 | 557 183 534 113 490 63 _c 285 | 445 12 384 -13 306 -13 _c 286 | 227 -13 165 12 121 63 _c 287 | 77 113 55 183 55 273 _c 288 | 55 363 77 433 121 484 _c 289 | 165 534 227 560 306 560 _c 290 | _cl}_d 291 | /p{{635 0 91 -207 580 560 _sc 292 | 181 82 _m 293 | 181 -207 _l 294 | 91 -207 _l 295 | 91 547 _l 296 | 181 547 _l 297 | 181 464 _l 298 | 199 496 223 520 252 536 _c 299 | 281 552 316 560 356 560 _c 300 | 422 560 476 533 518 481 _c 301 | 559 428 580 359 580 273 _c 302 | 580 187 559 117 518 65 _c 303 | 476 13 422 -13 356 -13 _c 304 | 316 -13 281 -5 252 10 _c 305 | 223 25 199 49 181 82 _c 306 | 487 273 _m 307 | 487 339 473 390 446 428 _c 308 | 418 466 381 485 334 485 _c 309 | 286 485 249 466 222 428 _c 310 | 194 390 181 339 181 273 _c 311 | 181 207 194 155 222 117 _c 312 | 249 79 286 61 334 61 _c 313 | 381 61 418 79 446 117 _c 314 | 473 155 487 207 487 273 _c 315 | _cl}_e}_d 316 | /r{411 0 91 0 411 560 _sc 317 | 411 463 _m 318 | 401 469 390 473 378 476 _c 319 | 366 478 353 480 339 480 _c 320 | 288 480 249 463 222 430 _c 321 | 194 397 181 350 181 288 _c 322 | 181 0 _l 323 | 91 0 _l 324 | 91 547 _l 325 | 181 547 _l 326 | 181 462 _l 327 | 199 495 224 520 254 536 _c 328 | 284 552 321 560 365 560 _c 329 | 371 560 378 559 386 559 _c 330 | 393 558 401 557 411 555 _c 331 | 411 463 _l 332 | _cl}_d 333 | end readonly def 334 | 335 | /BuildGlyph 336 | {exch begin 337 | CharStrings exch 338 | 2 copy known not{pop /.notdef}if 339 | true 3 1 roll get exec 340 | end}_d 341 | 342 | /BuildChar { 343 | 1 index /Encoding get exch get 344 | 1 index /BuildGlyph get exec 345 | }_d 346 | 347 | FontName currentdict end definefont pop 348 | end 349 | %%EndProlog 350 | mpldict begin 351 | 18 180 translate 352 | 576 432 0 0 clipbox 353 | 1.000 setlinewidth 354 | 1 setlinejoin 355 | 2 setlinecap 356 | [] 0 setdash 357 | 1.000 setgray 358 | gsave 359 | 0 0 m 360 | 576 0 l 361 | 576 432 l 362 | 0 432 l 363 | 0 0 l 364 | gsave 365 | fill 366 | grestore 367 | stroke 368 | grestore 369 | gsave 370 | 72 43.2 m 371 | 518.4 43.2 l 372 | 518.4 388.8 l 373 | 72 388.8 l 374 | 72 43.2 l 375 | fill 376 | grestore 377 | 2.000 setlinewidth 378 | 0.000 0.000 1.000 setrgbcolor 379 | gsave 380 | 446.4 345.6 72 43.2 clipbox 381 | 72 43.2 m 382 | 72 43.9363 l 383 | 77.5111 43.9363 l 384 | 77.5111 44.4222 l 385 | 83.0222 44.4222 l 386 | 83.0222 45.2073 l 387 | 88.5333 45.2073 l 388 | 88.5333 45.9248 l 389 | 94.0444 45.9248 l 390 | 94.0444 47.5776 l 391 | 99.5556 47.5776 l 392 | 99.5556 49.2304 l 393 | 105.067 49.2304 l 394 | 105.067 51.124 l 395 | 110.578 51.124 l 396 | 110.578 53.7693 l 397 | 117.091 53.7693 l 398 | 117.091 56.3301 l 399 | 124.606 56.3301 l 400 | 124.606 59.6148 l 401 | 132.121 59.6148 l 402 | 132.121 63.5771 l 403 | 139.636 63.5771 l 404 | 139.636 68.2494 l 405 | 147.152 68.2494 l 406 | 147.152 73.6061 l 407 | 154.667 73.6061 l 408 | 154.667 79.4133 l 409 | 163.852 79.4133 l 410 | 163.852 85.5086 l 411 | 173.037 85.5086 l 412 | 173.037 92.8014 l 413 | 182.222 92.8014 l 414 | 182.222 99.552 l 415 | 191.407 99.552 l 416 | 191.407 108.967 l 417 | 201.167 108.967 l 418 | 201.167 119.694 l 419 | 211.5 119.694 l 420 | 211.5 130.099 l 421 | 221.833 130.099 l 422 | 221.833 138.9 l 423 | 232.167 138.9 l 424 | 232.167 150.17 l 425 | 242.5 150.17 l 426 | 242.5 163.229 l 427 | 252.833 163.229 l 428 | 252.833 173.904 l 429 | 263.167 173.904 l 430 | 263.167 183.085 l 431 | 273.5 183.085 l 432 | 273.5 195.909 l 433 | 283.833 195.909 l 434 | 283.833 209.63 l 435 | 294.167 209.63 l 436 | 294.167 219.84 l 437 | 304.5 219.84 l 438 | 304.5 229.634 l 439 | 314.833 229.634 l 440 | 314.833 242.003 l 441 | 325.167 242.003 l 442 | 325.167 254.257 l 443 | 335.5 254.257 l 444 | 335.5 262.899 l 445 | 345.833 262.899 l 446 | 345.833 271.487 l 447 | 356.167 271.487 l 448 | 356.167 283.107 l 449 | 365.926 283.107 l 450 | 365.926 292.29 l 451 | 375.111 292.29 l 452 | 375.111 301.003 l 453 | 384.296 301.003 l 454 | 384.296 308.496 l 455 | 393.481 308.496 l 456 | 393.481 318.398 l 457 | 402.667 318.398 l 458 | 402.667 325.478 l 459 | 413 325.478 l 460 | 413 331.863 l 461 | 423.333 331.863 l 462 | 423.333 337.893 l 463 | 433.667 337.893 l 464 | 433.667 343.801 l 465 | 444 343.801 l 466 | 444 349.946 l 467 | 450.889 349.946 l 468 | 450.889 355.422 l 469 | 457.778 355.422 l 470 | 457.778 360.578 l 471 | 464.667 360.578 l 472 | 464.667 365.363 l 473 | 471.556 365.363 l 474 | 471.556 369.271 l 475 | 478.444 369.271 l 476 | 478.444 372.796 l 477 | 485.333 372.796 l 478 | 485.333 374.52 l 479 | 489.467 374.52 l 480 | 489.467 376.703 l 481 | 493.6 376.703 l 482 | 493.6 378.398 l 483 | 497.733 378.398 l 484 | 497.733 380.714 l 485 | 501.867 380.714 l 486 | 501.867 382.29 l 487 | 506 382.29 l 488 | 506 384.461 l 489 | 510.133 384.461 l 490 | 510.133 385.308 l 491 | 514.267 385.308 l 492 | 514.267 386.114 l 493 | 518.4 386.114 l 494 | 518.4 388.8 l 495 | stroke 496 | grestore 497 | 0.500 setlinewidth 498 | 0 setlinecap 499 | 0.000 setgray 500 | gsave 501 | /o { 502 | gsave 503 | newpath 504 | translate 505 | 0 0 m 506 | 0 4 l 507 | stroke 508 | grestore 509 | } bind def 510 | 72 43.2 o 511 | grestore 512 | gsave 513 | /o { 514 | gsave 515 | newpath 516 | translate 517 | 0 0 m 518 | 0 -4 l 519 | stroke 520 | grestore 521 | } bind def 522 | 72 388.8 o 523 | grestore 524 | /DejaVuSans findfont 525 | 14.000 scalefont 526 | setfont 527 | gsave 528 | 61.789062 28.606250 translate 529 | 0.000000 rotate 530 | 0.000000 0.203125 m /zero glyphshow 531 | 8.907227 0.203125 m /period glyphshow 532 | 13.357422 0.203125 m /zero glyphshow 533 | grestore 534 | gsave 535 | /o { 536 | gsave 537 | newpath 538 | translate 539 | 0 0 m 540 | 0 4 l 541 | stroke 542 | grestore 543 | } bind def 544 | 161.28 43.2 o 545 | grestore 546 | gsave 547 | /o { 548 | gsave 549 | newpath 550 | translate 551 | 0 0 m 552 | 0 -4 l 553 | stroke 554 | grestore 555 | } bind def 556 | 161.28 388.8 o 557 | grestore 558 | gsave 559 | 151.311250 28.606250 translate 560 | 0.000000 rotate 561 | 0.000000 0.203125 m /zero glyphshow 562 | 8.907227 0.203125 m /period glyphshow 563 | 13.357422 0.203125 m /two glyphshow 564 | grestore 565 | gsave 566 | /o { 567 | gsave 568 | newpath 569 | translate 570 | 0 0 m 571 | 0 4 l 572 | stroke 573 | grestore 574 | } bind def 575 | 250.56 43.2 o 576 | grestore 577 | gsave 578 | /o { 579 | gsave 580 | newpath 581 | translate 582 | 0 0 m 583 | 0 -4 l 584 | stroke 585 | grestore 586 | } bind def 587 | 250.56 388.8 o 588 | grestore 589 | gsave 590 | 240.278750 28.606250 translate 591 | 0.000000 rotate 592 | 0.000000 0.203125 m /zero glyphshow 593 | 8.907227 0.203125 m /period glyphshow 594 | 13.357422 0.203125 m /four glyphshow 595 | grestore 596 | gsave 597 | /o { 598 | gsave 599 | newpath 600 | translate 601 | 0 0 m 602 | 0 4 l 603 | stroke 604 | grestore 605 | } bind def 606 | 339.84 43.2 o 607 | grestore 608 | gsave 609 | /o { 610 | gsave 611 | newpath 612 | translate 613 | 0 0 m 614 | 0 -4 l 615 | stroke 616 | grestore 617 | } bind def 618 | 339.84 388.8 o 619 | grestore 620 | gsave 621 | 329.605625 28.606250 translate 622 | 0.000000 rotate 623 | 0.000000 0.203125 m /zero glyphshow 624 | 8.907227 0.203125 m /period glyphshow 625 | 13.357422 0.203125 m /six glyphshow 626 | grestore 627 | gsave 628 | /o { 629 | gsave 630 | newpath 631 | translate 632 | 0 0 m 633 | 0 4 l 634 | stroke 635 | grestore 636 | } bind def 637 | 429.12 43.2 o 638 | grestore 639 | gsave 640 | /o { 641 | gsave 642 | newpath 643 | translate 644 | 0 0 m 645 | 0 -4 l 646 | stroke 647 | grestore 648 | } bind def 649 | 429.12 388.8 o 650 | grestore 651 | gsave 652 | 418.924688 28.606250 translate 653 | 0.000000 rotate 654 | 0.000000 0.203125 m /zero glyphshow 655 | 8.907227 0.203125 m /period glyphshow 656 | 13.357422 0.203125 m /eight glyphshow 657 | grestore 658 | gsave 659 | /o { 660 | gsave 661 | newpath 662 | translate 663 | 0 0 m 664 | 0 4 l 665 | stroke 666 | grestore 667 | } bind def 668 | 518.4 43.2 o 669 | grestore 670 | gsave 671 | /o { 672 | gsave 673 | newpath 674 | translate 675 | 0 0 m 676 | 0 -4 l 677 | stroke 678 | grestore 679 | } bind def 680 | 518.4 388.8 o 681 | grestore 682 | gsave 683 | 508.501562 28.606250 translate 684 | 0.000000 rotate 685 | 0.000000 0.203125 m /one glyphshow 686 | 8.907227 0.203125 m /period glyphshow 687 | 13.357422 0.203125 m /zero glyphshow 688 | grestore 689 | 291.77 12.856 m 690 | 0 2.906 rmoveto 691 | (p) show 692 | gsave 693 | /o { 694 | gsave 695 | newpath 696 | translate 697 | 0 0 m 698 | 4 0 l 699 | stroke 700 | grestore 701 | } bind def 702 | 72 43.2 o 703 | grestore 704 | gsave 705 | /o { 706 | gsave 707 | newpath 708 | translate 709 | 0 0 m 710 | -4 0 l 711 | stroke 712 | grestore 713 | } bind def 714 | 518.4 43.2 o 715 | grestore 716 | gsave 717 | 47.578125 37.903125 translate 718 | 0.000000 rotate 719 | 0.000000 0.203125 m /zero glyphshow 720 | 8.907227 0.203125 m /period glyphshow 721 | 13.357422 0.203125 m /zero glyphshow 722 | grestore 723 | gsave 724 | /o { 725 | gsave 726 | newpath 727 | translate 728 | 0 0 m 729 | 4 0 l 730 | stroke 731 | grestore 732 | } bind def 733 | 72 112.32 o 734 | grestore 735 | gsave 736 | /o { 737 | gsave 738 | newpath 739 | translate 740 | 0 0 m 741 | -4 0 l 742 | stroke 743 | grestore 744 | } bind def 745 | 518.4 112.32 o 746 | grestore 747 | gsave 748 | 48.062500 107.023125 translate 749 | 0.000000 rotate 750 | 0.000000 0.203125 m /zero glyphshow 751 | 8.907227 0.203125 m /period glyphshow 752 | 13.357422 0.203125 m /two glyphshow 753 | grestore 754 | gsave 755 | /o { 756 | gsave 757 | newpath 758 | translate 759 | 0 0 m 760 | 4 0 l 761 | stroke 762 | grestore 763 | } bind def 764 | 72 181.44 o 765 | grestore 766 | gsave 767 | /o { 768 | gsave 769 | newpath 770 | translate 771 | 0 0 m 772 | -4 0 l 773 | stroke 774 | grestore 775 | } bind def 776 | 518.4 181.44 o 777 | grestore 778 | gsave 779 | 47.437500 176.143125 translate 780 | 0.000000 rotate 781 | 0.000000 0.203125 m /zero glyphshow 782 | 8.907227 0.203125 m /period glyphshow 783 | 13.357422 0.203125 m /four glyphshow 784 | grestore 785 | gsave 786 | /o { 787 | gsave 788 | newpath 789 | translate 790 | 0 0 m 791 | 4 0 l 792 | stroke 793 | grestore 794 | } bind def 795 | 72 250.56 o 796 | grestore 797 | gsave 798 | /o { 799 | gsave 800 | newpath 801 | translate 802 | 0 0 m 803 | -4 0 l 804 | stroke 805 | grestore 806 | } bind def 807 | 518.4 250.56 o 808 | grestore 809 | gsave 810 | 47.531250 245.263125 translate 811 | 0.000000 rotate 812 | 0.000000 0.203125 m /zero glyphshow 813 | 8.907227 0.203125 m /period glyphshow 814 | 13.357422 0.203125 m /six glyphshow 815 | grestore 816 | gsave 817 | /o { 818 | gsave 819 | newpath 820 | translate 821 | 0 0 m 822 | 4 0 l 823 | stroke 824 | grestore 825 | } bind def 826 | 72 319.68 o 827 | grestore 828 | gsave 829 | /o { 830 | gsave 831 | newpath 832 | translate 833 | 0 0 m 834 | -4 0 l 835 | stroke 836 | grestore 837 | } bind def 838 | 518.4 319.68 o 839 | grestore 840 | gsave 841 | 47.609375 314.383125 translate 842 | 0.000000 rotate 843 | 0.000000 0.203125 m /zero glyphshow 844 | 8.907227 0.203125 m /period glyphshow 845 | 13.357422 0.203125 m /eight glyphshow 846 | grestore 847 | gsave 848 | /o { 849 | gsave 850 | newpath 851 | translate 852 | 0 0 m 853 | 4 0 l 854 | stroke 855 | grestore 856 | } bind def 857 | 72 388.8 o 858 | grestore 859 | gsave 860 | /o { 861 | gsave 862 | newpath 863 | translate 864 | 0 0 m 865 | -4 0 l 866 | stroke 867 | grestore 868 | } bind def 869 | 518.4 388.8 o 870 | grestore 871 | gsave 872 | 48.203125 383.503125 translate 873 | 0.000000 rotate 874 | 0.000000 0.203125 m /one glyphshow 875 | 8.907227 0.203125 m /period glyphshow 876 | 13.357422 0.203125 m /zero glyphshow 877 | grestore 878 | 42.438 202.492 m 879 | gsave 880 | 90 rotate 881 | 0 0.203 rmoveto 882 | (CDF) show 883 | grestore 884 | 1.000 setlinewidth 885 | 2 setlinecap 886 | gsave 887 | 72 388.8 m 888 | 518.4 388.8 l 889 | stroke 890 | grestore 891 | gsave 892 | 518.4 43.2 m 893 | 518.4 388.8 l 894 | stroke 895 | grestore 896 | gsave 897 | 72 43.2 m 898 | 518.4 43.2 l 899 | stroke 900 | grestore 901 | gsave 902 | 72 43.2 m 903 | 72 388.8 l 904 | stroke 905 | grestore 906 | gsave 907 | 80.4 350.507 m 908 | 178.693 350.507 l 909 | 178.693 380.4 l 910 | 80.4 380.4 l 911 | 80.4 350.507 l 912 | cl 913 | gsave 914 | 1.000 setgray 915 | fill 916 | grestore 917 | stroke 918 | grestore 919 | 2.000 setlinewidth 920 | 0.000 0.000 1.000 setrgbcolor 921 | gsave 922 | 92.16 366.638 m 923 | 115.68 366.638 l 924 | stroke 925 | grestore 926 | 0.000 setgray 927 | /DejaVuSans findfont 928 | 16.800 scalefont 929 | setfont 930 | 134.16 357.227 m 931 | 0 3.531 rmoveto 932 | (prior) show 933 | 934 | end 935 | showpage 936 | -------------------------------------------------------------------------------- /book/figs/sat_prior2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/sat_prior2.pdf -------------------------------------------------------------------------------- /book/figs/species-cdf-B1558.G.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-cdf-B1558.G.pdf -------------------------------------------------------------------------------- /book/figs/species-cond-B1242.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-cond-B1242.pdf -------------------------------------------------------------------------------- /book/figs/species-cond-B1246.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-cond-B1246.pdf -------------------------------------------------------------------------------- /book/figs/species-frac-B1242.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-frac-B1242.pdf -------------------------------------------------------------------------------- /book/figs/species-frac-B1246.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-frac-B1246.pdf -------------------------------------------------------------------------------- /book/figs/species-l-cal.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-l-cal.pdf -------------------------------------------------------------------------------- /book/figs/species-l-val.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-l-val.pdf -------------------------------------------------------------------------------- /book/figs/species-l.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-l.pdf -------------------------------------------------------------------------------- /book/figs/species-madd.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-madd.pdf -------------------------------------------------------------------------------- /book/figs/species-n-cal.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-n-cal.pdf -------------------------------------------------------------------------------- /book/figs/species-n.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-n.pdf -------------------------------------------------------------------------------- /book/figs/species-ndist-B1242.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-ndist-B1242.pdf -------------------------------------------------------------------------------- /book/figs/species-ndist-B1246.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-ndist-B1246.pdf -------------------------------------------------------------------------------- /book/figs/species-prev-B1242.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-prev-B1242.pdf -------------------------------------------------------------------------------- /book/figs/species-prev-B1246.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-prev-B1246.pdf -------------------------------------------------------------------------------- /book/figs/species-q-cal.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-q-cal.pdf -------------------------------------------------------------------------------- /book/figs/species-q-val.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-q-val.pdf -------------------------------------------------------------------------------- /book/figs/species-q.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-q.pdf -------------------------------------------------------------------------------- /book/figs/species-rare-B1242.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-rare-B1242.pdf -------------------------------------------------------------------------------- /book/figs/species-rare-B1246.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species-rare-B1246.pdf -------------------------------------------------------------------------------- /book/figs/species.cond.B1242.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species.cond.B1242.pdf -------------------------------------------------------------------------------- /book/figs/species.frac.B1242.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species.frac.B1242.pdf -------------------------------------------------------------------------------- /book/figs/species.frac.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species.frac.pdf -------------------------------------------------------------------------------- /book/figs/species.ndist.B1242.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species.ndist.B1242.pdf -------------------------------------------------------------------------------- /book/figs/species.prev.B1242.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species.prev.B1242.pdf -------------------------------------------------------------------------------- /book/figs/species.rare.B1242.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species.rare.B1242.pdf -------------------------------------------------------------------------------- /book/figs/species.rare.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species.rare.pdf -------------------------------------------------------------------------------- /book/figs/species1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species1.pdf -------------------------------------------------------------------------------- /book/figs/species2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species2.pdf -------------------------------------------------------------------------------- /book/figs/species4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species4.pdf -------------------------------------------------------------------------------- /book/figs/species5-cal.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species5-cal.pdf -------------------------------------------------------------------------------- /book/figs/species5-val.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species5-val.pdf -------------------------------------------------------------------------------- /book/figs/species5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species5.pdf -------------------------------------------------------------------------------- /book/figs/species6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/species6.pdf -------------------------------------------------------------------------------- /book/figs/train1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/train1.pdf -------------------------------------------------------------------------------- /book/figs/train2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/train2.pdf -------------------------------------------------------------------------------- /book/figs/train3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/train3.pdf -------------------------------------------------------------------------------- /book/figs/train4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/train4.pdf -------------------------------------------------------------------------------- /book/figs/variability_cv.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/variability_cv.pdf -------------------------------------------------------------------------------- /book/figs/variability_posterior_female.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/variability_posterior_female.pdf -------------------------------------------------------------------------------- /book/figs/variability_posterior_male.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/figs/variability_posterior_male.pdf -------------------------------------------------------------------------------- /book/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /book/header.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 |

This HTML version of Think Bayes is provided for convenience, but it 7 | is not the best format for the book. In particular, some of the 8 | math symbols are not rendered correctly. 9 | 10 |

You might prefer to read 11 | the PDF version, or 12 | you can buy a hard copy from 13 | Amazon. 14 |

15 | -------------------------------------------------------------------------------- /book/hevea.sty: -------------------------------------------------------------------------------- 1 | % hevea : hevea.sty 2 | % This is a very basic style file for latex document to be processed 3 | % with hevea. It contains definitions of LaTeX environment which are 4 | % processed in a special way by the translator. 5 | % Mostly : 6 | % - latexonly, not processed by hevea, processed by latex. 7 | % - htmlonly , the reverse. 8 | % - rawhtml, to include raw HTML in hevea output. 9 | % - toimage, to send text to the image file. 10 | % The package also provides hevea logos, html related commands (ahref 11 | % etc.), void cutting and image commands. 12 | \NeedsTeXFormat{LaTeX2e} 13 | \ProvidesPackage{hevea}[2002/01/11] 14 | \RequirePackage{comment} 15 | \newif\ifhevea\heveafalse 16 | \@ifundefined{ifimagen}{\newif\ifimagen\imagenfalse} 17 | \makeatletter% 18 | \newcommand{\heveasmup}[2]{% 19 | \raise #1\hbox{$\m@th$% 20 | \csname S@\f@size\endcsname 21 | \fontsize\sf@size 0% 22 | \math@fontsfalse\selectfont 23 | #2% 24 | }}% 25 | \DeclareRobustCommand{\hevea}{H\kern-.15em\heveasmup{.2ex}{E}\kern-.15emV\kern-.15em\heveasmup{.2ex}{E}\kern-.15emA}% 26 | \DeclareRobustCommand{\hacha}{H\kern-.15em\heveasmup{.2ex}{A}\kern-.15emC\kern-.1em\heveasmup{.2ex}{H}\kern-.15emA}% 27 | \DeclareRobustCommand{\html}{\protect\heveasmup{0.ex}{HTML}} 28 | %%%%%%%%% Hyperlinks hevea style 29 | \newcommand{\ahref}[2]{{#2}} 30 | \newcommand{\ahrefloc}[2]{{#2}} 31 | \newcommand{\aname}[2]{{#2}} 32 | \newcommand{\ahrefurl}[1]{\texttt{#1}} 33 | \newcommand{\footahref}[2]{#2\footnote{\texttt{#1}}} 34 | \newcommand{\mailto}[1]{\texttt{#1}} 35 | \newcommand{\imgsrc}[2][]{} 36 | \newcommand{\home}[1]{\protect\raisebox{-.75ex}{\char126}#1} 37 | \AtBeginDocument 38 | {\@ifundefined{url} 39 | {%url package is not loaded 40 | \let\url\ahref\let\oneurl\ahrefurl\let\footurl\footahref} 41 | {}} 42 | %% Void cutting instructions 43 | \newcounter{cuttingdepth} 44 | \newcommand{\tocnumber}{} 45 | \newcommand{\notocnumber}{} 46 | \newcommand{\cuttingunit}{} 47 | \newcommand{\cutdef}[2][]{} 48 | \newcommand{\cuthere}[2]{} 49 | \newcommand{\cutend}{} 50 | \newcommand{\htmlhead}[1]{} 51 | \newcommand{\htmlfoot}[1]{} 52 | \newcommand{\htmlprefix}[1]{} 53 | \newenvironment{cutflow}[1]{}{} 54 | \newcommand{\cutname}[1]{} 55 | \newcommand{\toplinks}[3]{} 56 | \newcommand{\setlinkstext}[3]{} 57 | \newcommand{\flushdef}[1]{} 58 | \newcommand{\footnoteflush}[1]{} 59 | %%%% Html only 60 | \excludecomment{rawhtml} 61 | \newcommand{\rawhtmlinput}[1]{} 62 | \excludecomment{htmlonly} 63 | %%%% Latex only 64 | \newenvironment{latexonly}{}{} 65 | \newenvironment{verblatex}{}{} 66 | %%%% Image file stuff 67 | \def\toimage{\endgroup} 68 | \def\endtoimage{\begingroup\def\@currenvir{toimage}} 69 | \def\verbimage{\endgroup} 70 | \def\endverbimage{\begingroup\def\@currenvir{verbimage}} 71 | \newcommand{\imageflush}[1][]{} 72 | %%% Bgcolor definition 73 | \newsavebox{\@bgcolorbin} 74 | \newenvironment{bgcolor}[2][] 75 | {\newcommand{\@mycolor}{#2}\begin{lrbox}{\@bgcolorbin}\vbox\bgroup} 76 | {\egroup\end{lrbox}% 77 | \begin{flushleft}% 78 | \colorbox{\@mycolor}{\usebox{\@bgcolorbin}}% 79 | \end{flushleft}} 80 | %%% Style sheets macros, defined as no-ops 81 | \newcommand{\newstyle}[2]{} 82 | \newcommand{\addstyle}[1]{} 83 | \newcommand{\setenvclass}[2]{} 84 | \newcommand{\getenvclass}[1]{} 85 | \newcommand{\loadcssfile}[1]{} 86 | \newenvironment{divstyle}[1]{}{} 87 | \newenvironment{cellstyle}[2]{}{} 88 | \newif\ifexternalcss 89 | %%% Postlude 90 | \makeatother 91 | -------------------------------------------------------------------------------- /book/htmlonly: -------------------------------------------------------------------------------- 1 | % put commands here that should be used for the HTML 2 | % version of the book but not Postscript or PDF 3 | 4 | \newcommand{\beforefig}{} 5 | \newcommand{\afterfig}{} 6 | 7 | \newcommand{\beforeverb}{\blue \large} 8 | \newcommand{\afterverb}{\black \normalsize} 9 | 10 | \newcommand{\adjustpage}[1]{} 11 | 12 | \newcommand{\clearemptydoublepage}{} 13 | \newcommand{\blankpage}{} 14 | 15 | \newcommand{\spacing}{} 16 | \newcommand{\endspacing}{} 17 | 18 | \newcommand{\frontmatter}{} 19 | \newcommand{\mainmatter}{} 20 | 21 | \newcommand{\theoremstyle}[1]{} 22 | \newcommand{\newtheoremstyle}[1]{} 23 | 24 | \newcommand{\vfill}{} 25 | 26 | \htmlhead{\rawhtmlinput{header.html}} 27 | 28 | \htmlfoot{\rawhtmlinput{footer.html}} -------------------------------------------------------------------------------- /book/kidney_table.tex: -------------------------------------------------------------------------------- 1 | \begin{tabular}{|r||r|r|r|r|r|} 2 | \hline 3 | Diameter & \multicolumn{5}{c|}{Percentiles of age} \\ 4 | (cm) & 5th & 25th & 50th & 75th & 95th \\ 5 | \hline 6 | 0.3 & 0.7 & 1.3 & 2.0 & 3.4 & 6.0 \\ 7 | 0.4 & 1.3 & 2.7 & 4.0 & 5.4 & 8.7 \\ 8 | 0.5 & 2.0 & 4.0 & 5.4 & 7.4 & 11.4 \\ 9 | 0.7 & 2.7 & 5.4 & 7.4 & 10.1 & 14.8 \\ 10 | 1.0 & 4.0 & 6.7 & 8.7 & 12.1 & 16.1 \\ 11 | 1.3 & 5.4 & 8.1 & 10.7 & 13.4 & 18.8 \\ 12 | 1.8 & 6.0 & 9.4 & 12.1 & 15.4 & 20.8 \\ 13 | 2.5 & 6.7 & 10.7 & 14.1 & 17.5 & 24.2 \\ 14 | 3.3 & 8.1 & 12.8 & 16.1 & 19.5 & 25.5 \\ 15 | 4.5 & 10.1 & 14.1 & 17.5 & 21.5 & 28.2 \\ 16 | 6.0 & 10.7 & 15.4 & 19.5 & 23.5 & 30.2 \\ 17 | 8.2 & 12.1 & 16.8 & 20.8 & 24.8 & 32.2 \\ 18 | 11.0 & 13.4 & 18.8 & 22.2 & 26.8 & 34.2 \\ 19 | 14.9 & 14.8 & 20.1 & 24.2 & 28.9 & 35.6 \\ 20 | \hline 21 | \end{tabular} 22 | -------------------------------------------------------------------------------- /book/kidney_table2.tex: -------------------------------------------------------------------------------- 1 | \begin{tabular}{|l|r||r|r|r|r|r|} 2 | \hline 3 | Serial & Diameter & \multicolumn{5}{c|}{Percentiles of age} \\ 4 | Correlation & (cm) & 5th & 25th & 50th & 75th & 95th \\ 5 | \hline 6 | 0.0 & 6.0 & 10.7 & 15.4 & 19.5 & 23.5 & 30.2 \\ 7 | 0.4 & 6.0 & 9.4 & 15.4 & 20.8 & 26.2 & 36.9 \\ 8 | \hline 9 | \end{tabular} 10 | -------------------------------------------------------------------------------- /book/latexonly: -------------------------------------------------------------------------------- 1 | \sloppy 2 | %\setlength{\topmargin}{-0.375in} 3 | %\setlength{\oddsidemargin}{0.0in} 4 | %\setlength{\evensidemargin}{0.0in} 5 | 6 | % Uncomment these to center on 8.5 x 11 7 | %\setlength{\topmargin}{0.625in} 8 | %\setlength{\oddsidemargin}{0.875in} 9 | %\setlength{\evensidemargin}{0.875in} 10 | 11 | %\setlength{\textheight}{7.2in} 12 | 13 | \setlength{\headsep}{3ex} 14 | \setlength{\parindent}{0.0in} 15 | \setlength{\parskip}{1.7ex plus 0.5ex minus 0.5ex} 16 | \renewcommand{\baselinestretch}{1.02} 17 | 18 | % see LaTeX Companion page 62 19 | \setlength{\topsep}{-0.0\parskip} 20 | \setlength{\partopsep}{-0.5\parskip} 21 | \setlength{\itemindent}{0.0in} 22 | \setlength{\listparindent}{0.0in} 23 | 24 | % see LaTeX Companion page 26 25 | % these are copied from /usr/local/teTeX/share/texmf/tex/latex/base/book.cls 26 | % all I changed is afterskip 27 | 28 | \makeatletter 29 | 30 | \renewcommand{\section}{\@startsection 31 | {section} {1} {0mm}% 32 | {-3.5ex \@plus -1ex \@minus -.2ex}% 33 | {0.7ex \@plus.2ex}% 34 | {\normalfont\Large\bfseries}} 35 | \renewcommand\subsection{\@startsection {subsection}{2}{0mm}% 36 | {-3.25ex\@plus -1ex \@minus -.2ex}% 37 | {0.3ex \@plus .2ex}% 38 | {\normalfont\large\bfseries}} 39 | \renewcommand\subsubsection{\@startsection {subsubsection}{3}{0mm}% 40 | {-3.25ex\@plus -1ex \@minus -.2ex}% 41 | {0.3ex \@plus .2ex}% 42 | {\normalfont\normalsize\bfseries}} 43 | 44 | % The following line adds a little extra space to the column 45 | % in which the Section numbers appear in the table of contents 46 | \renewcommand{\l@section}{\@dottedtocline{1}{1.5em}{3.0em}} 47 | \setcounter{tocdepth}{1} 48 | 49 | \makeatother 50 | 51 | \newcommand{\beforefig}{\vspace{1.3\parskip}} 52 | \newcommand{\afterfig}{\vspace{-0.2\parskip}} 53 | 54 | \newcommand{\beforeverb}{\vspace{0.6\parskip}} 55 | \newcommand{\afterverb}{\vspace{0.6\parskip}} 56 | 57 | \newcommand{\adjustpage}[1]{\enlargethispage{#1\baselineskip}} 58 | 59 | 60 | % Note: the following command seems to cause problems for Acroreader 61 | % on Windows, so for now I am overriding it. 62 | %\newcommand{\clearemptydoublepage}{ 63 | % \newpage{\pagestyle{empty}\cleardoublepage}} 64 | \newcommand{\clearemptydoublepage}{\cleardoublepage} 65 | 66 | %\newcommand{\blankpage}{\pagestyle{empty}\vspace*{1in}\newpage} 67 | \newcommand{\blankpage}{\vspace*{1in}\newpage} 68 | 69 | % HEADERS 70 | 71 | \renewcommand{\chaptermark}[1]{\markboth{#1}{}} 72 | \renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}{}} 73 | 74 | \lhead[\fancyplain{}{\bfseries\thepage}]% 75 | {\fancyplain{}{\bfseries\rightmark}} 76 | \rhead[\fancyplain{}{\bfseries\leftmark}]% 77 | {\fancyplain{}{\bfseries\thepage}} 78 | \cfoot{} 79 | 80 | \pagestyle{fancyplain} 81 | 82 | 83 | % turn off the rule under the header 84 | %\setlength{\headrulewidth}{0pt} 85 | 86 | % the following is a brute-force way to prevent the headers 87 | % from getting transformed into all-caps 88 | \renewcommand\MakeUppercase{} 89 | 90 | % Exercise environment 91 | \newtheoremstyle{myex}% name 92 | {9pt}% Space above 93 | {9pt}% Space below 94 | {}% Body font 95 | {}% Indent amount (empty = no indent, \parindent = para indent) 96 | {\bfseries}% Thm head font 97 | {}% Punctuation after thm head 98 | {0.5em}% Space after thm head: " " = normal interword space; 99 | % \newline = linebreak 100 | {}% Thm head spec (can be left empty, meaning `normal') 101 | 102 | \theoremstyle{myex} 103 | -------------------------------------------------------------------------------- /book/localdef.py: -------------------------------------------------------------------------------- 1 | import plasTeX.Base as Base 2 | 3 | def idgen(): 4 | """ Generate a unique ID """ 5 | i = 1 6 | while 1: 7 | yield 'a%.10d' % i 8 | i += 1 9 | 10 | idgen = idgen() 11 | 12 | class Eqn(Base.Command): 13 | args = 'self' 14 | 15 | class Anchor(Base.Command): 16 | args = 'label:str' 17 | def invoke(self, tex): 18 | Base.Command.invoke(self, tex) 19 | self.ownerDocument.context.label(self.attributes['label'], self) 20 | 21 | class exercise(Base.Environment): 22 | counter = 'exercise' 23 | 24 | class index(Base.Command): 25 | args = 'termstring' 26 | 27 | def setEntry(self, s, seetype=0): 28 | # TYPE_NORMAL = 0 29 | # TYPE_SEE = 1 30 | # TYPE_SEEALSO = 2 31 | if type(s) != type(''): 32 | s = s.textContent 33 | if s.count('!'): 34 | priterm, secterm = s.split('!') 35 | if priterm.count('@'): 36 | prisort, primary = priterm.split('@') 37 | else: 38 | prisort, primary = None, priterm 39 | if secterm.count('@'): 40 | secsort, secondary = secterm.split('@') 41 | else: 42 | secsort, secondary = None, secterm 43 | elif s.count('@'): 44 | prisort, primary = s.split('@') 45 | secsort, secondary = None, None 46 | else: 47 | prisort, primary = None, s 48 | secsort, secondary = None, None 49 | 50 | # if secondary: 51 | # self.ownerDocument.userdata.setdefault('index', []).append(\ 52 | # Base.IndexEntry([primary, secondary], self, [prisort, secsort], None, type=seetype)) 53 | # else: 54 | # self.ownerDocument.userdata.setdefault('index', []).append(\ 55 | # Base.IndexEntry([primary], self, [prisort], None, type=seetype)) 56 | return prisort, primary, secsort, secondary 57 | 58 | def invoke(self, tex): 59 | Base.Command.invoke(self, tex) 60 | self.ownerDocument.context.label(idgen.next(), self) 61 | p0,p1,s0,s1 = self.setEntry(self.attributes['termstring']) 62 | if p0: 63 | self.prisort = '%s' % p0 64 | if p1: 65 | self.primary = '%s' % p1 66 | if s0: 67 | self.secsort = '%s' % s0 68 | if s1: 69 | self.secondary = '%s' % s1 70 | 71 | class scriptN(Base.Command): 72 | unicode = u'\U0001D4A9' 73 | 74 | class uxbar(Base.Command): pass 75 | class uybar(Base.Command): pass 76 | class unhat(Base.Command): pass 77 | class ule(Base.Command): pass 78 | class minus(Base.Command): pass 79 | class lowast(Base.Command): pass 80 | class Erdos(Base.Command): pass 81 | 82 | -------------------------------------------------------------------------------- /book/macros.hva: -------------------------------------------------------------------------------- 1 | 2 | % RESPONSIVE HTML 3 | \let\oldmeta=\@meta 4 | \renewcommand{\@meta}{% 5 | \oldmeta 6 | \begin{rawhtml} 7 | 8 | \end{rawhtml}} 9 | 10 | -------------------------------------------------------------------------------- /book/next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/next.png -------------------------------------------------------------------------------- /book/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/book/up.png -------------------------------------------------------------------------------- /code/CDBRFS08.ASC.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AllenDowney/ThinkBayes/77eed00b89c8dadf01d674b8b8f5a8d4e7e9cd27/code/CDBRFS08.ASC.gz -------------------------------------------------------------------------------- /code/brfss.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Stats", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2010 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | import math 10 | import sys 11 | import survey 12 | import thinkstats 13 | 14 | 15 | class Respondents(survey.Table): 16 | """Represents the respondent table.""" 17 | 18 | def ReadRecords(self, data_dir='.', n=None): 19 | filename = self.GetFilename() 20 | self.ReadFile(data_dir, 21 | filename, 22 | self.GetFields(), 23 | survey.Respondent, 24 | n) 25 | self.Recode() 26 | 27 | def GetFilename(self): 28 | """Get the name of the data file. 29 | 30 | This function can be overridden by child classes. 31 | 32 | The BRFSS data is available from thinkstats.com/CDBRFS08.ASC.gz 33 | 34 | """ 35 | return 'CDBRFS08.ASC.gz' 36 | 37 | def GetFields(self): 38 | """Returns a tuple specifying the fields to extract. 39 | 40 | BRFSS codebook 41 | http://www.cdc.gov/brfss/technical_infodata/surveydata/2008.htm 42 | 43 | The elements of the tuple are field, start, end, case. 44 | 45 | field is the name of the variable 46 | start and end are the indices as specified in the NSFG docs 47 | case is a callable that converts the result to int, float, etc. 48 | """ 49 | return [ 50 | ('age', 101, 102, int), 51 | ('weight2', 119, 122, int), 52 | ('wtyrago', 127, 130, int), 53 | ('wtkg2', 1254, 1258, int), 54 | ('htm3', 1251, 1253, int), 55 | ('sex', 143, 143, int), 56 | ] 57 | 58 | def Recode(self): 59 | """Recode variables that need cleaning.""" 60 | 61 | def CleanWeight(weight): 62 | if weight in [7777, 9999, 'NA']: 63 | return 'NA' 64 | elif weight < 1000: 65 | return weight / 2.2 66 | elif 9000 < weight < 9999: 67 | return weight - 9000 68 | else: 69 | return weight 70 | 71 | for rec in self.records: 72 | # recode wtkg2 73 | if rec.wtkg2 in ['NA', 99999]: 74 | rec.wtkg2 = 'NA' 75 | else: 76 | rec.wtkg2 /= 100.0 77 | 78 | # recode wtyrago 79 | rec.weight2 = CleanWeight(rec.weight2) 80 | rec.wtyrago = CleanWeight(rec.wtyrago) 81 | 82 | # recode htm3 83 | if rec.htm3 == 999: 84 | rec.htm3 = 'NA' 85 | 86 | # recode age 87 | if rec.age in [7, 9]: 88 | rec.age = 'NA' 89 | 90 | 91 | def SummarizeHeight(self): 92 | """Print summary statistics for male and female height.""" 93 | 94 | # make a dictionary that maps from gender code to list of heights 95 | d = {1:[], 2:[], 'all':[]} 96 | [d[r.sex].append(r.htm3) for r in self.records if r.htm3 != 'NA'] 97 | [d['all'].append(r.htm3) for r in self.records if r.htm3 != 'NA'] 98 | 99 | print('Height (cm):') 100 | print('key n mean var sigma cv') 101 | for key, t in d.items(): 102 | mu, var = thinkstats.TrimmedMeanVar(t) 103 | sigma = math.sqrt(var) 104 | cv = sigma / mu 105 | print(key, len(t), mu, var, sigma, cv) 106 | 107 | return d 108 | 109 | def SummarizeWeight(self): 110 | """Print summary statistics for male and female weight.""" 111 | 112 | # make a dictionary that maps from gender code to list of weights 113 | d = {1:[], 2:[], 'all':[]} 114 | [d[r.sex].append(r.weight2) for r in self.records if r.weight2 != 'NA'] 115 | [d['all'].append(r.weight2) for r in self.records if r.weight2 != 'NA'] 116 | 117 | print('Weight (kg):') 118 | print('key n mean var sigma cv') 119 | for key, t in d.items(): 120 | mu, var = thinkstats.TrimmedMeanVar(t) 121 | sigma = math.sqrt(var) 122 | cv = sigma / mu 123 | print(key, len(t), mu, var, sigma, cv) 124 | 125 | 126 | def SummarizeWeightChange(self): 127 | """Print the mean reported change in weight in kg.""" 128 | 129 | data = [(r.weight2, r.wtyrago) for r in self.records 130 | if r.weight2 != 'NA' and r.wtyrago != 'NA'] 131 | 132 | changes = [(curr - prev) for curr, prev in data] 133 | 134 | print('Mean change', thinkstats.Mean(changes)) 135 | 136 | 137 | def main(name, data_dir='.'): 138 | resp = Respondents() 139 | resp.ReadRecords(data_dir) 140 | resp.SummarizeHeight() 141 | resp.SummarizeWeight() 142 | resp.SummarizeWeightChange() 143 | 144 | if __name__ == '__main__': 145 | main(*sys.argv) 146 | -------------------------------------------------------------------------------- /code/columns.py: -------------------------------------------------------------------------------- 1 | """This file contains code related to "Think Stats", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | 10 | import csv 11 | 12 | 13 | def read_csv(filename, constructor): 14 | """Reads a CSV file, returns the header line and a list of objects. 15 | 16 | filename: string filename 17 | """ 18 | fp = open(filename) 19 | reader = csv.reader(fp) 20 | 21 | header = next(reader) 22 | names = [s.lower() for s in header] 23 | 24 | objs = [make_object(t, names, constructor) for t in reader] 25 | fp.close() 26 | 27 | return objs 28 | 29 | 30 | def write_csv(filename, header, data): 31 | """Writes a CSV file 32 | 33 | filename: string filename 34 | header: list of strings 35 | data: list of rows 36 | """ 37 | fp = open(filename, 'w') 38 | writer = csv.writer(fp) 39 | writer.writerow(header) 40 | 41 | for t in data: 42 | writer.writerow(t) 43 | fp.close() 44 | 45 | 46 | def print_cols(cols): 47 | """Prints the index and first two elements for each column. 48 | 49 | cols: list of columns 50 | """ 51 | for i, col in enumerate(cols): 52 | print(i, col[0], col[1]) 53 | 54 | 55 | def make_col_dict(cols, names): 56 | """Selects columns from a dataset and returns a map from name to column. 57 | 58 | cols: list of columns 59 | names: list of names 60 | """ 61 | col_dict = {} 62 | for name, col in zip(names, cols): 63 | col_dict[name] = col 64 | return col_dict 65 | 66 | 67 | def make_object(row, names, constructor): 68 | """Turns a row of values into an object. 69 | 70 | row: row of values 71 | names: list of attribute names 72 | constructor: function that makes the objects 73 | 74 | Returns: new object 75 | """ 76 | obj = constructor() 77 | for name, val in zip(names, row): 78 | func = constructor.convert.get(name, int) 79 | try: 80 | val = func(val) 81 | except: 82 | pass 83 | setattr(obj, name, val) 84 | obj.clean() 85 | return obj 86 | 87 | -------------------------------------------------------------------------------- /code/cookie.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | from thinkbayes import Pmf 10 | 11 | pmf = Pmf() 12 | pmf.Set('Bowl 1', 0.5) 13 | pmf.Set('Bowl 2', 0.5) 14 | 15 | pmf.Mult('Bowl 1', 0.75) 16 | pmf.Mult('Bowl 2', 0.5) 17 | 18 | pmf.Normalize() 19 | 20 | print(pmf.Prob('Bowl 1')) 21 | -------------------------------------------------------------------------------- /code/cookie2.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | from thinkbayes import Pmf 10 | 11 | 12 | class Cookie(Pmf): 13 | """A map from string bowl ID to probablity.""" 14 | 15 | def __init__(self, hypos): 16 | """Initialize self. 17 | 18 | hypos: sequence of string bowl IDs 19 | """ 20 | Pmf.__init__(self) 21 | for hypo in hypos: 22 | self.Set(hypo, 1) 23 | self.Normalize() 24 | 25 | def Update(self, data): 26 | """Updates the PMF with new data. 27 | 28 | data: string cookie type 29 | """ 30 | for hypo in self.Values(): 31 | like = self.Likelihood(data, hypo) 32 | self.Mult(hypo, like) 33 | self.Normalize() 34 | 35 | mixes = { 36 | 'Bowl 1':dict(vanilla=0.75, chocolate=0.25), 37 | 'Bowl 2':dict(vanilla=0.5, chocolate=0.5), 38 | } 39 | 40 | def Likelihood(self, data, hypo): 41 | """The likelihood of the data under the hypothesis. 42 | 43 | data: string cookie type 44 | hypo: string bowl ID 45 | """ 46 | mix = self.mixes[hypo] 47 | like = mix[data] 48 | return like 49 | 50 | 51 | def main(): 52 | hypos = ['Bowl 1', 'Bowl 2'] 53 | 54 | pmf = Cookie(hypos) 55 | 56 | pmf.Update('vanilla') 57 | 58 | for hypo, prob in pmf.Items(): 59 | print(hypo, prob) 60 | 61 | 62 | if __name__ == '__main__': 63 | main() 64 | -------------------------------------------------------------------------------- /code/correlation.py: -------------------------------------------------------------------------------- 1 | """This file contains code used in "Think Stats", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2010 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | import math 10 | import random 11 | 12 | import thinkstats 13 | 14 | 15 | def Cov(xs, ys, mux=None, muy=None): 16 | """Computes Cov(X, Y). 17 | 18 | Args: 19 | xs: sequence of values 20 | ys: sequence of values 21 | mux: optional float mean of xs 22 | muy: optional float mean of ys 23 | 24 | Returns: 25 | Cov(X, Y) 26 | """ 27 | if mux is None: 28 | mux = thinkstats.Mean(xs) 29 | if muy is None: 30 | muy = thinkstats.Mean(ys) 31 | 32 | total = 0.0 33 | for x, y in zip(xs, ys): 34 | total += (x-mux) * (y-muy) 35 | 36 | return total / len(xs) 37 | 38 | 39 | def Corr(xs, ys): 40 | """Computes Corr(X, Y). 41 | 42 | Args: 43 | xs: sequence of values 44 | ys: sequence of values 45 | 46 | Returns: 47 | Corr(X, Y) 48 | """ 49 | xbar, varx = thinkstats.MeanVar(xs) 50 | ybar, vary = thinkstats.MeanVar(ys) 51 | 52 | corr = Cov(xs, ys, xbar, ybar) / math.sqrt(varx * vary) 53 | 54 | return corr 55 | 56 | 57 | def SerialCorr(xs): 58 | """Computes the serial correlation of a sequence.""" 59 | return Corr(xs[:-1], xs[1:]) 60 | 61 | 62 | def SpearmanCorr(xs, ys): 63 | """Computes Spearman's rank correlation. 64 | 65 | Args: 66 | xs: sequence of values 67 | ys: sequence of values 68 | 69 | Returns: 70 | float Spearman's correlation 71 | """ 72 | xranks = MapToRanks(xs) 73 | yranks = MapToRanks(ys) 74 | return Corr(xranks, yranks) 75 | 76 | 77 | def LeastSquares(xs, ys): 78 | """Computes a linear least squares fit for ys as a function of xs. 79 | 80 | Args: 81 | xs: sequence of values 82 | ys: sequence of values 83 | 84 | Returns: 85 | tuple of (intercept, slope) 86 | """ 87 | xbar, varx = thinkstats.MeanVar(xs) 88 | ybar, vary = thinkstats.MeanVar(ys) 89 | 90 | slope = Cov(xs, ys, xbar, ybar) / varx 91 | inter = ybar - slope * xbar 92 | 93 | return inter, slope 94 | 95 | 96 | def FitLine(xs, inter, slope): 97 | """Returns the fitted line for the range of xs. 98 | 99 | xs: x values used for the fit 100 | slope: estimated slope 101 | inter: estimated intercept 102 | """ 103 | fxs = min(xs), max(xs) 104 | fys = [x * slope + inter for x in fxs] 105 | return fxs, fys 106 | 107 | 108 | def Residuals(xs, ys, inter, slope): 109 | """Computes residuals for a linear fit with parameters inter and slope. 110 | 111 | Args: 112 | xs: independent variable 113 | ys: dependent variable 114 | inter: float intercept 115 | slope: float slope 116 | 117 | Returns: 118 | list of residuals 119 | """ 120 | res = [y - inter - slope*x for x, y in zip(xs, ys)] 121 | return res 122 | 123 | 124 | def CoefDetermination(ys, res): 125 | """Computes the coefficient of determination (R^2) for given residuals. 126 | 127 | Args: 128 | ys: dependent variable 129 | res: residuals 130 | 131 | Returns: 132 | float coefficient of determination 133 | """ 134 | ybar, vary = thinkstats.MeanVar(ys) 135 | resbar, varres = thinkstats.MeanVar(res) 136 | return 1 - varres / vary 137 | 138 | 139 | def MapToRanks(t): 140 | """Returns a list of ranks corresponding to the elements in t. 141 | 142 | Args: 143 | t: sequence of numbers 144 | 145 | Returns: 146 | list of integer ranks, starting at 1 147 | """ 148 | # pair up each value with its index 149 | pairs = enumerate(t) 150 | 151 | # sort by value 152 | sorted_pairs = sorted(pairs, key=lambda pair: pair[1]) 153 | 154 | # pair up each pair with its rank 155 | ranked = enumerate(sorted_pairs) 156 | 157 | # sort by index 158 | resorted = sorted(ranked, key=lambda trip: trip[1][0]) 159 | 160 | # extract the ranks 161 | ranks = [trip[0]+1 for trip in resorted] 162 | return ranks 163 | 164 | 165 | def CorrelatedGenerator(rho): 166 | """Generates standard normal variates with correlation. 167 | 168 | rho: target coefficient of correlation 169 | 170 | Returns: iterable 171 | """ 172 | x = random.gauss(0, 1) 173 | yield x 174 | 175 | sigma = math.sqrt(1 - rho**2) 176 | while True: 177 | x = random.gauss(x * rho, sigma) 178 | yield x 179 | 180 | 181 | def CorrelatedNormalGenerator(mu, sigma, rho): 182 | """Generates normal variates with correlation. 183 | 184 | mu: mean of variate 185 | sigma: standard deviation of variate 186 | rho: target coefficient of correlation 187 | 188 | Returns: iterable 189 | """ 190 | for x in CorrelatedGenerator(rho): 191 | yield x * sigma + mu 192 | 193 | 194 | def main(): 195 | pass 196 | 197 | 198 | if __name__ == '__main__': 199 | main() 200 | -------------------------------------------------------------------------------- /code/dice.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | from thinkbayes import Suite 10 | 11 | 12 | class Dice(Suite): 13 | """Represents hypotheses about which die was rolled.""" 14 | 15 | def Likelihood(self, data, hypo): 16 | """Computes the likelihood of the data under the hypothesis. 17 | 18 | hypo: integer number of sides on the die 19 | data: integer die roll 20 | """ 21 | if hypo < data: 22 | return 0 23 | else: 24 | return 1.0/hypo 25 | 26 | 27 | def main(): 28 | suite = Dice([4, 6, 8, 12, 20]) 29 | 30 | suite.Update(6) 31 | print('After one 6') 32 | suite.Print() 33 | 34 | for roll in [4, 8, 7, 7, 2]: 35 | suite.Update(roll) 36 | 37 | print('After more rolls') 38 | suite.Print() 39 | 40 | 41 | if __name__ == '__main__': 42 | main() 43 | -------------------------------------------------------------------------------- /code/dungeons.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | import random 10 | 11 | import thinkbayes 12 | import thinkplot 13 | 14 | FORMATS = ['pdf', 'eps', 'png'] 15 | 16 | 17 | class Die(thinkbayes.Pmf): 18 | """Represents the PMF of outcomes for a die.""" 19 | 20 | def __init__(self, sides, name=''): 21 | """Initializes the die. 22 | 23 | sides: int number of sides 24 | name: string 25 | """ 26 | thinkbayes.Pmf.__init__(self, name=name) 27 | for x in range(1, sides+1): 28 | self.Set(x, 1) 29 | self.Normalize() 30 | 31 | 32 | def PmfMax(pmf1, pmf2): 33 | """Computes the distribution of the max of values drawn from two Pmfs. 34 | 35 | pmf1, pmf2: Pmf objects 36 | 37 | returns: new Pmf 38 | """ 39 | res = thinkbayes.Pmf() 40 | for v1, p1 in pmf1.Items(): 41 | for v2, p2 in pmf2.Items(): 42 | res.Incr(max(v1, v2), p1*p2) 43 | return res 44 | 45 | 46 | def main(): 47 | pmf_dice = thinkbayes.Pmf() 48 | pmf_dice.Set(Die(4), 5) 49 | pmf_dice.Set(Die(6), 4) 50 | pmf_dice.Set(Die(8), 3) 51 | pmf_dice.Set(Die(12), 2) 52 | pmf_dice.Set(Die(20), 1) 53 | pmf_dice.Normalize() 54 | 55 | mix = thinkbayes.Pmf() 56 | for die, weight in pmf_dice.Items(): 57 | for outcome, prob in die.Items(): 58 | mix.Incr(outcome, weight*prob) 59 | 60 | mix = thinkbayes.MakeMixture(pmf_dice) 61 | 62 | thinkplot.Hist(mix, width=0.9) 63 | thinkplot.Save(root='dungeons3', 64 | xlabel='Outcome', 65 | ylabel='Probability', 66 | formats=FORMATS) 67 | 68 | random.seed(17) 69 | 70 | d6 = Die(6, 'd6') 71 | 72 | dice = [d6] * 3 73 | three = thinkbayes.SampleSum(dice, 1000) 74 | three.name = 'sample' 75 | three.Print() 76 | 77 | three_exact = d6 + d6 + d6 78 | three_exact.name = 'exact' 79 | three_exact.Print() 80 | 81 | thinkplot.PrePlot(num=2) 82 | thinkplot.Pmf(three) 83 | thinkplot.Pmf(three_exact, linestyle='dashed') 84 | thinkplot.Save(root='dungeons1', 85 | xlabel='Sum of three d6', 86 | ylabel='Probability', 87 | axis=[2, 19, 0, 0.15], 88 | formats=FORMATS) 89 | 90 | thinkplot.Clf() 91 | thinkplot.PrePlot(num=1) 92 | 93 | # compute the distribution of the best attribute the hard way 94 | best_attr2 = PmfMax(three_exact, three_exact) 95 | best_attr4 = PmfMax(best_attr2, best_attr2) 96 | best_attr6 = PmfMax(best_attr4, best_attr2) 97 | # thinkplot.Pmf(best_attr6) 98 | 99 | # and the easy way 100 | best_attr_cdf = three_exact.Max(6) 101 | best_attr_cdf.name = '' 102 | best_attr_pmf = thinkbayes.MakePmfFromCdf(best_attr_cdf) 103 | best_attr_pmf.Print() 104 | 105 | thinkplot.Pmf(best_attr_pmf) 106 | thinkplot.Save(root='dungeons2', 107 | xlabel='Best of three d6', 108 | ylabel='Probability', 109 | axis=[2, 19, 0, 0.23], 110 | formats=FORMATS) 111 | 112 | 113 | 114 | if __name__ == '__main__': 115 | main() 116 | -------------------------------------------------------------------------------- /code/euro.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | """This file contains a partial solution to a problem from 10 | MacKay, "Information Theory, Inference, and Learning Algorithms." 11 | 12 | Exercise 3.15 (page 50): A statistical statement appeared in 13 | "The Guardian" on Friday January 4, 2002: 14 | 15 | When spun on edge 250 times, a Belgian one-euro coin came 16 | up heads 140 times and tails 110. 'It looks very suspicious 17 | to me,' said Barry Blight, a statistics lecturer at the London 18 | School of Economics. 'If the coin were unbiased, the chance of 19 | getting a result as extreme as that would be less than 7%.' 20 | 21 | MacKay asks, "But do these data give evidence that the coin is biased 22 | rather than fair?" 23 | 24 | """ 25 | 26 | import thinkbayes 27 | import thinkplot 28 | 29 | 30 | class Euro(thinkbayes.Suite): 31 | """Represents hypotheses about the probability of heads.""" 32 | 33 | def Likelihood(self, data, hypo): 34 | """Computes the likelihood of the data under the hypothesis. 35 | 36 | hypo: integer value of x, the probability of heads (0-100) 37 | data: string 'H' or 'T' 38 | """ 39 | x = hypo / 100.0 40 | if data == 'H': 41 | return x 42 | else: 43 | return 1-x 44 | 45 | 46 | class Euro2(thinkbayes.Suite): 47 | """Represents hypotheses about the probability of heads.""" 48 | 49 | def Likelihood(self, data, hypo): 50 | """Computes the likelihood of the data under the hypothesis. 51 | 52 | hypo: integer value of x, the probability of heads (0-100) 53 | data: tuple of (number of heads, number of tails) 54 | """ 55 | x = hypo / 100.0 56 | heads, tails = data 57 | like = x**heads * (1-x)**tails 58 | return like 59 | 60 | 61 | def UniformPrior(): 62 | """Makes a Suite with a uniform prior.""" 63 | suite = Euro(range(0, 101)) 64 | return suite 65 | 66 | 67 | def TrianglePrior(): 68 | """Makes a Suite with a triangular prior.""" 69 | suite = Euro() 70 | for x in range(0, 51): 71 | suite.Set(x, x) 72 | for x in range(51, 101): 73 | suite.Set(x, 100-x) 74 | suite.Normalize() 75 | return suite 76 | 77 | 78 | def RunUpdate(suite, heads=140, tails=110): 79 | """Updates the Suite with the given number of heads and tails. 80 | 81 | suite: Suite object 82 | heads: int 83 | tails: int 84 | """ 85 | dataset = 'H' * heads + 'T' * tails 86 | 87 | for data in dataset: 88 | suite.Update(data) 89 | 90 | 91 | def Summarize(suite): 92 | """Prints summary statistics for the suite.""" 93 | print(suite.Prob(50)) 94 | 95 | print('MLE', suite.MaximumLikelihood()) 96 | 97 | print('Mean', suite.Mean()) 98 | print('Median', thinkbayes.Percentile(suite, 50)) 99 | 100 | print('5th %ile', thinkbayes.Percentile(suite, 5)) 101 | print('95th %ile', thinkbayes.Percentile(suite, 95)) 102 | 103 | print('CI', thinkbayes.CredibleInterval(suite, 90)) 104 | 105 | 106 | def PlotSuites(suites, root): 107 | """Plots two suites. 108 | 109 | suite1, suite2: Suite objects 110 | root: string filename to write 111 | """ 112 | thinkplot.Clf() 113 | thinkplot.PrePlot(len(suites)) 114 | thinkplot.Pmfs(suites) 115 | 116 | thinkplot.Save(root=root, 117 | xlabel='x', 118 | ylabel='Probability', 119 | formats=['pdf', 'eps']) 120 | 121 | 122 | def main(): 123 | # make the priors 124 | suite1 = UniformPrior() 125 | suite1.name = 'uniform' 126 | 127 | suite2 = TrianglePrior() 128 | suite2.name = 'triangle' 129 | 130 | # plot the priors 131 | PlotSuites([suite1, suite2], 'euro2') 132 | 133 | # update 134 | RunUpdate(suite1) 135 | Summarize(suite1) 136 | 137 | RunUpdate(suite2) 138 | Summarize(suite2) 139 | 140 | # plot the posteriors 141 | PlotSuites([suite1], 'euro1') 142 | PlotSuites([suite1, suite2], 'euro3') 143 | 144 | 145 | if __name__ == '__main__': 146 | main() 147 | -------------------------------------------------------------------------------- /code/euro2.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | """This file contains a partial solution to a problem from 10 | MacKay, "Information Theory, Inference, and Learning Algorithms." 11 | 12 | Exercise 3.15 (page 50): A statistical statement appeared in 13 | "The Guardian" on Friday January 4, 2002: 14 | 15 | When spun on edge 250 times, a Belgian one-euro coin came 16 | up heads 140 times and tails 110. 'It looks very suspicious 17 | to me,' said Barry Blight, a statistics lecturer at the London 18 | School of Economics. 'If the coin were unbiased, the chance of 19 | getting a result as extreme as that would be less than 7%.' 20 | 21 | MacKay asks, "But do these data give evidence that the coin is biased 22 | rather than fair?" 23 | 24 | """ 25 | 26 | import thinkbayes 27 | import thinkplot 28 | 29 | 30 | class Euro(thinkbayes.Suite): 31 | """Represents hypotheses about the probability of heads.""" 32 | 33 | def Likelihood(self, data, hypo): 34 | """Computes the likelihood of the data under the hypothesis. 35 | 36 | hypo: integer value of x, the probability of heads (0-100) 37 | data: string 'H' or 'T' 38 | """ 39 | x = hypo / 100.0 40 | if data == 'H': 41 | return x 42 | else: 43 | return 1-x 44 | 45 | 46 | class Euro2(thinkbayes.Suite): 47 | """Represents hypotheses about the probability of heads.""" 48 | 49 | def Likelihood(self, data, hypo): 50 | """Computes the likelihood of the data under the hypothesis. 51 | 52 | hypo: integer value of x, the probability of heads (0-100) 53 | data: tuple of (number of heads, number of tails) 54 | """ 55 | x = hypo / 100.0 56 | heads, tails = data 57 | like = x**heads * (1-x)**tails 58 | return like 59 | 60 | 61 | def Version1(): 62 | suite = Euro(range(0, 101)) 63 | heads, tails = 140, 110 64 | dataset = 'H' * heads + 'T' * tails 65 | 66 | for data in dataset: 67 | suite.Update(data) 68 | 69 | return suite 70 | 71 | 72 | def Version2(): 73 | suite = Euro(range(0, 101)) 74 | heads, tails = 140, 110 75 | dataset = 'H' * heads + 'T' * tails 76 | 77 | suite.UpdateSet(dataset) 78 | return suite 79 | 80 | 81 | def Version3(): 82 | suite = Euro2(range(0, 101)) 83 | heads, tails = 140, 110 84 | 85 | suite.Update((heads, tails)) 86 | return suite 87 | 88 | 89 | def main(): 90 | 91 | suite = Version3() 92 | print(suite.Mean()) 93 | 94 | thinkplot.Pmf(suite) 95 | thinkplot.Show() 96 | 97 | 98 | 99 | if __name__ == '__main__': 100 | main() 101 | -------------------------------------------------------------------------------- /code/euro3.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | """This file contains a partial solution to a problem from 10 | MacKay, "Information Theory, Inference, and Learning Algorithms." 11 | 12 | Exercise 3.15 (page 50): A statistical statement appeared in 13 | "The Guardian" on Friday January 4, 2002: 14 | 15 | When spun on edge 250 times, a Belgian one-euro coin came 16 | up heads 140 times and tails 110. 'It looks very suspicious 17 | to me,' said Barry Blight, a statistics lecturer at the London 18 | School of Economics. 'If the coin were unbiased, the chance of 19 | getting a result as extreme as that would be less than 7%.' 20 | 21 | MacKay asks, "But do these data give evidence that the coin is biased 22 | rather than fair?" 23 | 24 | """ 25 | 26 | import thinkbayes 27 | 28 | 29 | class Euro(thinkbayes.Suite): 30 | """Represents hypotheses about the probability of heads.""" 31 | 32 | def Likelihood(self, data, hypo): 33 | """Computes the likelihood of the data under the hypothesis. 34 | 35 | hypo: integer value of x, the probability of heads (0-100) 36 | data: tuple of (number of heads, number of tails) 37 | """ 38 | x = hypo / 100.0 39 | heads, tails = data 40 | like = x**heads * (1-x)**tails 41 | return like 42 | 43 | 44 | def TrianglePrior(): 45 | """Makes a Suite with a triangular prior.""" 46 | suite = Euro() 47 | for x in range(0, 51): 48 | suite.Set(x, x) 49 | for x in range(51, 101): 50 | suite.Set(x, 100-x) 51 | suite.Normalize() 52 | return suite 53 | 54 | 55 | def SuiteLikelihood(suite, data): 56 | """Computes the weighted average of likelihoods for sub-hypotheses. 57 | 58 | suite: Suite that maps sub-hypotheses to probability 59 | data: some representation of the data 60 | 61 | returns: float likelihood 62 | """ 63 | total = 0 64 | for hypo, prob in suite.Items(): 65 | like = suite.Likelihood(data, hypo) 66 | total += prob * like 67 | return total 68 | 69 | 70 | def Main(): 71 | data = 140, 110 72 | data = 8, 12 73 | 74 | suite = Euro() 75 | like_f = suite.Likelihood(data, 50) 76 | print('p(D|F)', like_f) 77 | 78 | actual_percent = 100.0 * 140 / 250 79 | likelihood = suite.Likelihood(data, actual_percent) 80 | print('p(D|B_cheat)', likelihood) 81 | print('p(D|B_cheat) / p(D|F)', likelihood / like_f) 82 | 83 | like40 = suite.Likelihood(data, 40) 84 | like60 = suite.Likelihood(data, 60) 85 | likelihood = 0.5 * like40 + 0.5 * like60 86 | print('p(D|B_two)', likelihood) 87 | print('p(D|B_two) / p(D|F)', likelihood / like_f) 88 | 89 | b_uniform = Euro(range(0, 101)) 90 | b_uniform.Remove(50) 91 | b_uniform.Normalize() 92 | likelihood = SuiteLikelihood(b_uniform, data) 93 | print('p(D|B_uniform)', likelihood) 94 | print('p(D|B_uniform) / p(D|F)', likelihood / like_f) 95 | 96 | b_tri = TrianglePrior() 97 | b_tri.Remove(50) 98 | b_tri.Normalize() 99 | likelihood = b_tri.Update(data) 100 | print('p(D|B_tri)', likelihood) 101 | print('p(D|B_tri) / p(D|F)', likelihood / like_f) 102 | 103 | 104 | if __name__ == '__main__': 105 | Main() 106 | -------------------------------------------------------------------------------- /code/hockey.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | import math 10 | 11 | import columns 12 | import thinkbayes 13 | import thinkstats 14 | import thinkplot 15 | 16 | 17 | USE_SUMMARY_DATA = True 18 | 19 | class Hockey(thinkbayes.Suite): 20 | """Represents hypotheses about the scoring rate for a team.""" 21 | 22 | def __init__(self, name=''): 23 | """Initializes the Hockey object. 24 | 25 | name: string 26 | """ 27 | if USE_SUMMARY_DATA: 28 | # prior based on each team's average goals scored 29 | mu = 2.8 30 | sigma = 0.3 31 | else: 32 | # prior based on each pair-wise match-up 33 | mu = 2.8 34 | sigma = 0.85 35 | 36 | pmf = thinkbayes.MakeGaussianPmf(mu, sigma, 4) 37 | thinkbayes.Suite.__init__(self, pmf, name=name) 38 | 39 | def Likelihood(self, data, hypo): 40 | """Computes the likelihood of the data under the hypothesis. 41 | 42 | Evaluates the Poisson PMF for lambda and k. 43 | 44 | hypo: goal scoring rate in goals per game 45 | data: goals scored in one period 46 | """ 47 | lam = hypo 48 | k = data 49 | like = thinkbayes.EvalPoissonPmf(k, lam) 50 | return like 51 | 52 | 53 | def MakeGoalPmf(suite, high=10): 54 | """Makes the distribution of goals scored, given distribution of lam. 55 | 56 | suite: distribution of goal-scoring rate 57 | high: upper bound 58 | 59 | returns: Pmf of goals per game 60 | """ 61 | metapmf = thinkbayes.Pmf() 62 | 63 | for lam, prob in suite.Items(): 64 | pmf = thinkbayes.MakePoissonPmf(lam, high) 65 | metapmf.Set(pmf, prob) 66 | 67 | mix = thinkbayes.MakeMixture(metapmf, name=suite.name) 68 | return mix 69 | 70 | 71 | def MakeGoalTimePmf(suite): 72 | """Makes the distribution of time til first goal. 73 | 74 | suite: distribution of goal-scoring rate 75 | 76 | returns: Pmf of goals per game 77 | """ 78 | metapmf = thinkbayes.Pmf() 79 | 80 | for lam, prob in suite.Items(): 81 | pmf = thinkbayes.MakeExponentialPmf(lam, high=2, n=2001) 82 | metapmf.Set(pmf, prob) 83 | 84 | mix = thinkbayes.MakeMixture(metapmf, name=suite.name) 85 | return mix 86 | 87 | 88 | class Game(object): 89 | """Represents a game. 90 | 91 | Attributes are set in columns.read_csv. 92 | """ 93 | convert = dict() 94 | 95 | def clean(self): 96 | self.goals = self.pd1 + self.pd2 + self.pd3 97 | 98 | 99 | def ReadHockeyData(filename='hockey_data.csv'): 100 | """Read game scores from the data file. 101 | 102 | filename: string 103 | """ 104 | game_list = columns.read_csv(filename, Game) 105 | 106 | # map from gameID to list of two games 107 | games = {} 108 | for game in game_list: 109 | if game.season != 2011: 110 | continue 111 | key = game.game 112 | games.setdefault(key, []).append(game) 113 | 114 | # map from (team1, team2) to (score1, score2) 115 | pairs = {} 116 | for key, pair in games.items(): 117 | t1, t2 = pair 118 | key = t1.team, t2.team 119 | entry = t1.total, t2.total 120 | pairs.setdefault(key, []).append(entry) 121 | 122 | ProcessScoresTeamwise(pairs) 123 | ProcessScoresPairwise(pairs) 124 | 125 | 126 | def ProcessScoresPairwise(pairs): 127 | """Average number of goals for each team against each opponent. 128 | 129 | pairs: map from (team1, team2) to (score1, score2) 130 | """ 131 | # map from (team1, team2) to list of goals scored 132 | goals_scored = {} 133 | for key, entries in pairs.items(): 134 | t1, t2 = key 135 | for entry in entries: 136 | g1, g2 = entry 137 | goals_scored.setdefault((t1, t2), []).append(g1) 138 | goals_scored.setdefault((t2, t1), []).append(g2) 139 | 140 | # make a list of average goals scored 141 | lams = [] 142 | for key, goals in goals_scored.items(): 143 | if len(goals) < 3: 144 | continue 145 | lam = thinkstats.Mean(goals) 146 | lams.append(lam) 147 | 148 | # make the distribution of average goals scored 149 | cdf = thinkbayes.MakeCdfFromList(lams) 150 | thinkplot.Cdf(cdf) 151 | thinkplot.Show() 152 | 153 | mu, var = thinkstats.MeanVar(lams) 154 | print('mu, sig', mu, math.sqrt(var)) 155 | 156 | print('BOS v VAN', pairs['BOS', 'VAN']) 157 | 158 | 159 | def ProcessScoresTeamwise(pairs): 160 | """Average number of goals for each team. 161 | 162 | pairs: map from (team1, team2) to (score1, score2) 163 | """ 164 | # map from team to list of goals scored 165 | goals_scored = {} 166 | for key, entries in pairs.items(): 167 | t1, t2 = key 168 | for entry in entries: 169 | g1, g2 = entry 170 | goals_scored.setdefault(t1, []).append(g1) 171 | goals_scored.setdefault(t2, []).append(g2) 172 | 173 | # make a list of average goals scored 174 | lams = [] 175 | for key, goals in goals_scored.items(): 176 | lam = thinkstats.Mean(goals) 177 | lams.append(lam) 178 | 179 | # make the distribution of average goals scored 180 | cdf = thinkbayes.MakeCdfFromList(lams) 181 | thinkplot.Cdf(cdf) 182 | thinkplot.Show() 183 | 184 | mu, var = thinkstats.MeanVar(lams) 185 | print('mu, sig', mu, math.sqrt(var)) 186 | 187 | 188 | def main(): 189 | #ReadHockeyData() 190 | #return 191 | 192 | formats = ['pdf', 'eps'] 193 | 194 | suite1 = Hockey('bruins') 195 | suite2 = Hockey('canucks') 196 | 197 | thinkplot.Clf() 198 | thinkplot.PrePlot(num=2) 199 | thinkplot.Pmf(suite1) 200 | thinkplot.Pmf(suite2) 201 | thinkplot.Save(root='hockey0', 202 | xlabel='Goals per game', 203 | ylabel='Probability', 204 | formats=formats) 205 | 206 | suite1.UpdateSet([0, 2, 8, 4]) 207 | suite2.UpdateSet([1, 3, 1, 0]) 208 | 209 | thinkplot.Clf() 210 | thinkplot.PrePlot(num=2) 211 | thinkplot.Pmf(suite1) 212 | thinkplot.Pmf(suite2) 213 | thinkplot.Save(root='hockey1', 214 | xlabel='Goals per game', 215 | ylabel='Probability', 216 | formats=formats) 217 | 218 | 219 | goal_dist1 = MakeGoalPmf(suite1) 220 | goal_dist2 = MakeGoalPmf(suite2) 221 | 222 | thinkplot.Clf() 223 | thinkplot.PrePlot(num=2) 224 | thinkplot.Pmf(goal_dist1) 225 | thinkplot.Pmf(goal_dist2) 226 | thinkplot.Save(root='hockey2', 227 | xlabel='Goals', 228 | ylabel='Probability', 229 | formats=formats) 230 | 231 | time_dist1 = MakeGoalTimePmf(suite1) 232 | time_dist2 = MakeGoalTimePmf(suite2) 233 | 234 | print('MLE bruins', suite1.MaximumLikelihood()) 235 | print('MLE canucks', suite2.MaximumLikelihood()) 236 | 237 | thinkplot.Clf() 238 | thinkplot.PrePlot(num=2) 239 | thinkplot.Pmf(time_dist1) 240 | thinkplot.Pmf(time_dist2) 241 | thinkplot.Save(root='hockey3', 242 | xlabel='Games until goal', 243 | ylabel='Probability', 244 | formats=formats) 245 | 246 | diff = goal_dist1 - goal_dist2 247 | p_win = diff.ProbGreater(0) 248 | p_loss = diff.ProbLess(0) 249 | p_tie = diff.Prob(0) 250 | 251 | print(p_win, p_loss, p_tie) 252 | 253 | p_overtime = thinkbayes.PmfProbLess(time_dist1, time_dist2) 254 | p_adjust = thinkbayes.PmfProbEqual(time_dist1, time_dist2) 255 | p_overtime += p_adjust / 2 256 | print('p_overtime', p_overtime) 257 | 258 | print(p_overtime * p_tie) 259 | p_win += p_overtime * p_tie 260 | print('p_win', p_win) 261 | 262 | # win the next two 263 | p_series = p_win**2 264 | 265 | # split the next two, win the third 266 | p_series += 2 * p_win * (1-p_win) * p_win 267 | 268 | print('p_series', p_series) 269 | 270 | 271 | if __name__ == '__main__': 272 | main() 273 | -------------------------------------------------------------------------------- /code/jaynes.py: -------------------------------------------------------------------------------- 1 | """This file contains code used in "Think Stats", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2013 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | import thinkbayes 10 | import thinkplot 11 | 12 | from math import exp 13 | 14 | """This file contains a solution to an exercise from Think Bayes, 15 | by Allen B. Downey 16 | 17 | I got the idea from Tom Campbell-Ricketts author of the Maximum 18 | Entropy blog at 19 | 20 | http://maximum-entropy-blog.blogspot.com 21 | 22 | And he got the idea from E.T. Jaynes, author of the classic 23 | _Probability Theory: The Logic of Science_. 24 | 25 | Here's the version from Think Bayes: 26 | 27 | Radioactive decay is well modeled by a Poisson process; the 28 | probability that an atom decays is the same at any point in time. 29 | 30 | Suppose that a radioactive source emits particles toward a Geiger 31 | counter at an average rate of $r$ particles per second, but the 32 | counter only registers a fraction, $f$, of the particles that hit it. 33 | If $f$ is 10\% and the counter registers 15 particles in a one second 34 | interval, what is the posterior distribution of $n$, the actual number 35 | of particles that hit the counter, and $p$, the average rate particles 36 | are emitted? 37 | 38 | """ 39 | 40 | FORMATS = ['pdf', 'eps', 'png'] 41 | 42 | class Emitter(thinkbayes.Suite): 43 | """Represents hypotheses about r.""" 44 | 45 | def __init__(self, rs, f=0.1): 46 | """Initializes the Suite. 47 | 48 | rs: sequence of hypothetical emission rates 49 | f: fraction of particles registered 50 | """ 51 | detectors = [Detector(r, f) for r in rs] 52 | thinkbayes.Suite.__init__(self, detectors) 53 | 54 | def Update(self, data): 55 | """Updates the Suite based on data. 56 | 57 | data: number of particles counted 58 | """ 59 | thinkbayes.Suite.Update(self, data) 60 | 61 | for detector in self.Values(): 62 | detector.Update() 63 | 64 | def Likelihood(self, data, hypo): 65 | """Likelihood of the data given the hypothesis. 66 | 67 | Args: 68 | data: number of particles counted 69 | hypo: emission rate, r 70 | 71 | Returns: 72 | probability density of the data under the hypothesis 73 | """ 74 | detector = hypo 75 | like = detector.SuiteLikelihood(data) 76 | return like 77 | 78 | def DistOfR(self, name=''): 79 | """Returns the PMF of r.""" 80 | items = [(detector.r, prob) for detector, prob in self.Items()] 81 | return thinkbayes.MakePmfFromItems(items, name=name) 82 | 83 | def DistOfN(self, name=''): 84 | """Returns the PMF of n.""" 85 | return thinkbayes.MakeMixture(self, name=name) 86 | 87 | 88 | class Emitter2(thinkbayes.Suite): 89 | """Represents hypotheses about r.""" 90 | 91 | def __init__(self, rs, f=0.1): 92 | """Initializes the Suite. 93 | 94 | rs: sequence of hypothetical emission rates 95 | f: fraction of particles registered 96 | """ 97 | detectors = [Detector(r, f) for r in rs] 98 | thinkbayes.Suite.__init__(self, detectors) 99 | 100 | def Likelihood(self, data, hypo): 101 | """Likelihood of the data given the hypothesis. 102 | 103 | Args: 104 | data: number of counted per unit time 105 | hypo: emission rate, r 106 | 107 | Returns: 108 | probability density of the data under the hypothesis 109 | """ 110 | return hypo.Update(data) 111 | 112 | def DistOfR(self, name=''): 113 | """Returns the PMF of r.""" 114 | items = [(detector.r, prob) for detector, prob in self.Items()] 115 | return thinkbayes.MakePmfFromItems(items, name=name) 116 | 117 | def DistOfN(self, name=''): 118 | """Returns the PMF of n.""" 119 | return thinkbayes.MakeMixture(self, name=name) 120 | 121 | 122 | class Detector(thinkbayes.Suite): 123 | """Represents hypotheses about n.""" 124 | 125 | def __init__(self, r, f, high=500, step=5): 126 | """Initializes the suite. 127 | 128 | r: known emission rate, r 129 | f: fraction of particles registered 130 | high: maximum number of particles, n 131 | step: step size between hypothetical values of n 132 | """ 133 | pmf = thinkbayes.MakePoissonPmf(r, high, step=step) 134 | thinkbayes.Suite.__init__(self, pmf, name=r) 135 | self.r = r 136 | self.f = f 137 | 138 | def Likelihood(self, data, hypo): 139 | """Likelihood of the data given the hypothesis. 140 | 141 | data: number of particles counted 142 | hypo: number of particles hitting the counter, n 143 | """ 144 | k = data 145 | n = hypo 146 | p = self.f 147 | 148 | return thinkbayes.EvalBinomialPmf(k, n, p) 149 | 150 | def SuiteLikelihood(self, data): 151 | """Adds up the total probability of the data under the suite. 152 | 153 | data: number of particles counted 154 | """ 155 | total = 0 156 | for hypo, prob in self.Items(): 157 | like = self.Likelihood(data, hypo) 158 | total += prob * like 159 | return total 160 | 161 | 162 | def main(): 163 | k = 15 164 | f = 0.1 165 | 166 | # plot Detector suites for a range of hypothetical r 167 | thinkplot.PrePlot(num=3) 168 | for r in [100, 250, 400]: 169 | suite = Detector(r, f, step=1) 170 | suite.Update(k) 171 | thinkplot.Pmf(suite) 172 | print(suite.MaximumLikelihood()) 173 | 174 | thinkplot.Save(root='jaynes1', 175 | xlabel='Number of particles (n)', 176 | ylabel='PMF', 177 | formats=FORMATS) 178 | 179 | # plot the posterior distributions of r and n 180 | hypos = range(1, 501, 5) 181 | suite = Emitter2(hypos, f=f) 182 | suite.Update(k) 183 | 184 | thinkplot.PrePlot(num=2) 185 | post_r = suite.DistOfR(name='posterior r') 186 | post_n = suite.DistOfN(name='posterior n') 187 | 188 | thinkplot.Pmf(post_r) 189 | thinkplot.Pmf(post_n) 190 | 191 | thinkplot.Save(root='jaynes2', 192 | xlabel='Emission rate', 193 | ylabel='PMF', 194 | formats=FORMATS) 195 | 196 | 197 | if __name__ == '__main__': 198 | main() 199 | -------------------------------------------------------------------------------- /code/m_and_m.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | 8 | from thinkbayes import Suite 9 | 10 | 11 | class M_and_M(Suite): 12 | """Map from hypothesis (A or B) to probability.""" 13 | 14 | mix94 = dict(brown=30, 15 | yellow=20, 16 | red=20, 17 | green=10, 18 | orange=10, 19 | tan=10, 20 | blue=0) 21 | 22 | mix96 = dict(blue=24, 23 | green=20, 24 | orange=16, 25 | yellow=14, 26 | red=13, 27 | brown=13, 28 | tan=0) 29 | 30 | hypoA = dict(bag1=mix94, bag2=mix96) 31 | hypoB = dict(bag1=mix96, bag2=mix94) 32 | 33 | hypotheses = dict(A=hypoA, B=hypoB) 34 | 35 | def Likelihood(self, data, hypo): 36 | """Computes the likelihood of the data under the hypothesis. 37 | 38 | hypo: string hypothesis (A or B) 39 | data: tuple of string bag, string color 40 | """ 41 | bag, color = data 42 | mix = self.hypotheses[hypo][bag] 43 | like = mix[color] 44 | return like 45 | 46 | 47 | def main(): 48 | suite = M_and_M('AB') 49 | 50 | suite.Update(('bag1', 'yellow')) 51 | suite.Update(('bag2', 'green')) 52 | 53 | suite.Print() 54 | 55 | 56 | if __name__ == '__main__': 57 | main() 58 | -------------------------------------------------------------------------------- /code/monty.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | from thinkbayes import Pmf 10 | 11 | 12 | class Monty(Pmf): 13 | """Map from string location of car to probability""" 14 | 15 | def __init__(self, hypos): 16 | """Initialize the distribution. 17 | 18 | hypos: sequence of hypotheses 19 | """ 20 | Pmf.__init__(self) 21 | for hypo in hypos: 22 | self.Set(hypo, 1) 23 | self.Normalize() 24 | 25 | def Update(self, data): 26 | """Updates each hypothesis based on the data. 27 | 28 | data: any representation of the data 29 | """ 30 | for hypo in self.Values(): 31 | like = self.Likelihood(data, hypo) 32 | self.Mult(hypo, like) 33 | self.Normalize() 34 | 35 | def Likelihood(self, data, hypo): 36 | """Compute the likelihood of the data under the hypothesis. 37 | 38 | hypo: string name of the door where the prize is 39 | data: string name of the door Monty opened 40 | """ 41 | if hypo == data: 42 | return 0 43 | elif hypo == 'A': 44 | return 0.5 45 | else: 46 | return 1 47 | 48 | 49 | def main(): 50 | hypos = 'ABC' 51 | pmf = Monty(hypos) 52 | 53 | data = 'B' 54 | pmf.Update(data) 55 | 56 | for hypo, prob in sorted(pmf.Items()): 57 | print(hypo, prob) 58 | 59 | 60 | if __name__ == '__main__': 61 | main() 62 | -------------------------------------------------------------------------------- /code/monty2.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | 8 | from thinkbayes import Suite 9 | 10 | 11 | class Monty(Suite): 12 | def Likelihood(self, data, hypo): 13 | """Computes the likelihood of the data under the hypothesis. 14 | 15 | hypo: string name of the door where the prize is 16 | data: string name of the door Monty opened 17 | """ 18 | if hypo == data: 19 | return 0 20 | elif hypo == 'A': 21 | return 0.5 22 | else: 23 | return 1 24 | 25 | 26 | def main(): 27 | suite = Monty('ABC') 28 | suite.Update('B') 29 | suite.Print() 30 | 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /code/myplot.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Stats", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2010 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | import math 10 | import matplotlib 11 | import matplotlib.pyplot as pyplot 12 | import numpy as np 13 | 14 | # customize some matplotlib attributes 15 | #matplotlib.rc('figure', figsize=(4, 3)) 16 | 17 | #matplotlib.rc('font', size=14.0) 18 | #matplotlib.rc('axes', labelsize=22.0, titlesize=22.0) 19 | #matplotlib.rc('legend', fontsize=20.0) 20 | 21 | #matplotlib.rc('xtick.major', size=6.0) 22 | #matplotlib.rc('xtick.minor', size=3.0) 23 | 24 | #matplotlib.rc('ytick.major', size=6.0) 25 | #matplotlib.rc('ytick.minor', size=3.0) 26 | 27 | 28 | class Brewer(object): 29 | """Encapsulates a nice sequence of colors. 30 | 31 | Shades of blue that look good in color and can be distinguished 32 | in grayscale (up to a point). 33 | 34 | Borrowed from http://colorbrewer2.org/ 35 | """ 36 | color_iter = None 37 | 38 | colors = ['#081D58', 39 | '#253494', 40 | '#225EA8', 41 | '#1D91C0', 42 | '#41B6C4', 43 | '#7FCDBB', 44 | '#C7E9B4', 45 | '#EDF8B1', 46 | '#FFFFD9'] 47 | 48 | # lists that indicate which colors to use depending on how many are used 49 | which_colors = [[], 50 | [1], 51 | [1, 3], 52 | [0, 2, 4], 53 | [0, 2, 4, 6], 54 | [0, 2, 3, 5, 6], 55 | [0, 2, 3, 4, 5, 6], 56 | [0, 1, 2, 3, 4, 5, 6], 57 | ] 58 | 59 | @classmethod 60 | def Colors(cls): 61 | """Returns the list of colors. 62 | """ 63 | return cls.colors 64 | 65 | @classmethod 66 | def ColorGenerator(cls, n): 67 | """Returns an iterator of color strings. 68 | 69 | n: how many colors will be used 70 | """ 71 | for i in cls.which_colors[n]: 72 | yield cls.colors[i] 73 | 74 | @classmethod 75 | def InitializeIter(cls, num): 76 | """Initializes the color iterator with the given number of colors.""" 77 | cls.color_iter = cls.ColorGenerator(num) 78 | 79 | @classmethod 80 | def ClearIter(cls): 81 | """Sets the color iterator to None.""" 82 | cls.color_iter = None 83 | 84 | @classmethod 85 | def GetIter(cls): 86 | """Gets the color iterator.""" 87 | return cls.color_iter 88 | 89 | 90 | def PrePlot(num=None, rows=1, cols=1): 91 | """Takes hints about what's coming. 92 | 93 | num: number of lines that will be plotted 94 | """ 95 | if num: 96 | Brewer.InitializeIter(num) 97 | 98 | # TODO: get sharey and sharex working. probably means switching 99 | # to subplots instead of subplot. 100 | # also, get rid of the gray background. 101 | 102 | if rows > 1 or cols > 1: 103 | pyplot.subplots(rows, cols, sharey=True) 104 | global SUBPLOT_ROWS, SUBPLOT_COLS 105 | SUBPLOT_ROWS = rows 106 | SUBPLOT_COLS = cols 107 | 108 | 109 | def SubPlot(plot_number): 110 | pyplot.subplot(SUBPLOT_ROWS, SUBPLOT_COLS, plot_number) 111 | 112 | 113 | class InfiniteList(list): 114 | """A list that returns the same value for all indices.""" 115 | def __init__(self, val): 116 | """Initializes the list. 117 | 118 | val: value to be stored 119 | """ 120 | list.__init__(self) 121 | self.val = val 122 | 123 | def __getitem__(self, index): 124 | """Gets the item with the given index. 125 | 126 | index: int 127 | 128 | returns: the stored value 129 | """ 130 | return self.val 131 | 132 | 133 | def Underride(d, **options): 134 | """Add key-value pairs to d only if key is not in d. 135 | 136 | If d is None, create a new dictionary. 137 | 138 | d: dictionary 139 | options: keyword args to add to d 140 | """ 141 | if d is None: 142 | d = {} 143 | 144 | for key, val in options.items(): 145 | d.setdefault(key, val) 146 | 147 | return d 148 | 149 | 150 | def Clf(): 151 | """Clears the figure and any hints that have been set.""" 152 | Brewer.ClearIter() 153 | pyplot.clf() 154 | 155 | 156 | def Figure(**options): 157 | """Sets options for the current figure.""" 158 | Underride(options, figsize=(6, 8)) 159 | pyplot.figure(**options) 160 | 161 | 162 | def Plot(xs, ys, style='', **options): 163 | """Plots a line. 164 | 165 | Args: 166 | xs: sequence of x values 167 | ys: sequence of y values 168 | style: style string passed along to pyplot.plot 169 | options: keyword args passed to pyplot.plot 170 | """ 171 | color_iter = Brewer.GetIter() 172 | 173 | if color_iter: 174 | try: 175 | options = Underride(options, color=next(color_iter)) 176 | except StopIteration: 177 | print('Warning: Brewer ran out of colors.') 178 | Brewer.ClearIter() 179 | 180 | options = Underride(options, linewidth=3, alpha=0.8) 181 | pyplot.plot(xs, ys, style, **options) 182 | 183 | 184 | def Scatter(xs, ys, **options): 185 | """Makes a scatter plot. 186 | 187 | xs: x values 188 | ys: y values 189 | options: options passed to pyplot.scatter 190 | """ 191 | options = Underride(options, color='blue', alpha=0.2, 192 | s=30, edgecolors='none') 193 | pyplot.scatter(xs, ys, **options) 194 | 195 | 196 | def Pmf(pmf, **options): 197 | """Plots a Pmf or Hist as a line. 198 | 199 | Args: 200 | pmf: Hist or Pmf object 201 | options: keyword args passed to pyplot.plot 202 | """ 203 | xs, ps = pmf.Render() 204 | if pmf.name: 205 | options = Underride(options, label=pmf.name) 206 | Plot(xs, ps, **options) 207 | 208 | 209 | def Pmfs(pmfs, **options): 210 | """Plots a sequence of PMFs. 211 | 212 | Options are passed along for all PMFs. If you want different 213 | options for each pmf, make multiple calls to Pmf. 214 | 215 | Args: 216 | pmfs: sequence of PMF objects 217 | options: keyword args passed to pyplot.plot 218 | """ 219 | for pmf in pmfs: 220 | Pmf(pmf, **options) 221 | 222 | 223 | def Hist(hist, **options): 224 | """Plots a Pmf or Hist with a bar plot. 225 | 226 | Args: 227 | hist: Hist or Pmf object 228 | options: keyword args passed to pyplot.bar 229 | """ 230 | # find the minimum distance between adjacent values 231 | xs, fs = hist.Render() 232 | width = min(Diff(xs)) 233 | 234 | if hist.name: 235 | options = Underride(options, label=hist.name) 236 | 237 | options = Underride(options, 238 | align='center', 239 | linewidth=0, 240 | width=width) 241 | 242 | pyplot.bar(xs, fs, **options) 243 | 244 | 245 | def Hists(hists, **options): 246 | """Plots two histograms as interleaved bar plots. 247 | 248 | Options are passed along for all PMFs. If you want different 249 | options for each pmf, make multiple calls to Pmf. 250 | 251 | Args: 252 | hists: list of two Hist or Pmf objects 253 | options: keyword args passed to pyplot.plot 254 | """ 255 | for hist in hists: 256 | Hist(hist, **options) 257 | 258 | 259 | def Diff(t): 260 | """Compute the differences between adjacent elements in a sequence. 261 | 262 | Args: 263 | t: sequence of number 264 | 265 | Returns: 266 | sequence of differences (length one less than t) 267 | """ 268 | diffs = [t[i+1] - t[i] for i in range(len(t)-1)] 269 | return diffs 270 | 271 | 272 | def Cdf(cdf, complement=False, transform=None, **options): 273 | """Plots a CDF as a line. 274 | 275 | Args: 276 | cdf: Cdf object 277 | complement: boolean, whether to plot the complementary CDF 278 | transform: string, one of 'exponential', 'pareto', 'weibull', 'gumbel' 279 | options: keyword args passed to pyplot.plot 280 | 281 | Returns: 282 | dictionary with the scale options that should be passed to 283 | myplot.Save or myplot.Show 284 | """ 285 | xs, ps = cdf.Render() 286 | scale = dict(xscale='linear', yscale='linear') 287 | 288 | if transform == 'exponential': 289 | complement = True 290 | scale['yscale'] = 'log' 291 | 292 | if transform == 'pareto': 293 | complement = True 294 | scale['yscale'] = 'log' 295 | scale['xscale'] = 'log' 296 | 297 | if complement: 298 | ps = [1.0-p for p in ps] 299 | 300 | if transform == 'weibull': 301 | xs.pop() 302 | ps.pop() 303 | ps = [-math.log(1.0-p) for p in ps] 304 | scale['xscale'] = 'log' 305 | scale['yscale'] = 'log' 306 | 307 | if transform == 'gumbel': 308 | xs.pop(0) 309 | ps.pop(0) 310 | ps = [-math.log(p) for p in ps] 311 | scale['yscale'] = 'log' 312 | 313 | if cdf.name: 314 | options = Underride(options, label=cdf.name) 315 | 316 | Plot(xs, ps, **options) 317 | return scale 318 | 319 | 320 | def Cdfs(cdfs, complement=False, transform=None, **options): 321 | """Plots a sequence of CDFs. 322 | 323 | cdfs: sequence of CDF objects 324 | complement: boolean, whether to plot the complementary CDF 325 | transform: string, one of 'exponential', 'pareto', 'weibull', 'gumbel' 326 | options: keyword args passed to pyplot.plot 327 | """ 328 | for cdf in cdfs: 329 | Cdf(cdf, complement, transform, **options) 330 | 331 | 332 | def Contour(obj, pcolor=False, contour=True, imshow=False, **options): 333 | """Makes a contour plot. 334 | 335 | d: map from (x, y) to z, or object that provides GetDict 336 | pcolor: boolean, whether to make a pseudocolor plot 337 | contour: boolean, whether to make a contour plot 338 | imshow: boolean, whether to use pyplot.imshow 339 | options: keyword args passed to pyplot.pcolor and/or pyplot.contour 340 | """ 341 | try: 342 | d = obj.GetDict() 343 | except AttributeError: 344 | d = obj 345 | 346 | Underride(options, linewidth=3, cmap=matplotlib.cm.Blues) 347 | 348 | xs, ys = zip(*d.keys()) 349 | xs = sorted(set(xs)) 350 | ys = sorted(set(ys)) 351 | 352 | X, Y = np.meshgrid(xs, ys) 353 | func = lambda x, y: d.get((x, y), 0) 354 | func = np.vectorize(func) 355 | Z = func(X, Y) 356 | 357 | x_formatter = matplotlib.ticker.ScalarFormatter(useOffset=False) 358 | axes = pyplot.gca() 359 | axes.xaxis.set_major_formatter(x_formatter) 360 | 361 | if pcolor: 362 | pyplot.pcolormesh(X, Y, Z, **options) 363 | if contour: 364 | cs = pyplot.contour(X, Y, Z, **options) 365 | pyplot.clabel(cs, inline=1, fontsize=10) 366 | if imshow: 367 | extent = xs[0], xs[-1], ys[0], ys[-1] 368 | pyplot.imshow(Z, extent=extent, **options) 369 | 370 | 371 | def Pcolor(xs, ys, zs, pcolor=True, contour=False, **options): 372 | """Makes a pseudocolor plot. 373 | 374 | xs: 375 | ys: 376 | zs: 377 | pcolor: boolean, whether to make a pseudocolor plot 378 | contour: boolean, whether to make a contour plot 379 | options: keyword args passed to pyplot.pcolor and/or pyplot.contour 380 | """ 381 | Underride(options, linewidth=3, cmap=matplotlib.cm.Blues) 382 | 383 | X, Y = np.meshgrid(xs, ys) 384 | Z = zs 385 | 386 | x_formatter = matplotlib.ticker.ScalarFormatter(useOffset=False) 387 | axes = pyplot.gca() 388 | axes.xaxis.set_major_formatter(x_formatter) 389 | 390 | if pcolor: 391 | pyplot.pcolormesh(X, Y, Z, **options) 392 | 393 | if contour: 394 | cs = pyplot.contour(X, Y, Z, **options) 395 | pyplot.clabel(cs, inline=1, fontsize=10) 396 | 397 | 398 | def Config(**options): 399 | """Configures the plot. 400 | 401 | Pulls options out of the option dictionary and passes them to 402 | title, xlabel, ylabel, xscale, yscale, xticks, yticks, axis, legend, 403 | and loc. 404 | """ 405 | title = options.get('title', '') 406 | pyplot.title(title) 407 | 408 | xlabel = options.get('xlabel', '') 409 | pyplot.xlabel(xlabel) 410 | 411 | ylabel = options.get('ylabel', '') 412 | pyplot.ylabel(ylabel) 413 | 414 | if 'xscale' in options: 415 | pyplot.xscale(options['xscale']) 416 | 417 | if 'xticks' in options: 418 | pyplot.xticks(options['xticks']) 419 | 420 | if 'yscale' in options: 421 | pyplot.yscale(options['yscale']) 422 | 423 | if 'yticks' in options: 424 | pyplot.yticks(options['yticks']) 425 | 426 | if 'axis' in options: 427 | pyplot.axis(options['axis']) 428 | 429 | loc = options.get('loc', 0) 430 | legend = options.get('legend', True) 431 | if legend: 432 | pyplot.legend(loc=loc) 433 | 434 | 435 | def Show(**options): 436 | """Shows the plot. 437 | 438 | For options, see Config. 439 | 440 | options: keyword args used to invoke various pyplot functions 441 | """ 442 | # TODO: figure out how to show more than one plot 443 | Config(**options) 444 | pyplot.show() 445 | 446 | 447 | def Save(root=None, formats=None, **options): 448 | """Saves the plot in the given formats. 449 | 450 | For options, see Config. 451 | 452 | Args: 453 | root: string filename root 454 | formats: list of string formats 455 | options: keyword args used to invoke various pyplot functions 456 | """ 457 | Config(**options) 458 | 459 | if formats is None: 460 | formats = ['pdf', 'eps'] 461 | 462 | if root: 463 | for fmt in formats: 464 | SaveFormat(root, fmt) 465 | Clf() 466 | 467 | 468 | def SaveFormat(root, fmt='eps'): 469 | """Writes the current figure to a file in the given format. 470 | 471 | Args: 472 | root: string filename root 473 | fmt: string format 474 | """ 475 | filename = '%s.%s' % (root, fmt) 476 | print('Writing', filename) 477 | pyplot.savefig(filename, format=fmt, dpi=300) 478 | 479 | 480 | # provide aliases for calling functons with lower-case names 481 | preplot = PrePlot 482 | subplot = SubPlot 483 | clf = Clf 484 | figure = Figure 485 | plot = Plot 486 | scatter = Scatter 487 | pmf = Pmf 488 | pmfs = Pmfs 489 | hist = Hist 490 | hists = Hists 491 | diff = Diff 492 | cdf = Cdf 493 | cdfs = Cdfs 494 | contour = Contour 495 | pcolor = Pcolor 496 | config = Config 497 | show = Show 498 | save = Save 499 | 500 | 501 | def main(): 502 | color_iter = Brewer.ColorGenerator(7) 503 | for color in color_iter: 504 | print(color) 505 | 506 | if __name__ == '__main__': 507 | main() 508 | -------------------------------------------------------------------------------- /code/paintball.py: -------------------------------------------------------------------------------- 1 | """This file contains code used in "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | import thinkbayes 10 | 11 | import matplotlib.pyplot as pyplot 12 | import thinkplot 13 | 14 | import math 15 | import sys 16 | 17 | 18 | FORMATS = ['pdf', 'eps', 'png'] 19 | 20 | 21 | def StrafingSpeed(alpha, beta, x): 22 | """Computes strafing speed, given location of shooter and impact. 23 | 24 | alpha: x location of shooter 25 | beta: y location of shooter 26 | x: location of impact 27 | 28 | Returns: derivative of x with respect to theta 29 | """ 30 | theta = math.atan2(x - alpha, beta) 31 | speed = beta / math.cos(theta)**2 32 | return speed 33 | 34 | 35 | def MakeLocationPmf(alpha, beta, locations): 36 | """Computes the Pmf of the locations, given alpha and beta. 37 | 38 | Given that the shooter is at coordinates (alpha, beta), 39 | the probability of hitting any spot is inversely proportionate 40 | to the strafe speed. 41 | 42 | alpha: x position 43 | beta: y position 44 | locations: x locations where the pmf is evaluated 45 | 46 | Returns: Pmf object 47 | """ 48 | pmf = thinkbayes.Pmf() 49 | for x in locations: 50 | prob = 1.0 / StrafingSpeed(alpha, beta, x) 51 | pmf.Set(x, prob) 52 | pmf.Normalize() 53 | return pmf 54 | 55 | 56 | class Paintball(thinkbayes.Suite, thinkbayes.Joint): 57 | """Represents hypotheses about the location of an opponent.""" 58 | 59 | def __init__(self, alphas, betas, locations): 60 | """Makes a joint suite of parameters alpha and beta. 61 | 62 | Enumerates all pairs of alpha and beta. 63 | Stores locations for use in Likelihood. 64 | 65 | alphas: possible values for alpha 66 | betas: possible values for beta 67 | locations: possible locations along the wall 68 | """ 69 | self.locations = locations 70 | pairs = [(alpha, beta) 71 | for alpha in alphas 72 | for beta in betas] 73 | thinkbayes.Suite.__init__(self, pairs) 74 | 75 | def Likelihood(self, data, hypo): 76 | """Computes the likelihood of the data under the hypothesis. 77 | 78 | hypo: pair of alpha, beta 79 | data: location of a hit 80 | 81 | Returns: float likelihood 82 | """ 83 | alpha, beta = hypo 84 | x = data 85 | pmf = MakeLocationPmf(alpha, beta, self.locations) 86 | like = pmf.Prob(x) 87 | return like 88 | 89 | 90 | def MakePmfPlot(alpha = 10): 91 | """Plots Pmf of location for a range of betas.""" 92 | locations = range(0, 31) 93 | 94 | betas = [10, 20, 40] 95 | thinkplot.PrePlot(num=len(betas)) 96 | 97 | for beta in betas: 98 | pmf = MakeLocationPmf(alpha, beta, locations) 99 | pmf.name = 'beta = %d' % beta 100 | thinkplot.Pmf(pmf) 101 | 102 | thinkplot.Save('paintball1', 103 | xlabel='Distance', 104 | ylabel='Prob', 105 | formats=FORMATS) 106 | 107 | 108 | def MakePosteriorPlot(suite): 109 | """Plots the posterior marginal distributions for alpha and beta. 110 | 111 | suite: posterior joint distribution of location 112 | """ 113 | marginal_alpha = suite.Marginal(0) 114 | marginal_alpha.name = 'alpha' 115 | marginal_beta = suite.Marginal(1) 116 | marginal_beta.name = 'beta' 117 | 118 | print('alpha CI', marginal_alpha.CredibleInterval(50)) 119 | print('beta CI', marginal_beta.CredibleInterval(50)) 120 | 121 | thinkplot.PrePlot(num=2) 122 | 123 | #thinkplot.Pmf(marginal_alpha) 124 | #thinkplot.Pmf(marginal_beta) 125 | 126 | thinkplot.Cdf(thinkbayes.MakeCdfFromPmf(marginal_alpha)) 127 | thinkplot.Cdf(thinkbayes.MakeCdfFromPmf(marginal_beta)) 128 | 129 | thinkplot.Save('paintball2', 130 | xlabel='Distance', 131 | ylabel='Prob', 132 | loc=4, 133 | formats=FORMATS) 134 | 135 | 136 | def MakeConditionalPlot(suite): 137 | """Plots marginal CDFs for alpha conditioned on beta. 138 | 139 | suite: posterior joint distribution of location 140 | """ 141 | betas = [10, 20, 40] 142 | thinkplot.PrePlot(num=len(betas)) 143 | 144 | for beta in betas: 145 | cond = suite.Conditional(0, 1, beta) 146 | cond.name = 'beta = %d' % beta 147 | thinkplot.Pmf(cond) 148 | 149 | thinkplot.Save('paintball3', 150 | xlabel='Distance', 151 | ylabel='Prob', 152 | formats=FORMATS) 153 | 154 | 155 | def MakeContourPlot(suite): 156 | """Plots the posterior joint distribution as a contour plot. 157 | 158 | suite: posterior joint distribution of location 159 | """ 160 | thinkplot.Contour(suite.GetDict(), contour=False, pcolor=True) 161 | 162 | thinkplot.Save('paintball4', 163 | xlabel='alpha', 164 | ylabel='beta', 165 | axis=[0, 30, 0, 20], 166 | formats=FORMATS) 167 | 168 | 169 | def MakeCrediblePlot(suite): 170 | """Makes a plot showing several two-dimensional credible intervals. 171 | 172 | suite: Suite 173 | """ 174 | d = dict((pair, 0) for pair in suite.Values()) 175 | 176 | percentages = [75, 50, 25] 177 | for p in percentages: 178 | interval = suite.MaxLikeInterval(p) 179 | for pair in interval: 180 | d[pair] += 1 181 | 182 | thinkplot.Contour(d, contour=False, pcolor=True) 183 | pyplot.text(17, 4, '25', color='white') 184 | pyplot.text(17, 15, '50', color='white') 185 | pyplot.text(17, 30, '75') 186 | 187 | thinkplot.Save('paintball5', 188 | xlabel='alpha', 189 | ylabel='beta', 190 | formats=FORMATS) 191 | 192 | 193 | def main(script): 194 | 195 | alphas = range(0, 31) 196 | betas = range(1, 51) 197 | locations = range(0, 31) 198 | 199 | suite = Paintball(alphas, betas, locations) 200 | suite.UpdateSet([15, 16, 18, 21]) 201 | 202 | MakeCrediblePlot(suite) 203 | 204 | MakeContourPlot(suite) 205 | 206 | MakePosteriorPlot(suite) 207 | 208 | MakeConditionalPlot(suite) 209 | 210 | MakePmfPlot() 211 | 212 | 213 | if __name__ == '__main__': 214 | main(*sys.argv) 215 | -------------------------------------------------------------------------------- /code/price.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2013 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | import csv 10 | import numpy 11 | import thinkbayes 12 | import thinkplot 13 | 14 | import matplotlib.pyplot as pyplot 15 | 16 | 17 | FORMATS = ['png', 'pdf', 'eps'] 18 | 19 | 20 | def ReadData(filename='showcases.2011.csv'): 21 | """Reads a CSV file of data. 22 | 23 | Args: 24 | filename: string filename 25 | 26 | Returns: sequence of (price1 price2 bid1 bid2 diff1 diff2) tuples 27 | """ 28 | fp = open(filename) 29 | reader = csv.reader(fp) 30 | res = [] 31 | 32 | for t in reader: 33 | _heading = t[0] 34 | data = t[1:] 35 | try: 36 | data = [int(x) for x in data] 37 | # print(heading, data[0], len(data)) 38 | res.append(data) 39 | except ValueError: 40 | pass 41 | 42 | fp.close() 43 | return list(zip(*res)) 44 | 45 | 46 | class Price(thinkbayes.Suite): 47 | """Represents hypotheses about the price of a showcase.""" 48 | 49 | def __init__(self, pmf, player, name=''): 50 | """Constructs the suite. 51 | 52 | pmf: prior distribution of price 53 | player: Player object 54 | name: string 55 | """ 56 | thinkbayes.Suite.__init__(self, pmf, name=name) 57 | self.player = player 58 | 59 | def Likelihood(self, data, hypo): 60 | """Computes the likelihood of the data under the hypothesis. 61 | 62 | hypo: actual price 63 | data: the contestant's guess 64 | """ 65 | price = hypo 66 | guess = data 67 | 68 | error = price - guess 69 | like = self.player.ErrorDensity(error) 70 | 71 | return like 72 | 73 | 74 | class GainCalculator(object): 75 | """Encapsulates computation of expected gain.""" 76 | 77 | def __init__(self, player, opponent): 78 | """Constructs the calculator. 79 | 80 | player: Player 81 | opponent: Player 82 | """ 83 | self.player = player 84 | self.opponent = opponent 85 | 86 | def ExpectedGains(self, low=0, high=75000, n=101): 87 | """Computes expected gains for a range of bids. 88 | 89 | low: low bid 90 | high: high bid 91 | n: number of bids to evaluates 92 | 93 | returns: tuple (sequence of bids, sequence of gains) 94 | 95 | """ 96 | bids = numpy.linspace(low, high, n) 97 | 98 | gains = [self.ExpectedGain(bid) for bid in bids] 99 | 100 | return bids, gains 101 | 102 | def ExpectedGain(self, bid): 103 | """Computes the expected return of a given bid. 104 | 105 | bid: your bid 106 | """ 107 | suite = self.player.posterior 108 | total = 0 109 | for price, prob in sorted(suite.Items()): 110 | gain = self.Gain(bid, price) 111 | total += prob * gain 112 | return total 113 | 114 | def Gain(self, bid, price): 115 | """Computes the return of a bid, given the actual price. 116 | 117 | bid: number 118 | price: actual price 119 | """ 120 | # if you overbid, you get nothing 121 | if bid > price: 122 | return 0 123 | 124 | # otherwise compute the probability of winning 125 | diff = price - bid 126 | prob = self.ProbWin(diff) 127 | 128 | # if you are within 250 dollars, you win both showcases 129 | if diff <= 250: 130 | return 2 * price * prob 131 | else: 132 | return price * prob 133 | 134 | def ProbWin(self, diff): 135 | """Computes the probability of winning for a given diff. 136 | 137 | diff: how much your bid was off by 138 | """ 139 | prob = (self.opponent.ProbOverbid() + 140 | self.opponent.ProbWorseThan(diff)) 141 | return prob 142 | 143 | 144 | class Player(object): 145 | """Represents a player on The Price is Right.""" 146 | 147 | n = 101 148 | price_xs = numpy.linspace(0, 75000, n) 149 | 150 | def __init__(self, prices, bids, diffs): 151 | """Construct the Player. 152 | 153 | prices: sequence of prices 154 | bids: sequence of bids 155 | diffs: sequence of underness (negative means over) 156 | """ 157 | self.pdf_price = thinkbayes.EstimatedPdf(prices) 158 | self.cdf_diff = thinkbayes.MakeCdfFromList(diffs) 159 | 160 | mu = 0 161 | sigma = numpy.std(diffs) 162 | self.pdf_error = thinkbayes.GaussianPdf(mu, sigma) 163 | 164 | def ErrorDensity(self, error): 165 | """Density of the given error in the distribution of error. 166 | 167 | error: how much the bid is under the actual price 168 | """ 169 | return self.pdf_error.Density(error) 170 | 171 | def PmfPrice(self): 172 | """Returns a new Pmf of prices. 173 | 174 | A discrete version of the estimated Pdf. 175 | """ 176 | return self.pdf_price.MakePmf(self.price_xs) 177 | 178 | def CdfDiff(self): 179 | """Returns a reference to the Cdf of differences (underness). 180 | """ 181 | return self.cdf_diff 182 | 183 | def ProbOverbid(self): 184 | """Returns the probability this player overbids. 185 | """ 186 | return self.cdf_diff.Prob(-1) 187 | 188 | def ProbWorseThan(self, diff): 189 | """Probability this player's diff is greater than the given diff. 190 | 191 | diff: how much the oppenent is off by (always positive) 192 | """ 193 | return 1 - self.cdf_diff.Prob(diff) 194 | 195 | def MakeBeliefs(self, guess): 196 | """Makes a posterior distribution based on estimated price. 197 | 198 | Sets attributes prior and posterior. 199 | 200 | guess: what the player thinks the showcase is worth 201 | """ 202 | pmf = self.PmfPrice() 203 | self.prior = Price(pmf, self, name='prior') 204 | self.posterior = self.prior.Copy(name='posterior') 205 | self.posterior.Update(guess) 206 | 207 | def OptimalBid(self, guess, opponent): 208 | """Computes the bid that maximizes expected return. 209 | 210 | guess: what the player thinks the showcase is worth 211 | opponent: Player 212 | 213 | Returns: (optimal bid, expected gain) 214 | """ 215 | self.MakeBeliefs(guess) 216 | calc = GainCalculator(self, opponent) 217 | bids, gains = calc.ExpectedGains() 218 | gain, bid = max(zip(gains, bids)) 219 | return bid, gain 220 | 221 | def PlotBeliefs(self, root): 222 | """Plots prior and posterior beliefs. 223 | 224 | root: string filename root for saved figure 225 | """ 226 | thinkplot.Clf() 227 | thinkplot.PrePlot(num=2) 228 | thinkplot.Pmfs([self.prior, self.posterior]) 229 | thinkplot.Save(root=root, 230 | xlabel='price ($)', 231 | ylabel='PMF', 232 | formats=FORMATS) 233 | 234 | 235 | def MakePlots(player1, player2): 236 | """Generates two plots. 237 | 238 | price1 shows the priors for the two players 239 | price2 shows the distribution of diff for the two players 240 | """ 241 | 242 | # plot the prior distribution of price for both players 243 | thinkplot.Clf() 244 | thinkplot.PrePlot(num=2) 245 | pmf1 = player1.PmfPrice() 246 | pmf1.name = 'showcase 1' 247 | pmf2 = player2.PmfPrice() 248 | pmf2.name = 'showcase 2' 249 | thinkplot.Pmfs([pmf1, pmf2]) 250 | thinkplot.Save(root='price1', 251 | xlabel='price ($)', 252 | ylabel='PDF', 253 | formats=FORMATS) 254 | 255 | # plot the historical distribution of underness for both players 256 | thinkplot.Clf() 257 | thinkplot.PrePlot(num=2) 258 | cdf1 = player1.CdfDiff() 259 | cdf1.name = 'player 1' 260 | cdf2 = player2.CdfDiff() 261 | cdf2.name = 'player 2' 262 | 263 | print('Player median', cdf1.Percentile(50)) 264 | print('Player median', cdf2.Percentile(50)) 265 | 266 | print('Player 1 overbids', player1.ProbOverbid()) 267 | print('Player 2 overbids', player2.ProbOverbid()) 268 | 269 | thinkplot.Cdfs([cdf1, cdf2]) 270 | thinkplot.Save(root='price2', 271 | xlabel='diff ($)', 272 | ylabel='CDF', 273 | formats=FORMATS) 274 | 275 | 276 | def MakePlayers(): 277 | """Reads data and makes player objects.""" 278 | data = ReadData(filename='showcases.2011.csv') 279 | data += ReadData(filename='showcases.2012.csv') 280 | 281 | cols = zip(*data) 282 | price1, price2, bid1, bid2, diff1, diff2 = cols 283 | 284 | # print(list(sorted(price1))) 285 | # print(len(price1)) 286 | 287 | player1 = Player(price1, bid1, diff1) 288 | player2 = Player(price2, bid2, diff2) 289 | 290 | return player1, player2 291 | 292 | 293 | def PlotExpectedGains(guess1=20000, guess2=40000): 294 | """Plots expected gains as a function of bid. 295 | 296 | guess1: player1's estimate of the price of showcase 1 297 | guess2: player2's estimate of the price of showcase 2 298 | """ 299 | player1, player2 = MakePlayers() 300 | MakePlots(player1, player2) 301 | 302 | player1.MakeBeliefs(guess1) 303 | player2.MakeBeliefs(guess2) 304 | 305 | print('Player 1 prior mle', player1.prior.MaximumLikelihood()) 306 | print('Player 2 prior mle', player2.prior.MaximumLikelihood()) 307 | print('Player 1 mean', player1.posterior.Mean()) 308 | print('Player 2 mean', player2.posterior.Mean()) 309 | print('Player 1 mle', player1.posterior.MaximumLikelihood()) 310 | print('Player 2 mle', player2.posterior.MaximumLikelihood()) 311 | 312 | player1.PlotBeliefs('price3') 313 | player2.PlotBeliefs('price4') 314 | 315 | calc1 = GainCalculator(player1, player2) 316 | calc2 = GainCalculator(player2, player1) 317 | 318 | thinkplot.Clf() 319 | thinkplot.PrePlot(num=2) 320 | 321 | bids, gains = calc1.ExpectedGains() 322 | thinkplot.Plot(bids, gains, label='Player 1') 323 | print('Player 1 optimal bid', max(zip(gains, bids))) 324 | 325 | bids, gains = calc2.ExpectedGains() 326 | thinkplot.Plot(bids, gains, label='Player 2') 327 | print('Player 2 optimal bid', max(zip(gains, bids))) 328 | 329 | thinkplot.Save(root='price5', 330 | xlabel='bid ($)', 331 | ylabel='expected gain ($)', 332 | formats=FORMATS) 333 | 334 | 335 | def PlotOptimalBid(): 336 | """Plots optimal bid vs estimated price. 337 | """ 338 | player1, player2 = MakePlayers() 339 | guesses = numpy.linspace(15000, 60000, 21) 340 | 341 | res = [] 342 | for guess in guesses: 343 | player1.MakeBeliefs(guess) 344 | 345 | mean = player1.posterior.Mean() 346 | mle = player1.posterior.MaximumLikelihood() 347 | 348 | calc = GainCalculator(player1, player2) 349 | bids, gains = calc.ExpectedGains() 350 | gain, bid = max(zip(gains, bids)) 351 | 352 | res.append((guess, mean, mle, gain, bid)) 353 | 354 | guesses, means, _mles, gains, bids = zip(*res) 355 | 356 | thinkplot.PrePlot(num=3) 357 | pyplot.plot([15000, 60000], [15000, 60000], color='gray') 358 | thinkplot.Plot(guesses, means, label='mean') 359 | #thinkplot.Plot(guesses, mles, label='MLE') 360 | thinkplot.Plot(guesses, bids, label='bid') 361 | thinkplot.Plot(guesses, gains, label='gain') 362 | thinkplot.Save(root='price6', 363 | xlabel='guessed price ($)', 364 | formats=FORMATS) 365 | 366 | 367 | def TestCode(calc): 368 | """Check some intermediate results. 369 | 370 | calc: GainCalculator 371 | """ 372 | # test ProbWin 373 | for diff in [0, 100, 1000, 10000, 20000]: 374 | print(diff, calc.ProbWin(diff)) 375 | print 376 | 377 | # test Return 378 | price = 20000 379 | for bid in [17000, 18000, 19000, 19500, 19800, 20001]: 380 | print(bid, calc.Gain(bid, price)) 381 | print 382 | 383 | 384 | def main(): 385 | PlotExpectedGains() 386 | PlotOptimalBid() 387 | 388 | 389 | 390 | if __name__ == '__main__': 391 | main() 392 | -------------------------------------------------------------------------------- /code/redline_data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """This file contains code for use with "Think Bayes", 4 | by Allen B. Downey, available from greenteapress.com 5 | 6 | Copyright 2013 Allen B. Downey 7 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 8 | """ 9 | from __future__ import print_function 10 | 11 | import csv 12 | import json 13 | import numpy 14 | import os 15 | import sys 16 | import redis 17 | try: 18 | import urllib2 19 | except ImportError: 20 | import urllib.request as urllib2 21 | 22 | from datetime import datetime, time 23 | 24 | from time import sleep 25 | 26 | 27 | class Redis(object): 28 | """Provides access to a Redis instance on Redis To Go""" 29 | 30 | host = 'dory.redistogo.com' 31 | port = 10534 32 | 33 | def __init__(self): 34 | try: 35 | password = os.environ['REDIS_AUTH'] 36 | except KeyError: 37 | print('Environment variable REDIS_AUTH is not set.') 38 | sys.exit() 39 | 40 | self.r = redis.StrictRedis(host=self.host, 41 | port=self.port, 42 | password=password, 43 | db=0) 44 | 45 | def WriteTrainSpotting(self, timestamp, tripid, seconds, live=True): 46 | """Writes a trainspotting event to the database. 47 | 48 | timestamp: int seconds since epoch 49 | tripid: string unique id 50 | seconds: int how many seconds away the train is 51 | live: boolean, whether to actually write the data 52 | """ 53 | dt = datetime.fromtimestamp(timestamp) 54 | day = dt.date().isoformat() 55 | 56 | print(dt, tripid, seconds, timestamp) 57 | 58 | if live: 59 | self.r.sadd('days', day) 60 | self.r.sadd(day, tripid) 61 | self.r.zadd(tripid, seconds, timestamp) 62 | 63 | def FindArrivals(self, start_hour=16, end_hour=18): 64 | """For each trip, find the best estimate of the arrival time. 65 | 66 | start_hour: int 0-24, beginning of observation window 67 | end_hour: int 0-24, end of window 68 | 69 | Returns: map from string day to unsorted list of arrival datetimes 70 | """ 71 | days = self.r.smembers('days') 72 | print(days) 73 | 74 | start_time = time(hour=start_hour) 75 | end_time = time(hour=end_hour) 76 | 77 | arrival_map = {} 78 | 79 | for day in days: 80 | tripids = self.r.smembers(day) 81 | 82 | for tripid in tripids: 83 | pred_dt = self.GetPredictedArrival(tripid) 84 | pred_time = pred_dt.time() 85 | 86 | if start_time < pred_time < end_time: 87 | arrival_map.setdefault(day, []).append(pred_dt) 88 | 89 | return arrival_map 90 | 91 | def GetPredictedArrival(self, tripid): 92 | """Gets the best predicted arrival time for a given trip. 93 | 94 | tripid: string TripID like R98313D88 95 | """ 96 | pair = self.r.zrange(tripid, 0, 1, withscores=True) 97 | timestamp, seconds = pair[0] 98 | pred_ts = float(timestamp) + seconds 99 | pred_dt = datetime.fromtimestamp(pred_ts) 100 | return pred_dt 101 | 102 | class TrainSpotting(object): 103 | """Represents one observation of a train.""" 104 | 105 | def __init__(self, t): 106 | self.timestamp = int(t[0]) 107 | self.tripid = t[2] 108 | self.seconds = int(t[6]) 109 | 110 | 111 | def ReadCsv(url = 'http://developer.mbta.com/lib/rthr/red.csv'): 112 | """Reads data from the red line. 113 | 114 | Returns: list of TrainSpotting objects 115 | """ 116 | fp = urllib2.urlopen(url) 117 | reader = csv.reader(fp) 118 | 119 | tss = [] 120 | for t in reader: 121 | if t[5] != 'Kendall/MIT': continue 122 | if t[3] != 'Braintree': continue 123 | 124 | ts = TrainSpotting(t) 125 | tss.append(ts) 126 | 127 | fp.close() 128 | return tss 129 | 130 | 131 | def ReadJson(): 132 | url = 'http://developer.mbta.com/lib/rthr/red.json' 133 | json_text = urllib2.urlopen(url).read() 134 | json_obj = json.loads(json_text) 135 | print(json_obj) 136 | 137 | 138 | def ReadAndStore(red): 139 | """Read data from the MBTA and put it in the database. 140 | 141 | red: Redis object 142 | """ 143 | tss = ReadCsv() 144 | for ts in tss: 145 | red.WriteTrainSpotting(ts.timestamp, ts.tripid, ts.seconds) 146 | 147 | 148 | def Loop(red, start_time, end_time, delay=60): 149 | """Collects data from start_time until end_time. 150 | 151 | red: Redis object to store data 152 | start_time: datetime 153 | end_time: datetime 154 | delay: time to sleep between collections, in seconds 155 | """ 156 | if datetime.now() < start_time: 157 | diff = start_time - datetime.now() 158 | print('Sleeping', diff) 159 | sleep(diff.total_seconds()) 160 | 161 | while datetime.now() < end_time: 162 | print('Collecting') 163 | ReadAndStore(red) 164 | sleep(delay) 165 | 166 | 167 | def TodayAt(hour): 168 | """Makes a datetime object with today's date and the given time. 169 | 170 | hour: int 0-24 171 | """ 172 | now = datetime.now() 173 | return datetime.combine(now, time(hour=hour)) 174 | 175 | 176 | def GetInterarrivals(arrival_map): 177 | """Finds all interarrival times in the arrival map. 178 | 179 | arrival_map: map from string day to unsorted list of arrival datetimes 180 | 181 | Returns: list of float interarrival times in seconds 182 | """ 183 | interarrival_seconds = [] 184 | for day, arrivals in sorted(arrival_map.items()): 185 | print(day, len(arrivals)) 186 | arrivals.sort() 187 | diffs = numpy.diff(arrivals) 188 | diffs = [diff.total_seconds() for diff in diffs] 189 | interarrival_seconds.extend(diffs) 190 | 191 | return interarrival_seconds 192 | 193 | 194 | def main(script, command='collect'): 195 | red = Redis() 196 | 197 | if command == 'collect': 198 | start = TodayAt(16) 199 | end = TodayAt(18) 200 | 201 | print(start, end) 202 | Loop(red, start, end) 203 | 204 | elif command == 'report': 205 | arrival_map = red.FindArrivals() 206 | interarrivals = GetInterarrivals(arrival_map) 207 | print(repr(interarrivals)) 208 | 209 | 210 | if __name__ == '__main__': 211 | main(*sys.argv) 212 | -------------------------------------------------------------------------------- /code/sat.py: -------------------------------------------------------------------------------- 1 | """This file contains code used in "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | import csv 10 | import math 11 | import numpy 12 | import sys 13 | 14 | import matplotlib 15 | import matplotlib.pyplot as pyplot 16 | 17 | import thinkbayes 18 | import thinkplot 19 | 20 | 21 | def ReadScale(filename='sat_scale.csv', col=2): 22 | """Reads a CSV file of SAT scales (maps from raw score to standard score). 23 | 24 | Args: 25 | filename: string filename 26 | col: which column to start with (0=Reading, 2=Math, 4=Writing) 27 | 28 | Returns: thinkbayes.Interpolator object 29 | """ 30 | def ParseRange(s): 31 | """Parse a range of values in the form 123-456 32 | 33 | s: string 34 | """ 35 | t = [int(x) for x in s.split('-')] 36 | return 1.0 * sum(t) / len(t) 37 | 38 | fp = open(filename) 39 | reader = csv.reader(fp) 40 | raws = [] 41 | scores = [] 42 | 43 | for t in reader: 44 | try: 45 | raw = int(t[col]) 46 | raws.append(raw) 47 | score = ParseRange(t[col+1]) 48 | scores.append(score) 49 | except ValueError: 50 | pass 51 | 52 | raws.sort() 53 | scores.sort() 54 | return thinkbayes.Interpolator(raws, scores) 55 | 56 | 57 | def ReadRanks(filename='sat_ranks.csv'): 58 | """Reads a CSV file of SAT scores. 59 | 60 | Args: 61 | filename: string filename 62 | 63 | Returns: 64 | list of (score, freq) pairs 65 | """ 66 | fp = open(filename) 67 | reader = csv.reader(fp) 68 | res = [] 69 | 70 | for t in reader: 71 | try: 72 | score = int(t[0]) 73 | freq = int(t[1]) 74 | res.append((score, freq)) 75 | except ValueError: 76 | pass 77 | 78 | return res 79 | 80 | 81 | def DivideValues(pmf, denom): 82 | """Divides the values in a Pmf by denom. 83 | 84 | Returns a new Pmf. 85 | """ 86 | new = thinkbayes.Pmf() 87 | denom = float(denom) 88 | for val, prob in pmf.Items(): 89 | x = val / denom 90 | new.Set(x, prob) 91 | return new 92 | 93 | 94 | class Exam(object): 95 | """Encapsulates information about an exam. 96 | 97 | Contains the distribution of scaled scores and an 98 | Interpolator that maps between scaled and raw scores. 99 | """ 100 | def __init__(self): 101 | self.scale = ReadScale() 102 | 103 | scores = ReadRanks() 104 | score_pmf = thinkbayes.MakePmfFromDict(dict(scores)) 105 | 106 | self.raw = self.ReverseScale(score_pmf) 107 | self.max_score = max(self.raw.Values()) 108 | self.prior = DivideValues(self.raw, denom=self.max_score) 109 | 110 | center = -0.05 111 | width = 1.8 112 | self.difficulties = MakeDifficulties(center, width, self.max_score) 113 | 114 | def CompareScores(self, a_score, b_score, constructor): 115 | """Computes posteriors for two test scores and the likelihood ratio. 116 | 117 | a_score, b_score: scales SAT scores 118 | constructor: function that instantiates an Sat or Sat2 object 119 | """ 120 | a_sat = constructor(self, a_score) 121 | b_sat = constructor(self, b_score) 122 | 123 | a_sat.PlotPosteriors(b_sat) 124 | 125 | if constructor is Sat: 126 | PlotJointDist(a_sat, b_sat) 127 | 128 | top = TopLevel('AB') 129 | top.Update((a_sat, b_sat)) 130 | top.Print() 131 | 132 | ratio = top.Prob('A') / top.Prob('B') 133 | 134 | print('Likelihood ratio', ratio) 135 | 136 | posterior = ratio / (ratio + 1) 137 | print('Posterior', posterior) 138 | 139 | if constructor is Sat2: 140 | ComparePosteriorPredictive(a_sat, b_sat) 141 | 142 | def MakeRawScoreDist(self, efficacies): 143 | """Makes the distribution of raw scores for given difficulty. 144 | 145 | efficacies: Pmf of efficacy 146 | """ 147 | pmfs = thinkbayes.Pmf() 148 | for efficacy, prob in efficacies.Items(): 149 | scores = self.PmfCorrect(efficacy) 150 | pmfs.Set(scores, prob) 151 | 152 | mix = thinkbayes.MakeMixture(pmfs) 153 | return mix 154 | 155 | def CalibrateDifficulty(self): 156 | """Make a plot showing the model distribution of raw scores.""" 157 | thinkplot.Clf() 158 | thinkplot.PrePlot(num=2) 159 | 160 | cdf = thinkbayes.MakeCdfFromPmf(self.raw, name='data') 161 | thinkplot.Cdf(cdf) 162 | 163 | efficacies = thinkbayes.MakeGaussianPmf(0, 1.5, 3) 164 | pmf = self.MakeRawScoreDist(efficacies) 165 | cdf = thinkbayes.MakeCdfFromPmf(pmf, name='model') 166 | thinkplot.Cdf(cdf) 167 | 168 | thinkplot.Save(root='sat_calibrate', 169 | xlabel='raw score', 170 | ylabel='CDF', 171 | formats=['pdf', 'eps']) 172 | 173 | def PmfCorrect(self, efficacy): 174 | """Returns the PMF of number of correct responses. 175 | 176 | efficacy: float 177 | """ 178 | pmf = PmfCorrect(efficacy, self.difficulties) 179 | return pmf 180 | 181 | def Lookup(self, raw): 182 | """Looks up a raw score and returns a scaled score.""" 183 | return self.scale.Lookup(raw) 184 | 185 | def Reverse(self, score): 186 | """Looks up a scaled score and returns a raw score. 187 | 188 | Since we ignore the penalty, negative scores round up to zero. 189 | """ 190 | raw = self.scale.Reverse(score) 191 | return raw if raw > 0 else 0 192 | 193 | def ReverseScale(self, pmf): 194 | """Applies the reverse scale to the values of a PMF. 195 | 196 | Args: 197 | pmf: Pmf object 198 | scale: Interpolator object 199 | 200 | Returns: 201 | new Pmf 202 | """ 203 | new = thinkbayes.Pmf() 204 | for val, prob in pmf.Items(): 205 | raw = self.Reverse(val) 206 | new.Incr(raw, prob) 207 | return new 208 | 209 | 210 | class Sat(thinkbayes.Suite): 211 | """Represents the distribution of p_correct for a test-taker.""" 212 | 213 | def __init__(self, exam, score): 214 | self.exam = exam 215 | self.score = score 216 | 217 | # start with the prior distribution 218 | thinkbayes.Suite.__init__(self, exam.prior) 219 | 220 | # update based on an exam score 221 | self.Update(score) 222 | 223 | def Likelihood(self, data, hypo): 224 | """Computes the likelihood of a test score, given efficacy.""" 225 | p_correct = hypo 226 | score = data 227 | 228 | k = self.exam.Reverse(score) 229 | n = self.exam.max_score 230 | like = thinkbayes.EvalBinomialPmf(k, n, p_correct) 231 | return like 232 | 233 | def PlotPosteriors(self, other): 234 | """Plots posterior distributions of efficacy. 235 | 236 | self, other: Sat objects. 237 | """ 238 | thinkplot.Clf() 239 | thinkplot.PrePlot(num=2) 240 | 241 | cdf1 = thinkbayes.MakeCdfFromPmf(self, 'posterior %d' % self.score) 242 | cdf2 = thinkbayes.MakeCdfFromPmf(other, 'posterior %d' % other.score) 243 | 244 | thinkplot.Cdfs([cdf1, cdf2]) 245 | thinkplot.Save(xlabel='p_correct', 246 | ylabel='CDF', 247 | axis=[0.7, 1.0, 0.0, 1.0], 248 | root='sat_posteriors_p_corr', 249 | formats=['pdf', 'eps']) 250 | 251 | 252 | class Sat2(thinkbayes.Suite): 253 | """Represents the distribution of efficacy for a test-taker.""" 254 | 255 | def __init__(self, exam, score): 256 | self.exam = exam 257 | self.score = score 258 | 259 | # start with the Gaussian prior 260 | efficacies = thinkbayes.MakeGaussianPmf(0, 1.5, 3) 261 | thinkbayes.Suite.__init__(self, efficacies) 262 | 263 | # update based on an exam score 264 | self.Update(score) 265 | 266 | def Likelihood(self, data, hypo): 267 | """Computes the likelihood of a test score, given efficacy.""" 268 | efficacy = hypo 269 | score = data 270 | raw = self.exam.Reverse(score) 271 | 272 | pmf = self.exam.PmfCorrect(efficacy) 273 | like = pmf.Prob(raw) 274 | return like 275 | 276 | def MakePredictiveDist(self): 277 | """Returns the distribution of raw scores expected on a re-test.""" 278 | raw_pmf = self.exam.MakeRawScoreDist(self) 279 | return raw_pmf 280 | 281 | def PlotPosteriors(self, other): 282 | """Plots posterior distributions of efficacy. 283 | 284 | self, other: Sat objects. 285 | """ 286 | thinkplot.Clf() 287 | thinkplot.PrePlot(num=2) 288 | 289 | cdf1 = thinkbayes.MakeCdfFromPmf(self, 'posterior %d' % self.score) 290 | cdf2 = thinkbayes.MakeCdfFromPmf(other, 'posterior %d' % other.score) 291 | 292 | thinkplot.Cdfs([cdf1, cdf2]) 293 | thinkplot.Save(xlabel='efficacy', 294 | ylabel='CDF', 295 | axis=[0, 4.6, 0.0, 1.0], 296 | root='sat_posteriors_eff', 297 | formats=['pdf', 'eps']) 298 | 299 | 300 | def PlotJointDist(pmf1, pmf2, thresh=0.8): 301 | """Plot the joint distribution of p_correct. 302 | 303 | pmf1, pmf2: posterior distributions 304 | thresh: lower bound of the range to be plotted 305 | """ 306 | def Clean(pmf): 307 | """Removes values below thresh.""" 308 | vals = [val for val in pmf.Values() if val < thresh] 309 | [pmf.Remove(val) for val in vals] 310 | 311 | Clean(pmf1) 312 | Clean(pmf2) 313 | pmf = thinkbayes.MakeJoint(pmf1, pmf2) 314 | 315 | thinkplot.Figure(figsize=(6, 6)) 316 | thinkplot.Contour(pmf, contour=False, pcolor=True) 317 | 318 | thinkplot.Plot([thresh, 1.0], [thresh, 1.0], 319 | color='gray', alpha=0.2, linewidth=4) 320 | 321 | thinkplot.Save(root='sat_joint', 322 | xlabel='p_correct Alice', 323 | ylabel='p_correct Bob', 324 | axis=[thresh, 1.0, thresh, 1.0], 325 | formats=['pdf', 'eps']) 326 | 327 | 328 | def ComparePosteriorPredictive(a_sat, b_sat): 329 | """Compares the predictive distributions of raw scores. 330 | 331 | a_sat: posterior distribution 332 | b_sat: 333 | """ 334 | a_pred = a_sat.MakePredictiveDist() 335 | b_pred = b_sat.MakePredictiveDist() 336 | 337 | #thinkplot.Clf() 338 | #thinkplot.Pmfs([a_pred, b_pred]) 339 | #thinkplot.Show() 340 | 341 | a_like = thinkbayes.PmfProbGreater(a_pred, b_pred) 342 | b_like = thinkbayes.PmfProbLess(a_pred, b_pred) 343 | c_like = thinkbayes.PmfProbEqual(a_pred, b_pred) 344 | 345 | print('Posterior predictive') 346 | print('A', a_like) 347 | print('B', b_like) 348 | print('C', c_like) 349 | 350 | 351 | def PlotPriorDist(pmf): 352 | """Plot the prior distribution of p_correct. 353 | 354 | pmf: prior 355 | """ 356 | thinkplot.Clf() 357 | thinkplot.PrePlot(num=1) 358 | 359 | cdf1 = thinkbayes.MakeCdfFromPmf(pmf, 'prior') 360 | thinkplot.Cdf(cdf1) 361 | thinkplot.Save(root='sat_prior', 362 | xlabel='p_correct', 363 | ylabel='CDF', 364 | formats=['pdf', 'eps']) 365 | 366 | 367 | class TopLevel(thinkbayes.Suite): 368 | """Evaluates the top-level hypotheses about Alice and Bob. 369 | 370 | Uses the bottom-level posterior distribution about p_correct 371 | (or efficacy). 372 | """ 373 | 374 | def Update(self, data): 375 | a_sat, b_sat = data 376 | 377 | a_like = thinkbayes.PmfProbGreater(a_sat, b_sat) 378 | b_like = thinkbayes.PmfProbLess(a_sat, b_sat) 379 | c_like = thinkbayes.PmfProbEqual(a_sat, b_sat) 380 | 381 | a_like += c_like / 2 382 | b_like += c_like / 2 383 | 384 | self.Mult('A', a_like) 385 | self.Mult('B', b_like) 386 | 387 | self.Normalize() 388 | 389 | 390 | def ProbCorrect(efficacy, difficulty, a=1): 391 | """Returns the probability that a person gets a question right. 392 | 393 | efficacy: personal ability to answer questions 394 | difficulty: how hard the question is 395 | 396 | Returns: float prob 397 | """ 398 | return 1 / (1 + math.exp(-a * (efficacy - difficulty))) 399 | 400 | 401 | def BinaryPmf(p): 402 | """Makes a Pmf with values 1 and 0. 403 | 404 | p: probability given to 1 405 | 406 | Returns: Pmf object 407 | """ 408 | pmf = thinkbayes.Pmf() 409 | pmf.Set(1, p) 410 | pmf.Set(0, 1-p) 411 | return pmf 412 | 413 | 414 | def PmfCorrect(efficacy, difficulties): 415 | """Computes the distribution of correct responses. 416 | 417 | efficacy: personal ability to answer questions 418 | difficulties: list of difficulties, one for each question 419 | 420 | Returns: new Pmf object 421 | """ 422 | pmf0 = thinkbayes.Pmf([0]) 423 | 424 | ps = [ProbCorrect(efficacy, difficulty) for difficulty in difficulties] 425 | pmfs = [BinaryPmf(p) for p in ps] 426 | dist = sum(pmfs, pmf0) 427 | return dist 428 | 429 | 430 | def MakeDifficulties(center, width, n): 431 | """Makes a list of n difficulties with a given center and width. 432 | 433 | Returns: list of n floats between center-width and center+width 434 | """ 435 | low, high = center-width, center+width 436 | return numpy.linspace(low, high, n) 437 | 438 | 439 | def ProbCorrectTable(): 440 | """Makes a table of p_correct for a range of efficacy and difficulty.""" 441 | efficacies = [3, 1.5, 0, -1.5, -3] 442 | difficulties = [-1.85, -0.05, 1.75] 443 | 444 | for eff in efficacies: 445 | print('%0.2f & ' % eff, end="") 446 | for diff in difficulties: 447 | p = ProbCorrect(eff, diff) 448 | print('%0.2f & ' % p, end="") 449 | print(r'\\') 450 | 451 | 452 | def main(script): 453 | ProbCorrectTable() 454 | 455 | exam = Exam() 456 | 457 | PlotPriorDist(exam.prior) 458 | exam.CalibrateDifficulty() 459 | 460 | exam.CompareScores(780, 740, constructor=Sat) 461 | 462 | exam.CompareScores(780, 740, constructor=Sat2) 463 | 464 | 465 | if __name__ == '__main__': 466 | main(*sys.argv) 467 | -------------------------------------------------------------------------------- /code/sat_ranks.csv: -------------------------------------------------------------------------------- 1 | "http://professionals.collegeboard.com/profdownload/sat-mathematics-percentile-ranks-2010.pdf",,,,,, 2 | ,"Total",,"Male",,"Female", 3 | "Score","Number","Percentile","Number","Percentile","Number","Percentile" 4 | 800,11959,99,8072,99,3887,"99+" 5 | 790,3588,99,2327,99,1261,99 6 | 780,3770,99,2377,98,1393,99 7 | 770,9663,98,6340,97,3323,99 8 | 760,7016,98,4413,97,2603,98 9 | 750,10313,97,6721,96,3592,98 10 | 740,7542,97,4612,95,2930,98 11 | 730,9721,96,6004,94,3717,97 12 | 720,7674,95,4664,94,3010,97 13 | 710,15694,94,9508,92,6186,96 14 | 700,17394,93,10568,91,6826,95 15 | 690,21305,92,12858,89,8447,94 16 | 680,22953,90,13552,87,9401,93 17 | 670,24377,89,14205,85,10172,92 18 | 660,27356,87,15564,83,11792,91 19 | 650,26303,85,14685,81,11618,89 20 | 640,26844,84,14906,79,11938,88 21 | 630,28425,82,15675,77,12750,86 22 | 620,31515,80,17018,74,14497,84 23 | 610,44082,77,23042,71,21040,82 24 | 600,33358,75,17325,69,16033,80 25 | 590,38788,72,20170,66,18618,78 26 | 580,40879,70,20699,63,20180,75 27 | 570,51731,66,25790,60,25941,72 28 | 560,38232,64,18782,57,19450,70 29 | 550,38473,61,18659,54,19814,67 30 | 540,54552,58,26165,51,28387,64 31 | 530,55065,54,25373,47,29692,60 32 | 520,43599,51,20022,44,23577,57 33 | 510,45452,48,20673,42,24779,54 34 | 500,61084,45,26823,38,34261,50 35 | 490,57090,41,25113,34,31977,46 36 | 480,40871,38,17594,32,23277,44 37 | 470,47521,35,20181,29,27340,40 38 | 460,58137,31,23544,26,34593,36 39 | 450,50172,28,20777,23,29395,33 40 | 440,39180,26,15576,21,23604,30 41 | 430,46320,23,18412,18,27908,26 42 | 420,47752,20,18154,16,29598,23 43 | 410,41915,17,16052,14,25863,20 44 | 400,30052,15,11210,12,18842,17 45 | 390,32466,13,12140,10,20326,15 46 | 380,27135,11,9984,9,17151,13 47 | 370,25852,9,9484,8,16368,11 48 | 360,23847,8,8809,6,15038,9 49 | 350,20800,6,7755,5,13045,7 50 | 340,17639,5,6554,4,11085,6 51 | 330,14623,4,5371,4,9252,5 52 | 320,11400,4,4295,3,7105,4 53 | 310,11776,3,4411,2,7365,3 54 | 300,8430,2,3300,2,5130,3 55 | 290,7358,2,2898,2,4460,2 56 | 280,7358,1,2872,1,4486,2 57 | 270,3194,1,1301,1,1893,1 58 | 260,3495,1,1375,1,2120,1 59 | 250,2163,1,821,1,1342,1 60 | 240,3278,1,1303,1,1975,1 61 | 230,1454,1,555,"1-",899,1 62 | 220,2519,"1-",991,"1-",1528,"1-" 63 | 210,1221,"1-",501,"1-",720,"1-" 64 | 200,4265,"–",1868,"–",2397,"–" 65 | ,1547990,,720793,,827197, 66 | ,,,65606,,38728, 67 | ,,,0.0910191969,,0.0468183516, 68 | -------------------------------------------------------------------------------- /code/sat_scale.csv: -------------------------------------------------------------------------------- 1 | "http://professionals.collegeboard.com/profdownload/sat-raw-score-to-scaled-score-ranges-2010.pdf",,,,, 2 | "Raw score","Critical Reading","Raw score","Mathematics","Raw score","Writing Skills" 3 | 67,800,,,, 4 | 65,"790-800",,,, 5 | 60,"710-730",,,, 6 | 55,"660-670",54,800,, 7 | 50,"620-630",50,"710-730",49,800 8 | 45,"580-590",45,"650-670",45,"690-730" 9 | 40,"550-560",40,"610-630",40,"620-660" 10 | 35,"520-530",35,"570-580",35,"570-660" 11 | 30,"490-510",30,"530-540",30,"520-550" 12 | 25,"460-480",25,"490-500",25,"480-510" 13 | 20,"420-450",20,"450-460",20,"440-460" 14 | 15,"390-420",15,"410-420",15,"400-420" 15 | 10,"350-380",10,"360-380",10,"350-370" 16 | 5,"300-330",5,"300-330",5,"300-330" 17 | 0,"220-270",0,"220-260",0,"210-260" 18 | -5,200,-5,200,-5,200 19 | -------------------------------------------------------------------------------- /code/showcases.2011.csv: -------------------------------------------------------------------------------- 1 | ,"Sep. 19","Sep. 20","Sep. 21","Sep. 22","Sep. 23","Sep. 26","Sep. 27","Sep. 28","Sep. 29","Sep. 30","Oct. 3","Oct. 4","Oct. 5","Oct. 7","Oct. 10","Oct. 11","Oct. 12","Oct. 13","Oct. 14","Oct. 17","Oct. 18","Oct. 19","Oct. 20","Oct. 21","Oct. 24","Oct. 25","Oct. 26","Oct. 27","Oct. 28","Oct. 31","Nov. 1","Nov. 2","Nov. 3","Nov. 4","Nov. 7","Nov. 8","Nov. 9","Nov. 10","Nov. 11","Nov. 14","Nov. 15","Nov. 16","Nov. 17","Nov. 18","Nov. 21","Nov. 22","Nov. 23","Nov. 28","Nov. 29","Nov. 30","Dec. 1","Dec. 2","Dec. 5","Dec. 6","Dec. 7","Dec. 8","Dec. 9","Dec. 12","Dec. 13","Dec. 14","Dec. 15","Dec. 16","Dec. 19","Dec. 20","Dec. 21","Dec. 22","Dec. 23","Dec. 26","Dec. 30","Jan. 2","Jan. 3","Jan. 4","Jan. 5","Jan. 6","Jan. 9","Jan. 10","Jan. 11","Jan. 12","Jan. 13","Jan. 16","Jan. 18","Jan. 19","Jan. 20","Jan. 23","Jan. 24","Jan. 25","Jan. 26","Jan. 27","Jan. 30","Jan. 31","Feb. 1","Feb. 2","Feb. 3","Feb. 6","Feb. 7","Feb. 8","Feb. 9","Feb. 10","Feb. 13","Feb. 14","Feb. 15","Feb. 16","Feb. 17","Feb. 20","Feb. 21","Feb. 22","Feb. 23","Feb. 24","Feb. 27","Feb. 28","Feb. 29","Mar. 1","Mar. 2","Mar. 5","Mar. 6","Mar. 7","Mar. 8","Mar. 9","Mar. 12","Mar. 13","Mar. 14","Mar. 19","Mar. 20","Mar. 21","Mar. 22","Mar. 23","Mar. 26","Mar. 27","Mar. 28","Mar. 29","Mar. 30","Apr. 2","Apr. 3","Apr. 4","Apr. 5","Apr. 6","Apr. 9","Apr. 10","Apr. 11","Apr. 12","Apr. 13","Apr. 16","Apr. 17","Apr. 18","Apr. 19","Apr. 20","Apr. 23","Apr. 24","Apr. 25","Apr. 26","Apr. 27","Apr. 30","May 1","May 2","May 3","May 4","May 7","May 8","May 9","May 10","May 11","May 14","May 15","May 16","May 17","May 18","May 21","May 22","May 23","May 24","May 25","May 28","May 29","May 30","May 31","Jun. 1","Jun. 4","Jun. 5","Jun. 6","Jun. 7","Jun. 8","Jun. 11","Jun. 12","Jun. 13","Jun. 14","Jun. 15","Jun. 18","Jun. 19","Jul. 4","Aug. 17","Sep. 4" 2 | ,"5631K","5632K","5633K","5634K","5635K","5641K","5642K","5643K","5644K","5645K","5681K","5682K","5683K","5754K","5651K","5652K","5653K","5654K","5655K","5671K","5672K","5673K","5674K","5675K","5781K","5783K","5782K","5784K","5785K","5691K","5692K","5693K","5694K","5695K","5701K","5702K","5703K","5704K","5705K","5711K","5712K","5713K","5714K","5715K","5721K","5722K","5723K","5731K","5732K","5733K","5734K","5735K","5741K","5742K","5743K","5744K","5745K","5751K","5752K","5753K","5684K","5755K","5761K","5762K","5763K","5764K","5765K","5802K","5775K","5662K","5665K","5663K","5664K","5661K","5791K","5792K","5793K","5795K","5794K","5821K","5803K","5804K","5805K","5811K","5812K","5813K","5814K","5815K","5801K","5822K","5823K","5824K","5825K","5831K","5832K","5833K","5834K","5835K","5841K","5842K","5843K","5844K","5845K","5852K","5853K","5851K","5854K","5855K","5861K","5862K","5863K","5864K","5865K","5871K","5872K","5873K","5874K","5875K","5881K","5882K","5883K","5891K","5892K","5893K","5894K","5895K","5901K","5902K","5903K","5904K","5905K","5911K","5912K","5913K","5915K","5914K","5941K","5942K","5943K","5944K","5945K","5931K","5932K","5933K","5934K","5935K","5921K","5922K","5923K","5924K","5925K","5951K","5952K","5953K","5954K","5955K","5961K","5962K","5963K","5964K","5965K","5983K","5972K","5995K","5974K","5975K","5971K","5982K","5981K","5984K","5985K","5991K","5992K","5993K","5994K","5973K","6001K","6002K","6003K","6004K","6005K","6012K","6011K","6013K","6014K","6015K","6024K","5685K","6021K","6022K","6023K" 3 | ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 4 | "Showcase 1",50969,21901,32815,44432,24273,30554,20963,28941,25851,28800,37703,34774,25268,44044,32516,30827,40374,27698,23590,38625,24026,37449,34268,22281,22890,24226,25448,32525,36799,27380,25903,31769,22853,23202,20721,28451,26154,27019,51959,35811,24885,24648,30707,23744,45078,20773,30892,29971,37423,33593,24866,24628,24827,29248,24818,28762,31838,22268,38892,22599,31705,23299,21394,22589,30573,33009,19612,28550,49937,36915,33400,34516,31516,51108,23981,26383,39801,39201,19563,20418,28465,22356,24150,20425,23926,20860,35526,20912,27426,26393,25329,22434,31933,23986,24729,21747,27273,21681,29324,35874,30397,27310,28414,32535,22886,29842,35954,27883,31268,21563,39642,21862,33499,24313,26809,29674,21711,25618,35504,23327,34581,25918,20418,26511,28288,30348,34428,26732,29631,30253,30256,21399,30988,26536,39924,26254,29137,32666,30706,34805,33343,29671,20408,30406,20990,32391,20828,36439,31785,27663,30291,33480,28714,36803,24281,23841,33844,31809,28309,27332,28957,54579,28649,26854,20962,38787,26738,28958,28604,25269,30624,25366,31328,36813,31434,30321,36414,34736,21707,38297,28996,27690,29426,21711,29307,25263,26993,29390,34920,30323,46638 5 | "Showcase 2",45429,34061,53186,31428,22320,24337,41373,45437,41125,36319,38752,28450,39745,40894,30608,30463,29405,31290,38597,33917,43036,36623,31681,29080,34137,24925,36174,23705,24897,37776,19792,20182,36070,32357,24054,21527,30623,34089,58458,69485,29349,23955,28244,19756,28336,34646,26712,24349,24366,23276,34144,28136,33508,38836,27654,23097,23255,33801,35658,42174,34238,29515,26949,22797,25211,29737,23084,24891,71628,29460,24974,32693,26937,30939,32252,29551,22193,29344,33551,29524,23504,36954,18349,19508,20068,27319,26055,25875,29831,30918,36442,28854,36664,24753,25264,30843,32968,28487,27806,22513,25585,23677,29286,29299,31501,21902,20320,25830,32687,30493,20043,28598,34432,27386,19693,25812,24631,30858,26993,27570,23566,20908,25541,32310,37393,21827,26934,28480,39620,39263,34607,26375,43998,25357,33251,42675,20267,32390,20513,32782,29488,27498,34453,36562,19827,49869,30602,28979,36419,29993,36548,24984,22407,37746,30764,21255,37125,23904,37776,29317,49419,27712,31352,34808,33302,30317,26784,25612,22438,23548,29445,26525,30571,25755,38715,29281,38505,33612,25820,20344,25938,41765,34304,26277,26617,32646,33337,26314,31278,31285,42319 6 | ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 7 | "Bid 1",42000,14000,32000,27000,18750,27222,25000,35000,22500,21300,21567,35500,26000,38500,24500,27507,30000,36500,25000,36000,24000,37000,22575,20000,18200,25000,23000,36750,35000,38000,23045,22000,20000,31100,12500,29000,25400,22000,32750,32000,22486,29600,29000,23225,37000,17000,32450,28500,29100,24021,25000,24350,18500,25000,28750,25500,26000,21569,41000,34500,32614,22000,15000,14532,24000,28000,17500,24533,32000,33000,26132,27000,23000,50972,15500,27000,35000,27852,28500,22000,24500,19000,27000,25000,20000,18500,23000,20000,19000,34000,24000,22575,21995,27000,22500,26400,27000,20000,31250,38000,25000,26000,26000,23000,22100,29300,22500,22000,27000,18500,24240,16500,23000,19500,23000,24075,17500,5500,24000,18358,27000,16522,24622,21500,22475,25000,28000,18000,27000,32000,26550,20950,43200,22500,22135,21000,27237,24500,23000,33000,22000,22000,18200,18550,23990,27200,22000,15500,32500,18500,27000,27500,26576,27000,22000,28900,22253,27000,22000,26000,36000,40000,30450,25500,22000,23000,33000,24500,24000,35000,26121,21000,25700,30000,27000,31000,23723,28000,17500,27000,23500,23000,27000,19000,25300,25500,41000,23052,27800,27000,29900 8 | "Bid 2",34000,59900,45000,38000,23000,18525,32000,45000,32000,27500,23800,18975,35555,35000,29765,34000,23000,25000,24000,42333,27000,24500,27500,29500,25000,28000,22000,27500,22000,37000,22500,19900,32100,27590,20000,26500,20000,28000,58000,48000,30100,21000,22750,26500,27000,27500,26000,24250,26250,31000,28500,25000,20500,34000,24250,33250,15000,29250,25700,30000,34000,28950,26420,22000,27500,23456,21000,30500,28000,25200,19401,25000,28000,32310,27500,30000,23000,28000,30000,22750,33000,24500,20400,27000,25000,25000,24859,30100,23500,24150,33500,36500,32000,24000,27890,22000,27717,31000,26400,21000,27100,24000,27500,23695,23200,21500,21000,26535,19500,26500,26000,31860,25000,25496,24500,31000,23000,17000,34800,29000,21000,24000,23000,25000,27500,22525,23500,21000,38000,30000,32000,22000,35000,23000,23374,28999,26000,27500,21100,30777,18000,24000,36100,24000,18000,33057,28000,25500,28000,23000,23100,18200,24500,35000,22000,18605,31229,20000,34000,28300,38675,18522,33500,22000,26262,24500,23000,25000,22013,18500,28000,24050,31000,31000,32000,30972,28543,38000,26000,22300,29972,36000,30000,24750,28000,26800,26888,16000,30022,21000,33000 9 | ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 10 | "Difference 1",8969,7901,815,17432,5523,3332,-4037,-6059,3351,7500,16136,-726,-732,5544,8016,3320,10374,-8802,-1410,2625,26,449,11693,2281,4690,-774,2448,-4225,1799,-10620,2858,9769,2853,-7898,8221,-549,754,5019,19209,3811,2399,-4952,1707,519,8078,3773,-1558,1471,8323,9572,-134,278,6327,4248,-3932,3262,5838,699,-2108,-11901,-909,1299,6394,8057,6573,5009,2112,4017,17937,3915,7268,7516,8516,136,8481,-617,4801,11349,-8937,-1582,3965,3356,-2850,-4575,3926,2360,12526,912,8426,-7607,1329,-141,9938,-3014,2229,-4653,273,1681,-1926,-2126,5397,1310,2414,9535,786,542,13454,5883,4268,3063,15402,5362,10499,4813,3809,5599,4211,20118,11504,4969,7581,9396,-4204,5011,5813,5348,6428,8732,2631,-1747,3706,449,-12212,4036,17789,5254,1900,8166,7706,1805,11343,7671,2208,11856,-3000,5191,-1172,20939,-715,9163,3291,5980,2138,9803,2281,-5059,11591,4809,6309,1332,-7043,14579,-1801,1354,-1038,15787,-6262,4458,4604,-9731,4503,4366,5628,6813,4434,-679,12691,6736,4207,11297,5496,4690,2426,2711,4007,-237,-14007,6338,7120,3323,16738 11 | "Difference 2",11429,-25839,8186,-6572,-680,5812,9373,437,9125,8819,14952,9475,4190,5894,843,-3537,6405,6290,14597,-8416,16036,12123,4181,-420,9137,-3075,14174,-3795,2897,776,-2708,282,3970,4767,4054,-4973,10623,6089,458,21485,-751,2955,5494,-6744,1336,7146,712,99,-1884,-7724,5644,3136,13008,4836,3404,-10153,8255,4551,9958,12174,238,565,529,797,-2289,6281,2084,-5609,43628,4260,5573,7693,-1063,-1371,4752,-449,-807,1344,3551,6774,-9496,12454,-2051,-7492,-4932,2319,1196,-4225,6331,6768,2942,-7646,4664,753,-2626,8843,5251,-2513,1406,1513,-1515,-323,1786,5604,8301,402,-680,-705,13187,3993,-5957,-3262,9432,1890,-4807,-5188,1631,13858,-7807,-1430,2566,-3092,2541,7310,9893,-698,3434,7480,1620,9263,2607,4375,8998,2357,9877,13676,-5733,4890,-587,2005,11488,3498,-1647,12562,1827,16812,2602,3479,8419,6993,13448,6784,-2093,2746,8764,2650,5896,3904,3776,1017,10744,9190,-2148,12808,7040,5817,3784,612,425,5048,1445,2475,-429,-5245,6715,-1691,9962,-4388,-180,-1956,-4034,5765,4304,1527,-1383,5846,6449,10314,1256,10285,9319 12 | -------------------------------------------------------------------------------- /code/showcases.2012.csv: -------------------------------------------------------------------------------- 1 | ,"Sep. 24","Sep. 25","Sep. 26","Sep. 27","Sep. 28","Oct. 1","Oct. 2","Oct. 3","Oct. 4","Oct. 5","Oct. 8","Oct. 9","Oct. 10","Oct. 11","Oct. 12","Oct. 15","Oct. 16","Oct. 17","Oct. 18","Oct. 19","Oct. 22","Oct. 23","Oct. 24","Oct. 25","Oct. 26","Oct. 29","Oct. 30","Oct. 31","Nov. 1","Nov. 2","Nov. 5","Nov. 6","Nov. 7","Nov. 8","Nov. 9","Nov. 12","Nov. 13","Nov. 14","Nov. 15","Nov. 16","Nov. 19","Nov. 20","Nov. 21","Dec. 3","Dec. 4","Dec. 5","Dec. 6","Dec. 7","Dec. 10","Dec. 11","Dec. 12","Dec. 13","Dec. 14","Dec. 17","Dec. 18","Dec. 19","Dec. 20","Dec. 21","Dec. 24","Dec. 26","Dec. 27","Dec. 28","Dec. 31","Jan. 1","Jan. 2","Jan. 3","Jan. 4","Jan. 7","Jan. 8","Jan. 9","Jan. 10","Jan. 11","Jan. 14","Jan. 15","Jan. 16","Jan. 17","Jan. 18","Jan. 22","Jan. 23","Jan. 24","Jan. 25","Jan. 28","Jan. 29","Jan. 30","Jan. 31","Feb. 1","Feb. 4","Feb. 5","Feb. 6","Feb. 7","Feb. 8","Feb. 11","Feb. 12","Feb. 13","Feb. 14","Feb. 15","Feb. 18","Feb. 19","Feb. 20","Feb. 21","Feb. 22","Feb. 25","Feb. 26","Feb. 27","Feb. 28","Mar. 1","Mar. 4","Mar. 5","Mar. 6","Mar. 7","Mar. 8","Mar. 11","Mar. 12","Mar. 13","Mar. 14","Mar. 15","Mar. 18","Mar. 19","Mar. 20","Mar. 25","Mar. 26","Mar. 27" 2 | ,"6031K","6032K","6033K","6034K","6035K","6081K","6082K","6083K","6084K","6041K","6085K","6042K","6043K","6044K","6045K","6171K","6172K","6173K","6174K","6715K","6051K","6052K","6053K","6054K","6055K","6091K","6092K","6093K","6094K","6095K","6101K","6102K","6103K","6104K","6105K","6071K","6072K","6073K","6074K","6075K","6113K","6112K","6111K","6121K","6122K","6123K","6124K","6125K","6131K","6132K","6133K","6134K","6135K","6141K","6142K","6143K","6144K","6145K","6151K","6153K","6221K","6155K","6161K","6162K","6163K","6164K","6165K","6201K","6202K","6203K","6204K","6205K","6181K","6182K","6183K","6184K","6185K","6231K","6233K","6234K","6235K","6211K","6212K","6213K","6214K","6215K","6061K","6062K","6063K","6064K","6152K","6154K","6222K","6223K","6224K","6225K","6192K","6195K","6193K","6191K","6194K","6241K","6242K","6243K","6244K","6245K","6251K","6252K","6253K","6254K","6255K","6261K","6262K","6263K","6264K","6265K","6331K","6271K","6273K","6281K","6283K","6282K" 3 | "Showcase 1",40811,31259,41943,24946,26257,49928,30744,37671,32255,21983,40311,28573,28510,27341,29393,24379,24289,32784,41995,39939,46829,24413,36607,43902,36820,27575,24459,31749,22466,25809,35252,58342,21981,40294,45433,27480,28868,30864,36577,38468,34353,26262,23515,41374,22476,27762,28744,46872,32416,30296,27813,34608,25540,33795,28981,41280,28400,26462,36419,22716,35855,23261,48442,25643,25975,52557,21258,34640,33798,33513,38934,24988,27614,31816,39315,30396,37649,22542,22576,27288,40830,29943,28583,36407,27791,22703,29633,20869,29412,23437,27266,32922,27268,27382,27736,41781,38875,46339,24422,38902,40408,30764,27440,29271,37446,34763,22992,37517,27677,23988,29323,35379,34330,27793,22412,29528,22774,25375,24949,23662,23704,20898 4 | "Showcase 2",62485,32972,24755,34665,48635,42621,22253,24251,45871,31820,31399,33797,37252,30320,19290,32262,20545,34727,22554,21969,23624,38948,29310,43453,27734,30919,23309,33824,35704,40812,21261,33968,25903,35784,53263,27572,38588,20660,35617,26715,25832,28869,37668,24374,30649,28659,27518,45829,26685,46648,25761,29552,25336,28428,44564,22311,22564,38649,25419,21470,25510,43850,66996,37319,29509,32888,35368,21263,29856,25770,45916,20403,48281,33822,21361,29336,40328,28725,23928,32706,32349,39844,36804,25614,30964,28525,28269,30290,25815,33598,23318,23880,35341,22580,28976,28926,34637,34255,38823,42309,46833,42965,39296,28959,23576,35926,26521,26745,24335,27439,21340,43923,24585,27441,24285,23667,22812,31986,30696,22329,34325,23876 5 | ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 6 | "Bid 1",22000,10000,39500,21513,23420,36500,26500,42000,25000,21650,22000,20582,14575,21200,30000,27000,23491,32500,28450,24000,27000,19425,32813,27500,28500,28000,23313,42500,21400,23000,29500,26968,21000,32364,32000,23000,29800,18200,27500,28500,30000,30500,17823,31500,23000,19000,18500,16000,30000,25000,42000,30000,18500,27500,18965,37500,20600,34000,26500,22000,42000,21000,36000,25620,9950,30200,9000,27000,20000,33225,34500,32125,35000,32000,24500,24950,35000,19152,18750,23000,30000,37000,30000,32000,30000,22782,23000,22000,27000,28000,28000,21650,25000,26000,23500,28900,31500,41000,24000,35000,26000,36000,30736,27300,38000,18000,25700,27436,22000,26129,40000,21000,27000,27300,25000,27000,27000,36000,20500,26000,23800,28000 7 | "Bid 2",40500,21000,22500,32000,35000,34000,18000,26000,29000,33000,29000,27000,30500,28000,25000,35000,31500,29000,17500,27000,24175,27528,22000,33001,26000,22548,17000,15000,25044,27000,17500,31500,18000,27500,37000,21433,29000,25000,30578,20500,23250,27830,28000,19652,27500,28500,28500,38000,30000,33000,38500,28000,22307,19500,29600,20000,23000,35000,28000,25150,31000,32000,45000,22000,22000,36000,23000,20000,23000,28500,37450,29200,21850,25800,18000,31925,37000,29100,20000,24000,35500,23750,27500,22632,26400,32324,29000,26500,26000,32300,28666,19500,25000,35000,27000,29999,29300,27500,27345,23500,48750,43000,36000,30000,18888,25999,26500,32500,21000,25000,26000,31000,21500,18500,28500,25500,22500,32000,31000,20000,34029,25000 8 | ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 9 | "Difference 1",18811,21259,2443,3433,2837,13428,4244,-4329,7255,333,18311,7991,13935,6141,-607,-2621,798,284,13545,15939,19829,4988,3794,16402,8320,-425,1146,-10751,1066,2809,5752,31374,981,7930,13433,4480,-932,12664,9077,9968,4353,-4238,5692,9874,-524,8762,10244,30872,2416,5296,-14187,4608,7040,6295,10016,3780,7800,-7538,9919,716,-6145,2261,12442,23,16025,22357,12258,7640,13798,288,4434,-7137,-7386,-184,14815,5446,2649,3390,3826,4288,10830,-7057,-1417,4407,-2209,-79,6633,-1131,2412,-4563,-734,11272,2268,1382,4236,12881,7375,5339,422,3902,14408,-5236,-3296,1971,-554,16763,-2708,10081,5677,-2141,-10677,14379,7330,493,-2588,2528,-4226,-10625,4449,-2338,-96,-7102 10 | "Difference 2",21985,11972,2255,2665,13635,8621,4253,-1749,16871,-1180,2399,6797,6752,2320,-5710,-2738,-10955,5727,5054,-5031,-551,11420,7310,10452,1734,8371,6309,18824,10660,13812,3761,2468,7903,8284,16263,6139,9588,-4340,5039,6215,2582,1039,9668,4722,3149,159,-982,7829,-3315,13648,-12739,1552,3029,8928,14964,2311,-436,3649,-2581,-3680,-5490,11850,21996,15319,7509,-3112,12368,1263,6856,-2730,8466,-8797,26431,8022,3361,-2589,3328,-375,3928,8706,-3151,16094,9304,2982,4564,-3799,-731,3790,-185,1298,-5348,4380,10341,-12420,1976,-1073,5337,6755,11478,18809,-1917,-35,3296,-1041,4688,9927,21,-5755,3335,2439,-4660,12923,3085,8941,-4215,-1833,312,-14,-304,2329,296,-1124 11 | -------------------------------------------------------------------------------- /code/survey.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Stats", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2010 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | import sys 10 | import gzip 11 | import os 12 | 13 | class Record(object): 14 | """Represents a record.""" 15 | 16 | class Respondent(Record): 17 | """Represents a respondent.""" 18 | 19 | class Pregnancy(Record): 20 | """Represents a pregnancy.""" 21 | 22 | class Table(object): 23 | """Represents a table as a list of objects""" 24 | 25 | def __init__(self): 26 | self.records = [] 27 | 28 | def __len__(self): 29 | return len(self.records) 30 | 31 | def ReadFile(self, data_dir, filename, fields, constructor, n=None): 32 | """Reads a compressed data file builds one object per record. 33 | 34 | Args: 35 | data_dir: string directory name 36 | filename: string name of the file to read 37 | 38 | fields: sequence of (name, start, end, case) tuples specifying 39 | the fields to extract 40 | 41 | constructor: what kind of object to create 42 | """ 43 | filename = os.path.join(data_dir, filename) 44 | 45 | if filename.endswith('gz'): 46 | fp = gzip.open(filename) 47 | else: 48 | fp = open(filename) 49 | 50 | for i, line in enumerate(fp): 51 | if i == n: 52 | break 53 | record = self.MakeRecord(line, fields, constructor) 54 | self.AddRecord(record) 55 | fp.close() 56 | 57 | def MakeRecord(self, line, fields, constructor): 58 | """Scans a line and returns an object with the appropriate fields. 59 | 60 | Args: 61 | line: string line from a data file 62 | 63 | fields: sequence of (name, start, end, cast) tuples specifying 64 | the fields to extract 65 | 66 | constructor: callable that makes an object for the record. 67 | 68 | Returns: 69 | Record with appropriate fields. 70 | """ 71 | obj = constructor() 72 | for (field, start, end, cast) in fields: 73 | try: 74 | s = line[start-1:end] 75 | val = cast(s) 76 | except ValueError: 77 | # print(line) 78 | # print(field, start, end, s) 79 | val = 'NA' 80 | setattr(obj, field, val) 81 | return obj 82 | 83 | def AddRecord(self, record): 84 | """Adds a record to this table. 85 | 86 | Args: 87 | record: an object of one of the record types. 88 | """ 89 | self.records.append(record) 90 | 91 | def ExtendRecords(self, records): 92 | """Adds records to this table. 93 | 94 | Args: 95 | records: a sequence of record object 96 | """ 97 | self.records.extend(records) 98 | 99 | def Recode(self): 100 | """Child classes can override this to recode values.""" 101 | pass 102 | 103 | 104 | class Respondents(Table): 105 | """Represents the respondent table.""" 106 | 107 | def ReadRecords(self, data_dir='.', n=None): 108 | filename = self.GetFilename() 109 | self.ReadFile(data_dir, filename, self.GetFields(), Respondent, n) 110 | self.Recode() 111 | 112 | def GetFilename(self): 113 | return '2002FemResp.dat.gz' 114 | 115 | def GetFields(self): 116 | """Returns a tuple specifying the fields to extract. 117 | 118 | The elements of the tuple are field, start, end, case. 119 | 120 | field is the name of the variable 121 | start and end are the indices as specified in the NSFG docs 122 | cast is a callable that converts the result to int, float, etc. 123 | """ 124 | return [ 125 | ('caseid', 1, 12, int), 126 | ] 127 | 128 | class Pregnancies(Table): 129 | """Contains survey data about a Pregnancy.""" 130 | 131 | def ReadRecords(self, data_dir='.', n=None): 132 | filename = self.GetFilename() 133 | self.ReadFile(data_dir, filename, self.GetFields(), Pregnancy, n) 134 | self.Recode() 135 | 136 | def GetFilename(self): 137 | return '2002FemPreg.dat.gz' 138 | 139 | def GetFields(self): 140 | """Gets information about the fields to extract from the survey data. 141 | 142 | Documentation of the fields for Cycle 6 is at 143 | http://nsfg.icpsr.umich.edu/cocoon/WebDocs/NSFG/public/index.htm 144 | 145 | Returns: 146 | sequence of (name, start, end, type) tuples 147 | """ 148 | return [ 149 | ('caseid', 1, 12, int), 150 | ('nbrnaliv', 22, 22, int), 151 | ('babysex', 56, 56, int), 152 | ('birthwgt_lb', 57, 58, int), 153 | ('birthwgt_oz', 59, 60, int), 154 | ('prglength', 275, 276, int), 155 | ('outcome', 277, 277, int), 156 | ('birthord', 278, 279, int), 157 | ('agepreg', 284, 287, int), 158 | ('finalwgt', 423, 440, float), 159 | ] 160 | 161 | def Recode(self): 162 | for rec in self.records: 163 | 164 | # divide mother's age by 100 165 | try: 166 | if rec.agepreg != 'NA': 167 | rec.agepreg /= 100.0 168 | except AttributeError: 169 | pass 170 | 171 | # convert weight at birth from lbs/oz to total ounces 172 | # note: there are some very low birthweights 173 | # that are almost certainly errors, but for now I am not 174 | # filtering 175 | try: 176 | if (rec.birthwgt_lb != 'NA' and rec.birthwgt_lb < 20 and 177 | rec.birthwgt_oz != 'NA' and rec.birthwgt_oz <= 16): 178 | rec.totalwgt_oz = rec.birthwgt_lb * 16 + rec.birthwgt_oz 179 | else: 180 | rec.totalwgt_oz = 'NA' 181 | except AttributeError: 182 | pass 183 | 184 | 185 | def main(name, data_dir='.'): 186 | resp = Respondents() 187 | resp.ReadRecords(data_dir) 188 | print('Number of respondents', len(resp.records)) 189 | 190 | preg = Pregnancies() 191 | preg.ReadRecords(data_dir) 192 | print('Number of pregnancies', len(preg.records)) 193 | 194 | 195 | if __name__ == '__main__': 196 | main(*sys.argv) 197 | -------------------------------------------------------------------------------- /code/thinkstats.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Stats", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2010 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | 8 | import bisect 9 | import random 10 | 11 | def Mean(t): 12 | """Computes the mean of a sequence of numbers. 13 | 14 | Args: 15 | t: sequence of numbers 16 | 17 | Returns: 18 | float 19 | """ 20 | return float(sum(t)) / len(t) 21 | 22 | 23 | def MeanVar(t): 24 | """Computes the mean and variance of a sequence of numbers. 25 | 26 | Args: 27 | t: sequence of numbers 28 | 29 | Returns: 30 | tuple of two floats 31 | """ 32 | mu = Mean(t) 33 | var = Var(t, mu) 34 | return mu, var 35 | 36 | 37 | def Trim(t, p=0.01): 38 | """Trims the largest and smallest elements of t. 39 | 40 | Args: 41 | t: sequence of numbers 42 | p: fraction of values to trim off each end 43 | 44 | Returns: 45 | sequence of values 46 | """ 47 | n = int(p * len(t)) 48 | t = sorted(t)[n:-n] 49 | return t 50 | 51 | 52 | def Jitter(values, jitter=0.5): 53 | """Jitters the values by adding a uniform variate in (-jitter, jitter).""" 54 | return [x + random.uniform(-jitter, jitter) for x in values] 55 | 56 | 57 | def TrimmedMean(t, p=0.01): 58 | """Computes the trimmed mean of a sequence of numbers. 59 | 60 | Side effect: sorts the list. 61 | 62 | Args: 63 | t: sequence of numbers 64 | p: fraction of values to trim off each end 65 | 66 | Returns: 67 | float 68 | """ 69 | t = Trim(t, p) 70 | return Mean(t) 71 | 72 | 73 | def TrimmedMeanVar(t, p=0.01): 74 | """Computes the trimmed mean and variance of a sequence of numbers. 75 | 76 | Side effect: sorts the list. 77 | 78 | Args: 79 | t: sequence of numbers 80 | p: fraction of values to trim off each end 81 | 82 | Returns: 83 | float 84 | """ 85 | t = Trim(t, p) 86 | mu, var = MeanVar(t) 87 | return mu, var 88 | 89 | 90 | def Var(t, mu=None): 91 | """Computes the variance of a sequence of numbers. 92 | 93 | Args: 94 | t: sequence of numbers 95 | mu: value around which to compute the variance; by default, 96 | computes the mean. 97 | 98 | Returns: 99 | float 100 | """ 101 | if mu is None: 102 | mu = Mean(t) 103 | 104 | # compute the squared deviations and return their mean. 105 | dev2 = [(x - mu)**2 for x in t] 106 | var = Mean(dev2) 107 | return var 108 | 109 | 110 | def Binom(n, k, d={}): 111 | """Compute the binomial coefficient "n choose k". 112 | 113 | Args: 114 | n: number of trials 115 | k: number of successes 116 | d: map from (n,k) tuples to cached results 117 | 118 | Returns: 119 | int 120 | """ 121 | if k == 0: 122 | return 1 123 | if n == 0: 124 | return 0 125 | 126 | try: 127 | return d[n, k] 128 | except KeyError: 129 | res = Binom(n-1, k, d) + Binom(n-1, k-1, d) 130 | d[n, k] = res 131 | return res 132 | 133 | 134 | class Interpolator(object): 135 | """Represents a mapping between sorted sequences; performs linear interp. 136 | 137 | Attributes: 138 | xs: sorted list 139 | ys: sorted list 140 | """ 141 | def __init__(self, xs, ys): 142 | self.xs = xs 143 | self.ys = ys 144 | 145 | def Lookup(self, x): 146 | """Looks up x and returns the corresponding value of y.""" 147 | return self._Bisect(x, self.xs, self.ys) 148 | 149 | def Reverse(self, y): 150 | """Looks up y and returns the corresponding value of x.""" 151 | return self._Bisect(y, self.ys, self.xs) 152 | 153 | def _Bisect(self, x, xs, ys): 154 | """Helper function.""" 155 | if x <= xs[0]: 156 | return ys[0] 157 | if x >= xs[-1]: 158 | return ys[-1] 159 | i = bisect.bisect(xs, x) 160 | frac = 1.0 * (x - xs[i-1]) / (xs[i] - xs[i-1]) 161 | y = ys[i-1] + frac * 1.0 * (ys[i] - ys[i-1]) 162 | return y 163 | 164 | 165 | -------------------------------------------------------------------------------- /code/train.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | from dice import Dice 10 | import thinkplot 11 | 12 | 13 | class Train(Dice): 14 | """Represents hypotheses about how many trains the company has. 15 | 16 | The likelihood function for the train problem is the same as 17 | for the Dice problem. 18 | """ 19 | 20 | 21 | def main(): 22 | hypos = range(1, 1001) 23 | suite = Train(hypos) 24 | 25 | suite.Update(60) 26 | print(suite.Mean()) 27 | 28 | thinkplot.PrePlot(1) 29 | thinkplot.Pmf(suite) 30 | thinkplot.Save(root='train1', 31 | xlabel='Number of trains', 32 | ylabel='Probability', 33 | formats=['pdf', 'eps']) 34 | 35 | 36 | if __name__ == '__main__': 37 | main() 38 | -------------------------------------------------------------------------------- /code/train2.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | from dice import Dice 10 | import thinkplot 11 | 12 | class Train(Dice): 13 | """The likelihood function for the train problem is the same as 14 | for the Dice problem.""" 15 | 16 | 17 | def Mean(suite): 18 | total = 0 19 | for hypo, prob in suite.Items(): 20 | total += hypo * prob 21 | return total 22 | 23 | 24 | def MakePosterior(high, dataset): 25 | hypos = range(1, high+1) 26 | suite = Train(hypos) 27 | suite.name = str(high) 28 | 29 | for data in dataset: 30 | suite.Update(data) 31 | 32 | thinkplot.Pmf(suite) 33 | return suite 34 | 35 | 36 | def main(): 37 | dataset = [30, 60, 90] 38 | 39 | for high in [500, 1000, 2000]: 40 | suite = MakePosterior(high, dataset) 41 | print(high, suite.Mean()) 42 | 43 | thinkplot.Save(root='train2', 44 | xlabel='Number of trains', 45 | ylabel='Probability') 46 | 47 | 48 | if __name__ == '__main__': 49 | main() 50 | -------------------------------------------------------------------------------- /code/train3.py: -------------------------------------------------------------------------------- 1 | """This file contains code for use with "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | import thinkbayes 10 | import thinkplot 11 | 12 | from thinkbayes import Pmf, Percentile 13 | from dice import Dice 14 | 15 | 16 | class Train(Dice): 17 | """Represents hypotheses about how many trains the company has.""" 18 | 19 | 20 | class Train2(Dice): 21 | """Represents hypotheses about how many trains the company has.""" 22 | 23 | def __init__(self, hypos, alpha=1.0): 24 | """Initializes the hypotheses with a power law distribution. 25 | 26 | hypos: sequence of hypotheses 27 | alpha: parameter of the power law prior 28 | """ 29 | Pmf.__init__(self) 30 | for hypo in hypos: 31 | self.Set(hypo, hypo**(-alpha)) 32 | self.Normalize() 33 | 34 | 35 | def MakePosterior(high, dataset, constructor): 36 | """Makes and updates a Suite. 37 | 38 | high: upper bound on the range of hypotheses 39 | dataset: observed data to use for the update 40 | constructor: function that makes a new suite 41 | 42 | Returns: posterior Suite 43 | """ 44 | hypos = range(1, high+1) 45 | suite = constructor(hypos) 46 | suite.name = str(high) 47 | 48 | for data in dataset: 49 | suite.Update(data) 50 | 51 | return suite 52 | 53 | 54 | def ComparePriors(): 55 | """Runs the analysis with two different priors and compares them.""" 56 | dataset = [60] 57 | high = 1000 58 | 59 | thinkplot.Clf() 60 | thinkplot.PrePlot(num=2) 61 | 62 | constructors = [Train, Train2] 63 | labels = ['uniform', 'power law'] 64 | 65 | for constructor, label in zip(constructors, labels): 66 | suite = MakePosterior(high, dataset, constructor) 67 | suite.name = label 68 | thinkplot.Pmf(suite) 69 | 70 | thinkplot.Save(root='train4', 71 | xlabel='Number of trains', 72 | ylabel='Probability') 73 | 74 | def main(): 75 | ComparePriors() 76 | 77 | dataset = [30, 60, 90] 78 | 79 | thinkplot.Clf() 80 | thinkplot.PrePlot(num=3) 81 | 82 | for high in [500, 1000, 2000]: 83 | suite = MakePosterior(high, dataset, Train2) 84 | print(high, suite.Mean()) 85 | 86 | thinkplot.Save(root='train3', 87 | xlabel='Number of trains', 88 | ylabel='Probability') 89 | 90 | interval = Percentile(suite, 5), Percentile(suite, 95) 91 | print(interval) 92 | 93 | cdf = thinkbayes.MakeCdfFromPmf(suite) 94 | interval = cdf.Percentile(5), cdf.Percentile(95) 95 | print(interval) 96 | 97 | 98 | if __name__ == '__main__': 99 | main() 100 | -------------------------------------------------------------------------------- /code/variability.py: -------------------------------------------------------------------------------- 1 | """This file contains code used in "Think Bayes", 2 | by Allen B. Downey, available from greenteapress.com 3 | 4 | Copyright 2012 Allen B. Downey 5 | License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html 6 | """ 7 | from __future__ import print_function 8 | 9 | import math 10 | import numpy 11 | import pickle 12 | import random 13 | import scipy 14 | 15 | import brfss 16 | 17 | import thinkplot 18 | import thinkbayes 19 | import thinkstats 20 | 21 | import matplotlib.pyplot as pyplot 22 | 23 | 24 | NUM_SIGMAS = 1 25 | 26 | class Height(thinkbayes.Suite, thinkbayes.Joint): 27 | """Hypotheses about parameters of the distribution of height.""" 28 | 29 | def __init__(self, mus, sigmas, name=''): 30 | """Makes a prior distribution for mu and sigma based on a sample. 31 | 32 | mus: sequence of possible mus 33 | sigmas: sequence of possible sigmas 34 | name: string name for the Suite 35 | """ 36 | pairs = [(mu, sigma) 37 | for mu in mus 38 | for sigma in sigmas] 39 | 40 | thinkbayes.Suite.__init__(self, pairs, name=name) 41 | 42 | def Likelihood(self, data, hypo): 43 | """Computes the likelihood of the data under the hypothesis. 44 | 45 | Args: 46 | hypo: tuple of hypothetical mu and sigma 47 | data: float sample 48 | 49 | Returns: 50 | likelihood of the sample given mu and sigma 51 | """ 52 | x = data 53 | mu, sigma = hypo 54 | like = scipy.stats.norm.pdf(x, mu, sigma) 55 | return like 56 | 57 | def LogLikelihood(self, data, hypo): 58 | """Computes the log likelihood of the data under the hypothesis. 59 | 60 | Args: 61 | data: a list of values 62 | hypo: tuple of hypothetical mu and sigma 63 | 64 | Returns: 65 | log likelihood of the sample given mu and sigma (unnormalized) 66 | """ 67 | x = data 68 | mu, sigma = hypo 69 | loglike = EvalGaussianLogPdf(x, mu, sigma) 70 | return loglike 71 | 72 | def LogUpdateSetFast(self, data): 73 | """Updates the suite using a faster implementation. 74 | 75 | Computes the sum of the log likelihoods directly. 76 | 77 | Args: 78 | data: sequence of values 79 | """ 80 | xs = tuple(data) 81 | n = len(xs) 82 | 83 | for hypo in self.Values(): 84 | mu, sigma = hypo 85 | total = Summation(xs, mu) 86 | loglike = -n * math.log(sigma) - total / 2 / sigma**2 87 | self.Incr(hypo, loglike) 88 | 89 | def LogUpdateSetMeanVar(self, data): 90 | """Updates the suite using ABC and mean/var. 91 | 92 | Args: 93 | data: sequence of values 94 | """ 95 | xs = data 96 | n = len(xs) 97 | 98 | m = numpy.mean(xs) 99 | s = numpy.std(xs) 100 | 101 | self.LogUpdateSetABC(n, m, s) 102 | 103 | def LogUpdateSetMedianIPR(self, data): 104 | """Updates the suite using ABC and median/iqr. 105 | 106 | Args: 107 | data: sequence of values 108 | """ 109 | xs = data 110 | n = len(xs) 111 | 112 | # compute summary stats 113 | median, s = MedianS(xs, num_sigmas=NUM_SIGMAS) 114 | print('median, s', median, s) 115 | 116 | self.LogUpdateSetABC(n, median, s) 117 | 118 | def LogUpdateSetABC(self, n, m, s): 119 | """Updates the suite using ABC. 120 | 121 | n: sample size 122 | m: estimated central tendency 123 | s: estimated spread 124 | """ 125 | for hypo in sorted(self.Values()): 126 | mu, sigma = hypo 127 | 128 | # compute log likelihood of m, given hypo 129 | stderr_m = sigma / math.sqrt(n) 130 | loglike = EvalGaussianLogPdf(m, mu, stderr_m) 131 | 132 | #compute log likelihood of s, given hypo 133 | stderr_s = sigma / math.sqrt(2 * (n-1)) 134 | loglike += EvalGaussianLogPdf(s, sigma, stderr_s) 135 | 136 | self.Incr(hypo, loglike) 137 | 138 | 139 | def EvalGaussianLogPdf(x, mu, sigma): 140 | """Computes the log PDF of x given mu and sigma. 141 | 142 | x: float values 143 | mu, sigma: paramemters of Gaussian 144 | 145 | returns: float log-likelihood 146 | """ 147 | return scipy.stats.norm.logpdf(x, mu, sigma) 148 | 149 | 150 | def FindPriorRanges(xs, num_points, num_stderrs=3.0, median_flag=False): 151 | """Find ranges for mu and sigma with non-negligible likelihood. 152 | 153 | xs: sample 154 | num_points: number of values in each dimension 155 | num_stderrs: number of standard errors to include on either side 156 | 157 | Returns: sequence of mus, sequence of sigmas 158 | """ 159 | def MakeRange(estimate, stderr): 160 | """Makes a linear range around the estimate. 161 | 162 | estimate: central value 163 | stderr: standard error of the estimate 164 | 165 | returns: numpy array of float 166 | """ 167 | spread = stderr * num_stderrs 168 | array = numpy.linspace(estimate-spread, estimate+spread, num_points) 169 | return array 170 | 171 | # estimate mean and stddev of xs 172 | n = len(xs) 173 | if median_flag: 174 | m, s = MedianS(xs, num_sigmas=NUM_SIGMAS) 175 | else: 176 | m = numpy.mean(xs) 177 | s = numpy.std(xs) 178 | 179 | print('classical estimators', m, s) 180 | 181 | # compute ranges for m and s 182 | stderr_m = s / math.sqrt(n) 183 | mus = MakeRange(m, stderr_m) 184 | 185 | stderr_s = s / math.sqrt(2 * (n-1)) 186 | sigmas = MakeRange(s, stderr_s) 187 | 188 | return mus, sigmas 189 | 190 | 191 | def Summation(xs, mu, cache={}): 192 | """Computes the sum of (x-mu)**2 for x in t. 193 | 194 | Caches previous results. 195 | 196 | xs: tuple of values 197 | mu: hypothetical mean 198 | cache: cache of previous results 199 | """ 200 | try: 201 | return cache[xs, mu] 202 | except KeyError: 203 | ds = [(x-mu)**2 for x in xs] 204 | total = sum(ds) 205 | cache[xs, mu] = total 206 | return total 207 | 208 | 209 | def CoefVariation(suite): 210 | """Computes the distribution of CV. 211 | 212 | suite: Pmf that maps (x, y) to z 213 | 214 | Returns: Pmf object for CV. 215 | """ 216 | pmf = thinkbayes.Pmf() 217 | for (m, s), p in suite.Items(): 218 | pmf.Incr(s/m, p) 219 | return pmf 220 | 221 | 222 | def PlotCdfs(d, labels): 223 | """Plot CDFs for each sequence in a dictionary. 224 | 225 | Jitters the data and subtracts away the mean. 226 | 227 | d: map from key to sequence of values 228 | labels: map from key to string label 229 | """ 230 | thinkplot.Clf() 231 | for key, xs in d.items(): 232 | mu = thinkstats.Mean(xs) 233 | xs = thinkstats.Jitter(xs, 1.3) 234 | xs = [x-mu for x in xs] 235 | cdf = thinkbayes.MakeCdfFromList(xs) 236 | thinkplot.Cdf(cdf, label=labels[key]) 237 | thinkplot.Show() 238 | 239 | 240 | def PlotPosterior(suite, pcolor=False, contour=True): 241 | """Makes a contour plot. 242 | 243 | suite: Suite that maps (mu, sigma) to probability 244 | """ 245 | thinkplot.Clf() 246 | thinkplot.Contour(suite.GetDict(), pcolor=pcolor, contour=contour) 247 | 248 | thinkplot.Save(root='variability_posterior_%s' % suite.name, 249 | title='Posterior joint distribution', 250 | xlabel='Mean height (cm)', 251 | ylabel='Stddev (cm)') 252 | 253 | 254 | def PlotCoefVariation(suites): 255 | """Plot the posterior distributions for CV. 256 | 257 | suites: map from label to Pmf of CVs. 258 | """ 259 | thinkplot.Clf() 260 | thinkplot.PrePlot(num=2) 261 | 262 | pmfs = {} 263 | for label, suite in suites.items(): 264 | pmf = CoefVariation(suite) 265 | print('CV posterior mean', pmf.Mean()) 266 | cdf = thinkbayes.MakeCdfFromPmf(pmf, label) 267 | thinkplot.Cdf(cdf) 268 | 269 | pmfs[label] = pmf 270 | 271 | thinkplot.Save(root='variability_cv', 272 | xlabel='Coefficient of variation', 273 | ylabel='Probability') 274 | 275 | print('female bigger', thinkbayes.PmfProbGreater(pmfs['female'], pmfs['male'])) 276 | print('male bigger', thinkbayes.PmfProbGreater(pmfs['male'], pmfs['female'])) 277 | 278 | 279 | def PlotOutliers(samples): 280 | """Make CDFs showing the distribution of outliers.""" 281 | cdfs = [] 282 | for label, sample in samples.items(): 283 | outliers = [x for x in sample if x < 150] 284 | 285 | cdf = thinkbayes.MakeCdfFromList(outliers, label) 286 | cdfs.append(cdf) 287 | 288 | thinkplot.Clf() 289 | thinkplot.Cdfs(cdfs) 290 | thinkplot.Save(root='variability_cdfs', 291 | title='CDF of height', 292 | xlabel='Reported height (cm)', 293 | ylabel='CDF') 294 | 295 | 296 | def PlotMarginals(suite): 297 | """Plots marginal distributions from a joint distribution. 298 | 299 | suite: joint distribution of mu and sigma. 300 | """ 301 | thinkplot.Clf() 302 | 303 | pyplot.subplot(1, 2, 1) 304 | pmf_m = suite.Marginal(0) 305 | cdf_m = thinkbayes.MakeCdfFromPmf(pmf_m) 306 | thinkplot.Cdf(cdf_m) 307 | 308 | pyplot.subplot(1, 2, 2) 309 | pmf_s = suite.Marginal(1) 310 | cdf_s = thinkbayes.MakeCdfFromPmf(pmf_s) 311 | thinkplot.Cdf(cdf_s) 312 | 313 | thinkplot.Show() 314 | 315 | 316 | def DumpHeights(data_dir='.', n=10000): 317 | """Read the BRFSS dataset, extract the heights and pickle them.""" 318 | resp = brfss.Respondents() 319 | resp.ReadRecords(data_dir, n) 320 | 321 | d = {1:[], 2:[]} 322 | [d[r.sex].append(r.htm3) for r in resp.records if r.htm3 != 'NA'] 323 | 324 | fp = open('variability_data.pkl', 'wb') 325 | pickle.dump(d, fp) 326 | fp.close() 327 | 328 | 329 | def LoadHeights(): 330 | """Read the pickled height data. 331 | 332 | returns: map from sex code to list of heights. 333 | """ 334 | fp = open('variability_data.pkl', 'rb') 335 | d = pickle.load(fp) 336 | fp.close() 337 | return d 338 | 339 | 340 | def UpdateSuite1(suite, xs): 341 | """Computes the posterior distibution of mu and sigma. 342 | 343 | Computes untransformed likelihoods. 344 | 345 | suite: Suite that maps from (mu, sigma) to prob 346 | xs: sequence 347 | """ 348 | suite.UpdateSet(xs) 349 | 350 | 351 | def UpdateSuite2(suite, xs): 352 | """Computes the posterior distibution of mu and sigma. 353 | 354 | Computes log likelihoods. 355 | 356 | suite: Suite that maps from (mu, sigma) to prob 357 | xs: sequence 358 | """ 359 | suite.Log() 360 | suite.LogUpdateSet(xs) 361 | suite.Exp() 362 | suite.Normalize() 363 | 364 | 365 | def UpdateSuite3(suite, xs): 366 | """Computes the posterior distibution of mu and sigma. 367 | 368 | Computes log likelihoods efficiently. 369 | 370 | suite: Suite that maps from (mu, sigma) to prob 371 | t: sequence 372 | """ 373 | suite.Log() 374 | suite.LogUpdateSetFast(xs) 375 | suite.Exp() 376 | suite.Normalize() 377 | 378 | 379 | def UpdateSuite4(suite, xs): 380 | """Computes the posterior distibution of mu and sigma. 381 | 382 | Computes log likelihoods efficiently. 383 | 384 | suite: Suite that maps from (mu, sigma) to prob 385 | t: sequence 386 | """ 387 | suite.Log() 388 | suite.LogUpdateSetMeanVar(xs) 389 | suite.Exp() 390 | suite.Normalize() 391 | 392 | 393 | def UpdateSuite5(suite, xs): 394 | """Computes the posterior distibution of mu and sigma. 395 | 396 | Computes log likelihoods efficiently. 397 | 398 | suite: Suite that maps from (mu, sigma) to prob 399 | t: sequence 400 | """ 401 | suite.Log() 402 | suite.LogUpdateSetMedianIPR(xs) 403 | suite.Exp() 404 | suite.Normalize() 405 | 406 | 407 | def MedianIPR(xs, p): 408 | """Computes the median and interpercentile range. 409 | 410 | xs: sequence of values 411 | p: range (0-1), 0.5 yields the interquartile range 412 | 413 | returns: tuple of float (median, IPR) 414 | """ 415 | cdf = thinkbayes.MakeCdfFromList(xs) 416 | median = cdf.Percentile(50) 417 | 418 | alpha = (1-p) / 2 419 | ipr = cdf.Value(1-alpha) - cdf.Value(alpha) 420 | return median, ipr 421 | 422 | 423 | def MedianS(xs, num_sigmas): 424 | """Computes the median and an estimate of sigma. 425 | 426 | Based on an interpercentile range (IPR). 427 | 428 | factor: number of standard deviations spanned by the IPR 429 | """ 430 | half_p = thinkbayes.StandardGaussianCdf(num_sigmas) - 0.5 431 | median, ipr = MedianIPR(xs, half_p * 2) 432 | s = ipr / 2 / num_sigmas 433 | 434 | return median, s 435 | 436 | def Summarize(xs): 437 | """Prints summary statistics from a sequence of values. 438 | 439 | xs: sequence of values 440 | """ 441 | # print(smallest and largest) 442 | xs.sort() 443 | print('smallest', xs[:10]) 444 | print('largest', xs[-10:]) 445 | 446 | # print(median and interquartile range) 447 | cdf = thinkbayes.MakeCdfFromList(xs) 448 | print(cdf.Percentile(25), cdf.Percentile(50), cdf.Percentile(75)) 449 | 450 | 451 | def RunEstimate(update_func, num_points=31, median_flag=False): 452 | """Runs the whole analysis. 453 | 454 | update_func: which of the update functions to use 455 | num_points: number of points in the Suite (in each dimension) 456 | """ 457 | DumpHeights(n=10000000) 458 | d = LoadHeights() 459 | labels = {1:'male', 2:'female'} 460 | 461 | # PlotCdfs(d, labels) 462 | 463 | suites = {} 464 | for key, xs in d.items(): 465 | name = labels[key] 466 | print(name, len(xs)) 467 | Summarize(xs) 468 | 469 | xs = thinkstats.Jitter(xs, 1.3) 470 | 471 | mus, sigmas = FindPriorRanges(xs, num_points, median_flag=median_flag) 472 | suite = Height(mus, sigmas, name) 473 | suites[name] = suite 474 | update_func(suite, xs) 475 | print('MLE', suite.MaximumLikelihood()) 476 | 477 | PlotPosterior(suite) 478 | 479 | pmf_m = suite.Marginal(0) 480 | pmf_s = suite.Marginal(1) 481 | print('marginal mu', pmf_m.Mean(), pmf_m.Var()) 482 | print('marginal sigma', pmf_s.Mean(), pmf_s.Var()) 483 | 484 | # PlotMarginals(suite) 485 | 486 | PlotCoefVariation(suites) 487 | 488 | 489 | def main(): 490 | random.seed(17) 491 | 492 | func = UpdateSuite5 493 | median_flag = (func == UpdateSuite5) 494 | RunEstimate(func, median_flag=median_flag) 495 | 496 | 497 | if __name__ == '__main__': 498 | main() 499 | 500 | 501 | """ Results: 502 | 503 | UpdateSuite1 (100): 504 | marginal mu 162.816901408 0.55779791443 505 | marginal sigma 6.36966103214 0.277026082819 506 | 507 | UpdateSuite2 (100): 508 | marginal mu 162.816901408 0.55779791443 509 | marginal sigma 6.36966103214 0.277026082819 510 | 511 | UpdateSuite3 (100): 512 | marginal mu 162.816901408 0.55779791443 513 | marginal sigma 6.36966103214 0.277026082819 514 | 515 | UpdateSuite4 (100): 516 | marginal mu 162.816901408 0.547456009605 517 | marginal sigma 6.30305516111 0.27544106054 518 | 519 | UpdateSuite3 (1000): 520 | marginal mu 163.722137405 0.0660294386397 521 | marginal sigma 6.64453251495 0.0329935312671 522 | 523 | UpdateSuite4 (1000): 524 | marginal mu 163.722137405 0.0658920503302 525 | marginal sigma 6.63692197049 0.0329689887609 526 | 527 | UpdateSuite3 (all): 528 | marginal mu 163.223475005 0.000203282582659 529 | marginal sigma 7.26918836916 0.000101641131229 530 | 531 | UpdateSuite4 (all): 532 | marginal mu 163.223475004 0.000203281499857 533 | marginal sigma 7.26916693422 0.000101640932082 534 | 535 | UpdateSuite5 (all): 536 | marginal mu 163.1805214 7.9399898468e-07 537 | marginal sigma 7.29969524118 3.26257030869e-14 538 | 539 | """ 540 | 541 | --------------------------------------------------------------------------------