<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Austin Rochford (Posts about Bayesian Statistics)</title><link>https://austinrochford.com/</link><description></description><atom:link href="https://austinrochford.com/tags/bayesian-statistics.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2022 &lt;a href="mailto:austin.rochford@gmail.com"&gt;Austin Rochford&lt;/a&gt; </copyright><lastBuildDate>Mon, 17 Jan 2022 11:51:53 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Playing Battleship with Bayesian Search Theory, Thompson Sampling, and Approximate Bayesian Computation</title><link>https://austinrochford.com/posts/2021-09-02-battleship-bayes.html</link><dc:creator>Austin Rochford</dc:creator><description>&lt;p&gt;As a child, I spent many hours playing &lt;a href="https://en.wikipedia.org/wiki/Battleship_(game)"&gt;Battleship&lt;/a&gt; against my Mom or brother to pass the time.&lt;/p&gt;
&lt;center&gt;
&lt;img src="https://s3.us-east-2.amazonaws.com/boardashell/battleship.jpeg" width="500"&gt;
&lt;/center&gt;
&lt;p&gt;Battleship is a classic game of &lt;a href="https://en.wikipedia.org/wiki/Complete_information"&gt;incomplete information&lt;/a&gt; that involves placing ships of different lengths on a square grid (&lt;span class="math inline"&gt;\(10 \times 10\)&lt;/span&gt; in the most popular version) and trying to guess the location of all of the opponent’s ships (sinking them) before the opponent does the same.&lt;/p&gt;
&lt;p&gt;Many years after I stopped playing Battleship with my family, I developed an interest in &lt;a href="https://en.wikipedia.org/wiki/Bayesian_search_theory"&gt;Bayesian search theory&lt;/a&gt; after learning about a firm that specializes in search consulting for the US government at jobs-in-industry panel in graduate school. I had already happily lined up a &lt;a href="https://kibocommerce.com/personalization-software/"&gt;job&lt;/a&gt; in e-commerce optimization, but the idea of using statistics to guide the potentially expensive searches piqued my intellectual curiosity. I e-mailed the presenter afterward for more information and he recommended [&lt;em&gt;Theory of Optimal Search&lt;/em&gt;]^(Stone, Lawrence D. &lt;em&gt;Theory of optimal search.&lt;/em&gt; Elsevier, 1976.) as the sessential reference in the field. The book is interesting if a bit dry, it is about mathematical optimization after all, and I was always curious about the connection with the search theory it develops and Battleship, which has always stood out in my mind as a basic search problem. Though most of the theory in this book is not directly applicable to Battleship for various reasons, a continuing theme is allocating search in areas with the largest posterior probability of containing the target object given the search results so far. A 1985 result of [Assaf and Zamir]^(Assaf, David, and Shmuel Zamir. “Optimal sequential search: a Bayesian approach.” &lt;em&gt;The Annals of Statistics&lt;/em&gt; 13, no. 3 (1985): 1213-1221.) shows the optimality of this strategy in a situation much closer to that of Battleship.&lt;/p&gt;
&lt;p&gt;Inspired by these forays into search theory I have thought idly for many years about constructing a near-optimal Bayesian approach to playing Battleship. This post is the culmination of these thoughts, showing how to use ideas from Bayesian search theory, &lt;a href="https://en.wikipedia.org/wiki/Approximate_Bayesian_computation"&gt;approximate Bayesian computation&lt;/a&gt; (ABC), and &lt;a href="https://en.wikipedia.org/wiki/Thompson_sampling"&gt;Thompson sampling&lt;/a&gt; to construct an easily tractable, near optimal strategy for Battleship that only requires simulating random Battleship boards and not reasoning through hard-coded special cases to achieve strong play.&lt;/p&gt;
&lt;h2 id="playing-battleship"&gt;Playing Battleship&lt;/h2&gt;
&lt;p&gt;First we make the necessary Python imports and do a bit of housekeeping.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb1-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;matplotlib inline&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb2-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; abc &lt;span class="im"&gt;import&lt;/span&gt; ABC, abstractmethod&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; datetime&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; IPython.display &lt;span class="im"&gt;import&lt;/span&gt; HTML&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; itertools &lt;span class="im"&gt;import&lt;/span&gt; product&lt;/span&gt;
&lt;span id="cb2-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb2-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; multiprocessing &lt;span class="im"&gt;as&lt;/span&gt; mp&lt;/span&gt;
&lt;span id="cb2-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb2-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; tqdm &lt;span class="im"&gt;import&lt;/span&gt; tqdm, trange&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb3-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; empiricaldist &lt;span class="im"&gt;import&lt;/span&gt; Pmf&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; matplotlib &lt;span class="im"&gt;as&lt;/span&gt; mpl&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib &lt;span class="im"&gt;import&lt;/span&gt; pyplot &lt;span class="im"&gt;as&lt;/span&gt; plt&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib.animation &lt;span class="im"&gt;import&lt;/span&gt; FuncAnimation&lt;/span&gt;
&lt;span id="cb3-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb3-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib.colors &lt;span class="im"&gt;import&lt;/span&gt; LinearSegmentedColormap&lt;/span&gt;
&lt;span id="cb3-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb3-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib.ticker &lt;span class="im"&gt;import&lt;/span&gt; IndexLocator, StrMethodFormatter&lt;/span&gt;
&lt;span id="cb3-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb3-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; numpy &lt;span class="im"&gt;as&lt;/span&gt; np&lt;/span&gt;
&lt;span id="cb3-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb3-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; scipy &lt;span class="im"&gt;import&lt;/span&gt; linalg, stats&lt;/span&gt;
&lt;span id="cb3-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb3-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; seaborn &lt;span class="im"&gt;as&lt;/span&gt; sns&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb4-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;FIG_WIDTH &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;8&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;FIG_HEIGHT &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;6&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;mpl.rcParams[&lt;span class="st"&gt;'figure.figsize'&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (FIG_WIDTH, FIG_HEIGHT)&lt;/span&gt;
&lt;span id="cb4-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb4-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;CMAP &lt;span class="op"&gt;=&lt;/span&gt; LinearSegmentedColormap.from_list(&lt;/span&gt;
&lt;span id="cb4-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'battleship'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb4-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    [&lt;/span&gt;
&lt;span id="cb4-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        (&lt;span class="fl"&gt;0.0&lt;/span&gt;, &lt;span class="st"&gt;'blue'&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb4-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        (&lt;span class="fl"&gt;0.2&lt;/span&gt;, &lt;span class="st"&gt;'orange'&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb4-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        (&lt;span class="fl"&gt;1.&lt;/span&gt;, &lt;span class="st"&gt;'red'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb4-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ]&lt;/span&gt;
&lt;span id="cb4-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb4-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;CMAP.set_bad(&lt;span class="st"&gt;'w'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb4-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb4-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.&lt;span class="bu"&gt;set&lt;/span&gt;(color_codes&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb4-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb4-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb4-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pct_formatter &lt;span class="op"&gt;=&lt;/span&gt; StrMethodFormatter(&lt;span class="st"&gt;'&lt;/span&gt;&lt;span class="sc"&gt;{x:.1%}&lt;/span&gt;&lt;span class="st"&gt;'&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb5-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SEED &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;123456789&lt;/span&gt; &lt;span class="co"&gt;# for reproducibility&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb5-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb5-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb5-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;rng &lt;span class="op"&gt;=&lt;/span&gt; np.random.default_rng(SEED)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We represent a Battleship board as a sequence of rectangular grids, one per ship. For standard Battleship, that means a game consists of five &lt;span class="math inline"&gt;\(10 \times 10\)&lt;/span&gt; grids, the first grid containing a ship of length five, the seconding containing a ship of length four, and so on.&lt;/p&gt;
&lt;p&gt;The following constants are useful for defining a standard game of Battleship. (Note that we are using Hasbro’s &lt;a href="https://en.wikipedia.org/wiki/Battleship_(game)#Description"&gt;names&lt;/a&gt; for the ships, revised in 2002.)&lt;/p&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb6-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;GRID_LENGTH &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;10&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SHIP_NAMES &lt;span class="op"&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb6-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"Carrier"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb6-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"Battleship"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb6-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"Destroyer"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb6-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"Submarine"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb6-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"Patrol boat"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;
&lt;span id="cb6-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SHIP_SIZES &lt;span class="op"&gt;=&lt;/span&gt; np.array([&lt;/span&gt;
&lt;span id="cb6-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dv"&gt;5&lt;/span&gt;, &lt;/span&gt;
&lt;span id="cb6-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dv"&gt;4&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb6-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dv"&gt;3&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb6-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dv"&gt;3&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb6-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dv"&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;])&lt;/span&gt;
&lt;span id="cb6-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb6-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_ships &lt;span class="op"&gt;=&lt;/span&gt; SHIP_SIZES.size&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The following plots show how a Battleship board is represented as a sequence of five grids, one per ship.&lt;/p&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb7-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb7-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships &lt;span class="op"&gt;=&lt;/span&gt; np.zeros((n_ships, GRID_LENGTH, GRID_LENGTH))&lt;/span&gt;
&lt;span id="cb7-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb7-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships[&lt;span class="dv"&gt;0&lt;/span&gt;, &lt;span class="dv"&gt;0&lt;/span&gt;, :&lt;span class="dv"&gt;5&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb7-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships[&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;4&lt;/span&gt;:&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;7&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb7-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships[&lt;span class="dv"&gt;2&lt;/span&gt;, &lt;span class="dv"&gt;9&lt;/span&gt;, &lt;span class="dv"&gt;3&lt;/span&gt;:&lt;span class="dv"&gt;6&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb7-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships[&lt;span class="dv"&gt;3&lt;/span&gt;, &lt;span class="dv"&gt;3&lt;/span&gt;:&lt;span class="dv"&gt;6&lt;/span&gt;, &lt;span class="dv"&gt;1&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb7-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships[&lt;span class="dv"&gt;4&lt;/span&gt;, &lt;span class="dv"&gt;5&lt;/span&gt;, &lt;span class="dv"&gt;8&lt;/span&gt;:&lt;span class="dv"&gt;10&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb8-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; plot_board(board, cmap&lt;span class="op"&gt;=&lt;/span&gt;CMAP,&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               cbar&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, cbar_kwargs&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               ax&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, &lt;span class="op"&gt;**&lt;/span&gt;heatmap_kwargs):&lt;/span&gt;
&lt;span id="cb8-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; ax &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb8-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        _, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(FIG_WIDTH, FIG_WIDTH))&lt;/span&gt;
&lt;span id="cb8-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb8-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    heatmap_kwargs.setdefault(&lt;span class="st"&gt;'vmin'&lt;/span&gt;, &lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb8-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    heatmap_kwargs.setdefault(&lt;span class="st"&gt;'vmax'&lt;/span&gt;, &lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb8-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb8-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    board_ &lt;span class="op"&gt;=&lt;/span&gt; np.atleast_2d(board)&lt;/span&gt;
&lt;span id="cb8-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    mask &lt;span class="op"&gt;=&lt;/span&gt; board_.mask &lt;span class="cf"&gt;if&lt;/span&gt; np.ma.is_masked(board_) &lt;span class="cf"&gt;else&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb8-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; cbar_kwargs &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb8-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        cbar_kwargs &lt;span class="op"&gt;=&lt;/span&gt; {}&lt;/span&gt;
&lt;span id="cb8-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb8-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    cbar_kwargs.setdefault(&lt;span class="st"&gt;'format'&lt;/span&gt;, pct_formatter)&lt;/span&gt;
&lt;span id="cb8-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    cbar_kwargs.setdefault(&lt;span class="st"&gt;'label'&lt;/span&gt;, &lt;span class="st"&gt;"Posterior probability of a hit"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb8-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb8-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    sns.heatmap(board_, mask&lt;span class="op"&gt;=&lt;/span&gt;mask, cmap&lt;span class="op"&gt;=&lt;/span&gt;cmap,&lt;/span&gt;
&lt;span id="cb8-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                cbar&lt;span class="op"&gt;=&lt;/span&gt;cbar, square&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                linewidths&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;1.5&lt;/span&gt;, linecolor&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                cbar_kws&lt;span class="op"&gt;=&lt;/span&gt;cbar_kwargs,&lt;/span&gt;
&lt;span id="cb8-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                ax&lt;span class="op"&gt;=&lt;/span&gt;ax, &lt;span class="op"&gt;**&lt;/span&gt;heatmap_kwargs)&lt;/span&gt;
&lt;span id="cb8-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb8-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; board_.shape[&lt;span class="dv"&gt;0&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb8-26"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ax.set_yticklabels([])&lt;/span&gt;
&lt;span id="cb8-27"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb8-28"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; cbar:&lt;/span&gt;
&lt;span id="cb8-29"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        cbar &lt;span class="op"&gt;=&lt;/span&gt; ax.figure.axes[&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb8-30"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        cbar.set_ylabel(cbar.get_ylabel(), rotation&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;270&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb8-31"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb8-32"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb8-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; ax&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb9-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(ncols&lt;span class="op"&gt;=&lt;/span&gt;n_ships, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb9-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb9-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         figsize&lt;span class="op"&gt;=&lt;/span&gt;(n_ships &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="fl"&gt;2.5&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb9-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb9-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb9-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb9-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;for&lt;/span&gt; (ship, name, ax) &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;zip&lt;/span&gt;(ships, SHIP_NAMES, axes):&lt;/span&gt;
&lt;span id="cb9-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb9-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    plot_board(ship, ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb9-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb9-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb9-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_xticklabels([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb9-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_yticklabels([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb9-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_title(name)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb9-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb9-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb9-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_13_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Adding these ship grids gives us the two-dimensional board familiar to anyone who has played battleship.&lt;/p&gt;
&lt;div class="sourceCode" id="cb10"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb10-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb10-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; to_board(ships, ship_axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb10-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb10-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; ships.&lt;span class="bu"&gt;sum&lt;/span&gt;(axis&lt;span class="op"&gt;=&lt;/span&gt;ship_axis)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb11"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb11-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb11-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(to_board(ships))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_16_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The following class implements most of the basics necessary to track the state of a game of Battleship, make guesses, and reveal the contents of guessed spaces.&lt;/p&gt;
&lt;div class="sourceCode" id="cb12"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb12-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; Battleship:&lt;/span&gt;
&lt;span id="cb12-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;__init__&lt;/span&gt;(&lt;span class="va"&gt;self&lt;/span&gt;, ships):&lt;/span&gt;
&lt;span id="cb12-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="va"&gt;self&lt;/span&gt;._ships &lt;span class="op"&gt;=&lt;/span&gt; ships&lt;/span&gt;
&lt;span id="cb12-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="va"&gt;self&lt;/span&gt;._turn_revealed &lt;span class="op"&gt;=&lt;/span&gt; []&lt;/span&gt;
&lt;span id="cb12-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb12-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="at"&gt;@property&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; _board(&lt;span class="va"&gt;self&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb12-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; to_board(&lt;span class="va"&gt;self&lt;/span&gt;._ships)&lt;/span&gt;
&lt;span id="cb12-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb12-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="at"&gt;@property&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; grid_length(&lt;span class="va"&gt;self&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb12-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;._board.shape[&lt;span class="dv"&gt;0&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb12-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb12-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="at"&gt;@property&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; is_solved(&lt;span class="va"&gt;self&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb12-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;.revealed.&lt;span class="bu"&gt;sum&lt;/span&gt;() &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;._board.&lt;span class="bu"&gt;sum&lt;/span&gt;()&lt;/span&gt;
&lt;span id="cb12-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb12-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="at"&gt;@property&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; revealed(&lt;span class="va"&gt;self&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb12-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; to_board(&lt;span class="va"&gt;self&lt;/span&gt;._revealed_ships)&lt;/span&gt;
&lt;span id="cb12-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb12-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="at"&gt;@property&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; _revealed_ships(&lt;span class="va"&gt;self&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb12-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;if&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;.turns &lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb12-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;._turn_revealed[&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb12-26"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb12-27"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;return&lt;/span&gt; np.ma.masked_all_like(&lt;span class="va"&gt;self&lt;/span&gt;._ships)&lt;/span&gt;
&lt;span id="cb12-28"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb12-29"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="at"&gt;@property&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-30"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; ship_sizes(&lt;span class="va"&gt;self&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb12-31"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;._ships.&lt;span class="bu"&gt;sum&lt;/span&gt;(axis&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;2&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb12-32"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb12-33"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="at"&gt;@property&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-34"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; sunk(&lt;span class="va"&gt;self&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb12-35"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ship_sizes &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;._ships.&lt;span class="bu"&gt;sum&lt;/span&gt;(axis&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;2&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb12-36"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        revealed_sizes &lt;span class="op"&gt;=&lt;/span&gt; (&lt;span class="va"&gt;self&lt;/span&gt;._revealed_ships&lt;/span&gt;
&lt;span id="cb12-37"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                              .&lt;span class="bu"&gt;sum&lt;/span&gt;(axis&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;2&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb12-38"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                              .filled(&lt;span class="dv"&gt;0&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb12-39"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb12-40"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; ship_sizes &lt;span class="op"&gt;==&lt;/span&gt; revealed_sizes&lt;/span&gt;
&lt;span id="cb12-41"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-41" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb12-42"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-42" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="at"&gt;@property&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-43"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-43" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; turn_revealed(&lt;span class="va"&gt;self&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb12-44"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-44" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; [np.ma.masked_all_like(&lt;span class="va"&gt;self&lt;/span&gt;._board)] &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-45"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-45" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="op"&gt;+&lt;/span&gt; [to_board(revealed) &lt;span class="cf"&gt;for&lt;/span&gt; revealed &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;._turn_revealed]&lt;/span&gt;
&lt;span id="cb12-46"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-46" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb12-47"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-47" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="at"&gt;@property&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-48"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-48" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; turns(&lt;span class="va"&gt;self&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb12-49"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb12-49" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="bu"&gt;len&lt;/span&gt;(&lt;span class="va"&gt;self&lt;/span&gt;._turn_revealed)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These bookkeeping methods are fairly self-explanatory. An instance of &lt;code&gt;Battleship&lt;/code&gt; tracks which squares have been revealed to the opponent using &lt;code&gt;numpy&lt;/code&gt;’s &lt;a href="https://numpy.org/doc/stable/reference/maskedarray.generic.html"&gt;masked arrays&lt;/a&gt;. The &lt;code&gt;revealed&lt;/code&gt; grid is masked wherever the opponent has not yet guessed.&lt;/p&gt;
&lt;p&gt;The heart of our &lt;code&gt;Battleship&lt;/code&gt; class is the &lt;code&gt;guess&lt;/code&gt; method, which takes the coordinates to guess, and returns a tuple containing whether or not the guess resulted in a hit or miss, and the index of the ship sunk as a result of that guess (&lt;code&gt;None&lt;/code&gt; if no ship was sunk). (Here we use a &lt;a href="https://www.cgranade.com/blog/2016/10/07/documenting-long-classes-jupyter-notebook.html"&gt;dirty trick&lt;/a&gt; to add a method to the &lt;code&gt;Battleship&lt;/code&gt; class after it has already been defined for expository clarity. &lt;strong&gt;Don’t do this in practice!&lt;/strong&gt;)&lt;/p&gt;
&lt;div class="sourceCode" id="cb13"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb13-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; Battleship(Battleship):&lt;/span&gt;
&lt;span id="cb13-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; guess(&lt;span class="va"&gt;self&lt;/span&gt;, i, j):&lt;/span&gt;
&lt;span id="cb13-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;if&lt;/span&gt; &lt;span class="kw"&gt;not&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;.revealed.mask[i, j]:&lt;/span&gt;
&lt;span id="cb13-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;raise&lt;/span&gt; &lt;span class="pp"&gt;ValueError&lt;/span&gt;(&lt;span class="ss"&gt;f"&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;i&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;, &lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;j&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt; already guessed"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb13-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb13-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            prev_sunk &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;.sunk&lt;/span&gt;
&lt;span id="cb13-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            next_ships &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;._revealed_ships.copy()&lt;/span&gt;
&lt;span id="cb13-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            next_ships[:, i, j] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;._ships[:, i, j]&lt;/span&gt;
&lt;span id="cb13-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="va"&gt;self&lt;/span&gt;._turn_revealed.append(next_ships)&lt;/span&gt;
&lt;span id="cb13-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;/span&gt;
&lt;span id="cb13-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            curr_sunk &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;.sunk&lt;/span&gt;
&lt;span id="cb13-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;/span&gt;
&lt;span id="cb13-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;if&lt;/span&gt; (curr_sunk &lt;span class="op"&gt;==&lt;/span&gt; prev_sunk).&lt;span class="bu"&gt;all&lt;/span&gt;():&lt;/span&gt;
&lt;span id="cb13-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                sunk &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb13-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                sunk &lt;span class="op"&gt;=&lt;/span&gt; (curr_sunk &lt;span class="op"&gt;&amp;amp;&lt;/span&gt; &lt;span class="op"&gt;~&lt;/span&gt;prev_sunk).argmax()&lt;/span&gt;
&lt;span id="cb13-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;/span&gt;
&lt;span id="cb13-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb13-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;._board[i, j], sunk&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In addition to this class representing game state and history, we define an abstract class &lt;code&gt;Strategy&lt;/code&gt; that generates the guesses necessary to play a game.&lt;/p&gt;
&lt;div class="sourceCode" id="cb14"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb14-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb14-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; Strategy(ABC):&lt;/span&gt;
&lt;span id="cb14-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb14-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="at"&gt;@abstractmethod&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb14-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; next_guess(&lt;span class="va"&gt;self&lt;/span&gt;, revealed):&lt;/span&gt;
&lt;span id="cb14-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb14-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;pass&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb14-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb14-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb14-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; reveal(&lt;span class="va"&gt;self&lt;/span&gt;, i, j, hit_or_miss, sunk):&lt;/span&gt;
&lt;span id="cb14-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb14-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;pass&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;next_guess&lt;/code&gt; method takes a masked array of the board as revealed so far and should return the coordinates of the next spot to guess. The &lt;code&gt;reveal&lt;/code&gt; method takes guessed coordinates, an indicator of whether the guess resulted in a hit or miss, and the index of the ship sunk as a result of that guess (or &lt;code&gt;None&lt;/code&gt;, as with &lt;code&gt;guess&lt;/code&gt; above). This method allows a &lt;code&gt;Strategy&lt;/code&gt; to update internal state based on the result of guesses. While some simple strategies can infer the next guess purely based on the state of the revealed board, we will see that it is useful when taking a Bayesian approach to maintain state inside a strategy.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;play&lt;/code&gt; function take a configuration of ships and a &lt;code&gt;Strategy&lt;/code&gt; and plays the corresponding game of Battleship.&lt;/p&gt;
&lt;div class="sourceCode" id="cb15"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb15-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; play(ships, strategy, progress_bar&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb15-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    game &lt;span class="op"&gt;=&lt;/span&gt; Battleship(ships)&lt;/span&gt;
&lt;span id="cb15-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb15-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; progress_bar:&lt;/span&gt;
&lt;span id="cb15-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        pbar &lt;span class="op"&gt;=&lt;/span&gt; tqdm(total&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="bu"&gt;int&lt;/span&gt;(ships.&lt;span class="bu"&gt;sum&lt;/span&gt;()))&lt;/span&gt;
&lt;span id="cb15-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb15-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;while&lt;/span&gt; &lt;span class="kw"&gt;not&lt;/span&gt; game.is_solved:&lt;/span&gt;
&lt;span id="cb15-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        i, j &lt;span class="op"&gt;=&lt;/span&gt; strategy.next_guess(game.revealed)&lt;/span&gt;
&lt;span id="cb15-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        hit_or_miss, sunk &lt;span class="op"&gt;=&lt;/span&gt; game.guess(i, j)&lt;/span&gt;
&lt;span id="cb15-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        strategy.reveal(i, j, hit_or_miss, sunk)&lt;/span&gt;
&lt;span id="cb15-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb15-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;if&lt;/span&gt; progress_bar &lt;span class="kw"&gt;and&lt;/span&gt; hit_or_miss &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb15-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            pbar.update()&lt;/span&gt;
&lt;span id="cb15-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;/span&gt;
&lt;span id="cb15-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; progress_bar:&lt;/span&gt;
&lt;span id="cb15-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        pbar.close()&lt;/span&gt;
&lt;span id="cb15-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb15-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb15-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; game&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The rest of this post progresses from strategies for simplified versions of Battleship to finally showing how to use ABC and Thompson sampling to achieve near optimal play.&lt;/p&gt;
&lt;h3 id="manual-guessing"&gt;Manual guessing&lt;/h3&gt;
&lt;p&gt;This framework allows us to manually play Battleship by inputting user guesses and watching how the board evolves.&lt;/p&gt;
&lt;div class="sourceCode" id="cb16"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb16-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb16-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; ManualStrategy(Strategy):&lt;/span&gt;
&lt;span id="cb16-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb16-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; next_guess(&lt;span class="va"&gt;self&lt;/span&gt;, revealed):&lt;/span&gt;
&lt;span id="cb16-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb16-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ax &lt;span class="op"&gt;=&lt;/span&gt; plot_board(revealed)&lt;/span&gt;
&lt;span id="cb16-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb16-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ax.set_title(&lt;span class="st"&gt;"Currently revealed"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb16-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb16-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        plt.show()&lt;/span&gt;
&lt;span id="cb16-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb16-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb16-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb16-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        i &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="bu"&gt;int&lt;/span&gt;(&lt;span class="bu"&gt;input&lt;/span&gt;(&lt;span class="st"&gt;"Enter row to guess: "&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb16-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb16-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        j &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="bu"&gt;int&lt;/span&gt;(&lt;span class="bu"&gt;input&lt;/span&gt;(&lt;span class="st"&gt;"Enter column to guess: "&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb16-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb16-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb16-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb16-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; i, j&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb17"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb17-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb17-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;try&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb17-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb17-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    play(ships, ManualStrategy())&lt;/span&gt;
&lt;span id="cb17-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb17-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;except&lt;/span&gt; &lt;span class="pp"&gt;KeyboardInterrupt&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb17-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb17-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="bu"&gt;print&lt;/span&gt;(&lt;span class="st"&gt;"Game ended"&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_28_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;pre&gt;&lt;code&gt;Enter row to guess:  5
Enter column to guess:  4&lt;/code&gt;&lt;/pre&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_28_2.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;pre&gt;&lt;code&gt;Enter row to guess:  0
Enter column to guess:  3&lt;/code&gt;&lt;/pre&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_28_4.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;pre&gt;&lt;code&gt;Enter row to guess:  1
Enter column to guess:  3&lt;/code&gt;&lt;/pre&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_28_6.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;pre&gt;&lt;code&gt;Enter row to guess:  0
Enter column to guess:  2&lt;/code&gt;&lt;/pre&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_28_8.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;pre&gt;&lt;code&gt;Enter row to guess:  0
Enter column to guess:  4&lt;/code&gt;&lt;/pre&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_28_10.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;pre&gt;&lt;code&gt;Game ended&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This strategy is not really useful for our purposes, but it provides a good illustration of how the game is usually played. The white squares here indicate the cells whose contents are unknown because we have not yet guessed them.&lt;/p&gt;
&lt;h3 id="row-with-one-ship"&gt;Row with one ship&lt;/h3&gt;
&lt;p&gt;We begin by simplifying the idea of Battleship to the most basic possible setting of a single row containing a single ship.&lt;/p&gt;
&lt;p&gt;The following function generates all possible rows of a given length containing a ship of a given size.&lt;/p&gt;
&lt;div class="sourceCode" id="cb24"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb24-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb24-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; get_all_ship_rows(grid_length, ship_size):&lt;/span&gt;
&lt;span id="cb24-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb24-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    i, j &lt;span class="op"&gt;=&lt;/span&gt; np.indices((grid_length, grid_length))[:, :&lt;span class="op"&gt;-&lt;/span&gt;ship_size &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb24-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb24-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb24-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb24-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; (i &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; j) &lt;span class="op"&gt;&amp;amp;&lt;/span&gt; (j &lt;span class="op"&gt;&amp;lt;&lt;/span&gt; i &lt;span class="op"&gt;+&lt;/span&gt; ship_size)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For a row of length three and a ship of size two (3/2), there are only two such rows.&lt;/p&gt;
&lt;div class="sourceCode" id="cb25"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb25-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb25-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;all_rows_3_2 &lt;span class="op"&gt;=&lt;/span&gt; get_all_ship_rows(&lt;span class="dv"&gt;3&lt;/span&gt;, &lt;span class="dv"&gt;2&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb26"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb26-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb26-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_board(all_rows_3_2)&lt;/span&gt;
&lt;span id="cb26-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb26-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"All rows 3/2"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_34_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;For a row of length ten and a ship of size four (10/4), there are seven such rows.&lt;/p&gt;
&lt;div class="sourceCode" id="cb27"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb27-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb27-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;all_rows_10_4 &lt;span class="op"&gt;=&lt;/span&gt; get_all_ship_rows(&lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;4&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb28"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb28-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb28-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_board(all_rows_10_4)&lt;/span&gt;
&lt;span id="cb28-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb28-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"All rows 10/4"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_37_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We will compare our Bayesian strategies to several benchmark strategies, starting with the simplest possible strategy: random guessing.&lt;/p&gt;
&lt;h4 id="random-guessing"&gt;Random guessing&lt;/h4&gt;
&lt;p&gt;The random guessing approach to Battleship is equivalent to the following urn problem from classic probability theory. Imagine an urn containing 100 balls (corresponding to cells on the board), 17 of which are red (corresponding to cells covered by ships), and 83 of which are blue. The number of turns required to solve Battleship through random guessing has the same distribution as the number of balls of any color that are drawn before all 17 red balls have been drawn. It is well known (in the right circles, at least) that this corresponds to the &lt;a href="https://en.wikipedia.org/wiki/Negative_hypergeometric_distribution"&gt;negative hypergeometric distribution&lt;/a&gt;.&lt;/p&gt;
&lt;center&gt;
&lt;figure&gt;
&lt;img src="https://austinrochford.com/resources/battleship_files/neg_hyp_geo.png" width="500"&gt; &lt;br&gt;
&lt;caption&gt;
Original image credit &lt;a href="https://www.johndcook.com/blog/distribution_chart/"&gt;John D. Cook&lt;/a&gt;
&lt;/caption&gt;
&lt;/figure&gt;
&lt;/center&gt;
&lt;p&gt;The following function returns the probability mass function (pmf) of the appropriate negative hypergeometric distribution given a grid and ship size.&lt;/p&gt;
&lt;div class="sourceCode" id="cb29"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb29-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb29-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; get_random_guess_dist(grid_size, ship_size, n_hit&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb29-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb29-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; n_hit &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb29-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb29-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        n_hit &lt;span class="op"&gt;=&lt;/span&gt; ship_size&lt;/span&gt;
&lt;span id="cb29-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb29-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb29-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    support &lt;span class="op"&gt;=&lt;/span&gt; np.arange(ship_size, grid_size &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb29-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb29-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    nhg &lt;span class="op"&gt;=&lt;/span&gt; stats.nhypergeom(grid_size,&lt;/span&gt;
&lt;span id="cb29-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb29-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                           grid_size &lt;span class="op"&gt;-&lt;/span&gt; ship_size,&lt;/span&gt;
&lt;span id="cb29-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb29-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                           n_hit)&lt;/span&gt;
&lt;span id="cb29-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb29-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb29-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb29-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; Pmf(nhg.pmf(support &lt;span class="op"&gt;-&lt;/span&gt; ship_size), support)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We see, unsurprisingly, that random guessing will usually take near the maximum number of turns to solve the game.&lt;/p&gt;
&lt;div class="sourceCode" id="cb30"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb30-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb30-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_random_pmf &lt;span class="op"&gt;=&lt;/span&gt; get_random_guess_dist(GRID_LENGTH&lt;span class="op"&gt;**&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, SHIP_SIZES.&lt;span class="bu"&gt;sum&lt;/span&gt;())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb31"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb31-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; plot_turn_dist(pmf, kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'bar'&lt;/span&gt;, mean&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, mean_kwargs&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, &lt;span class="op"&gt;**&lt;/span&gt;kwargs):&lt;/span&gt;
&lt;span id="cb31-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; ax &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb31-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        _, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots()&lt;/span&gt;
&lt;span id="cb31-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb31-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; kind &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="st"&gt;'bar'&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb31-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="co"&gt;# pandas barplot uses odd indexing, making it hard to&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="co"&gt;# mix bar and line plots if we use pandas's versions&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        kwargs.setdefault(&lt;span class="st"&gt;'width'&lt;/span&gt;, &lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        kwargs.setdefault(&lt;span class="st"&gt;'alpha'&lt;/span&gt;, &lt;span class="fl"&gt;0.75&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb31-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ax.bar(pmf.index, pmf, &lt;span class="op"&gt;**&lt;/span&gt;kwargs)&lt;/span&gt;
&lt;span id="cb31-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;elif&lt;/span&gt; kind &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="st"&gt;'line'&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb31-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        pmf.plot(ax&lt;span class="op"&gt;=&lt;/span&gt;ax, &lt;span class="op"&gt;**&lt;/span&gt;kwargs)&lt;/span&gt;
&lt;span id="cb31-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb31-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;raise&lt;/span&gt; &lt;span class="pp"&gt;ValueError&lt;/span&gt;(&lt;span class="st"&gt;"kind must be one of 'bar' or 'line'"&lt;/span&gt;)    &lt;/span&gt;
&lt;span id="cb31-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb31-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; mean:&lt;/span&gt;
&lt;span id="cb31-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;if&lt;/span&gt; mean_kwargs &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb31-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            mean_kwargs &lt;span class="op"&gt;=&lt;/span&gt; {}&lt;/span&gt;
&lt;span id="cb31-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;/span&gt;
&lt;span id="cb31-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        mean_kwargs.setdefault(&lt;span class="st"&gt;'ls'&lt;/span&gt;, &lt;span class="st"&gt;'--'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb31-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ax.axvline(pmf.mean(), &lt;span class="op"&gt;**&lt;/span&gt;mean_kwargs)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb31-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.xaxis.grid(&lt;span class="va"&gt;False&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-26"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_xlabel(&lt;span class="st"&gt;"Turns"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-27"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb31-28"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb31-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; ax&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb32"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb32-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb32-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; make_pct_yaxis(ax):&lt;/span&gt;
&lt;span id="cb32-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb32-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.yaxis.set_major_formatter(pct_formatter)&lt;/span&gt;
&lt;span id="cb32-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb32-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_ylabel(&lt;span class="st"&gt;"Probability"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb32-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb32-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb32-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb32-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; ax&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb33"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb33-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb33-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_turn_ax &lt;span class="op"&gt;=&lt;/span&gt; plot_turn_dist(std_random_pmf, kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'line'&lt;/span&gt;, mean&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb33-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb33-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb33-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb33-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_pct_yaxis(std_turn_ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb33-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb33-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_turn_ax.set_title(&lt;span class="st"&gt;"Random guessing&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;Standard Battleship"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_45_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The dashed vertical line shows the expected number of turns to solve Battleship by randomly guessing,&lt;/p&gt;
&lt;div class="sourceCode" id="cb34"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb34-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb34-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_random_pmf.mean()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;95.38888888888883&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Returning the the case of a row with a single ship, we visualize the turn distribution of random guessin strategies for various row lengths and a ship of size two.&lt;/p&gt;
&lt;div class="sourceCode" id="cb36"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb36-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb36-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;RANDOM_ROW_LENGTHS &lt;span class="op"&gt;=&lt;/span&gt; [&lt;span class="dv"&gt;4&lt;/span&gt;, &lt;span class="dv"&gt;5&lt;/span&gt;, &lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;10&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb37"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb37-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb37-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(nrows&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="bu"&gt;len&lt;/span&gt;(RANDOM_ROW_LENGTHS) &lt;span class="op"&gt;//&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;, ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb37-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb37-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb37-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb37-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         figsize&lt;span class="op"&gt;=&lt;/span&gt;(FIG_WIDTH, &lt;span class="fl"&gt;1.25&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; FIG_HEIGHT))&lt;/span&gt;
&lt;span id="cb37-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb37-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb37-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb37-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;for&lt;/span&gt; (row_length, ax) &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;zip&lt;/span&gt;(RANDOM_ROW_LENGTHS, axes.flat):&lt;/span&gt;
&lt;span id="cb37-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb37-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    pmf &lt;span class="op"&gt;=&lt;/span&gt; get_random_guess_dist(row_length, &lt;span class="dv"&gt;2&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb37-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb37-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    plot_turn_dist(pmf, ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb37-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb37-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb37-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb37-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    make_pct_yaxis(ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb37-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb37-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_title(&lt;span class="ss"&gt;f"&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;row_length&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;/2"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb37-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb37-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb37-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb37-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.suptitle(&lt;span class="st"&gt;"Random guessing"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb37-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb37-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_50_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We do the same for a ship of size three.&lt;/p&gt;
&lt;div class="sourceCode" id="cb38"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb38-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb38-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(nrows&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="bu"&gt;len&lt;/span&gt;(RANDOM_ROW_LENGTHS) &lt;span class="op"&gt;//&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;, ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb38-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb38-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb38-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb38-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         figsize&lt;span class="op"&gt;=&lt;/span&gt;(FIG_WIDTH, &lt;span class="fl"&gt;1.25&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; FIG_HEIGHT))&lt;/span&gt;
&lt;span id="cb38-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb38-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb38-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb38-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;for&lt;/span&gt; (row_length, ax) &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;zip&lt;/span&gt;(RANDOM_ROW_LENGTHS, axes.flat):&lt;/span&gt;
&lt;span id="cb38-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb38-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    pmf &lt;span class="op"&gt;=&lt;/span&gt; get_random_guess_dist(row_length, &lt;span class="dv"&gt;3&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb38-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb38-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    plot_turn_dist(pmf, ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb38-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb38-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb38-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb38-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    make_pct_yaxis(ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb38-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb38-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_title(&lt;span class="ss"&gt;f"&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;row_length&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;/3"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb38-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb38-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb38-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb38-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.suptitle(&lt;span class="st"&gt;"Random guessing"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb38-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb38-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_52_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;As with the case of standard Battleship, the most likely outcome is to use all the turns, and the expected value will be slightly below that.&lt;/p&gt;
&lt;h4 id="optimal-search"&gt;Optimal search&lt;/h4&gt;
&lt;p&gt;In the simple setting of a row with a single ship, it is not too hard to work out the optimal search strategy, which consists of two phases. First we must locate the ship by getting at least one hit. Once the ship has been located, we must sink it by attacking spaces next to known hits until all of the ship has been found.&lt;/p&gt;
&lt;h5 id="after-at-least-one-hit"&gt;After at least one hit&lt;/h5&gt;
&lt;p&gt;We first implement optimal search after at least one hit has occurred. In this case, we guess the spot immediately to the left of the leftmost hit, unless that hit is in the first cell, or the cell to its left has already been shown to contain water. In those two cases, we guess the cell to the right of the rightmost hit until all cells containing the ship have been hit. The following function implements this strategy.&lt;/p&gt;
&lt;div class="sourceCode" id="cb39"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb39-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb39-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; next_guess_1d_with_hit(row):&lt;/span&gt;
&lt;span id="cb39-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb39-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    first &lt;span class="op"&gt;=&lt;/span&gt; row.argmax()&lt;/span&gt;
&lt;span id="cb39-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb39-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb39-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb39-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="co"&gt;# found the left edge, fill out the ship to the right&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb39-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb39-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; first &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="kw"&gt;or&lt;/span&gt; row[first &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb39-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb39-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; first &lt;span class="op"&gt;+&lt;/span&gt; row[first:].mask.argmax()&lt;/span&gt;
&lt;span id="cb39-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb39-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="co"&gt;# find the left edge&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb39-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb39-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb39-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb39-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; first &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can show how this strategy works through a simple animated example. Suppose the position of a length three ship on a length ten row is as shown below.&lt;/p&gt;
&lt;div class="sourceCode" id="cb40"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb40-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb40-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;board &lt;span class="op"&gt;=&lt;/span&gt; np.zeros(&lt;span class="dv"&gt;10&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb40-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb40-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;board[&lt;span class="dv"&gt;6&lt;/span&gt;:&lt;span class="dv"&gt;9&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb41"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb41-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb41-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(board)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_58_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Also suppose that after three guesses, the following spots have been revealed.&lt;/p&gt;
&lt;div class="sourceCode" id="cb42"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb42-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb42-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed &lt;span class="op"&gt;=&lt;/span&gt; np.ma.masked_all_like(board)&lt;/span&gt;
&lt;span id="cb42-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb42-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed[[&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;4&lt;/span&gt;, &lt;span class="dv"&gt;7&lt;/span&gt;]] &lt;span class="op"&gt;=&lt;/span&gt; board[[&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;4&lt;/span&gt;, &lt;span class="dv"&gt;7&lt;/span&gt;]]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb43"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb43-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb43-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(revealed)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_61_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The above strategy will take three guesses to sink the ship, as shown in the animation below.&lt;/p&gt;
&lt;div class="sourceCode" id="cb44"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb44-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;turn_revealed &lt;span class="op"&gt;=&lt;/span&gt; [revealed]&lt;/span&gt;
&lt;span id="cb44-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb44-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;next_j &lt;span class="op"&gt;=&lt;/span&gt; next_guess_1d_with_hit(revealed)&lt;/span&gt;
&lt;span id="cb44-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;next_revealed &lt;span class="op"&gt;=&lt;/span&gt; revealed.copy()&lt;/span&gt;
&lt;span id="cb44-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;next_revealed[next_j] &lt;span class="op"&gt;=&lt;/span&gt; board[next_j]&lt;/span&gt;
&lt;span id="cb44-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;turn_revealed.append(next_revealed)&lt;/span&gt;
&lt;span id="cb44-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed &lt;span class="op"&gt;=&lt;/span&gt; next_revealed&lt;/span&gt;
&lt;span id="cb44-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb44-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;next_j &lt;span class="op"&gt;=&lt;/span&gt; next_guess_1d_with_hit(revealed)&lt;/span&gt;
&lt;span id="cb44-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;next_revealed &lt;span class="op"&gt;=&lt;/span&gt; revealed.copy()&lt;/span&gt;
&lt;span id="cb44-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;next_revealed[next_j] &lt;span class="op"&gt;=&lt;/span&gt; board[next_j]&lt;/span&gt;
&lt;span id="cb44-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;turn_revealed.append(next_revealed)&lt;/span&gt;
&lt;span id="cb44-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed &lt;span class="op"&gt;=&lt;/span&gt; next_revealed&lt;/span&gt;
&lt;span id="cb44-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb44-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;next_j &lt;span class="op"&gt;=&lt;/span&gt; next_guess_1d_with_hit(revealed)&lt;/span&gt;
&lt;span id="cb44-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;next_revealed &lt;span class="op"&gt;=&lt;/span&gt; revealed.copy()&lt;/span&gt;
&lt;span id="cb44-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;next_revealed[next_j] &lt;span class="op"&gt;=&lt;/span&gt; board[next_j]&lt;/span&gt;
&lt;span id="cb44-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;turn_revealed.append(next_revealed)&lt;/span&gt;
&lt;span id="cb44-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb44-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed &lt;span class="op"&gt;=&lt;/span&gt; next_revealed&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb45"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb45-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; animate_boards(boards,&lt;/span&gt;
&lt;span id="cb45-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   cmap&lt;span class="op"&gt;=&lt;/span&gt;CMAP, cbar&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb45-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   heatmap_kwargs&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, &lt;span class="op"&gt;**&lt;/span&gt;ani_kwargs):&lt;/span&gt;
&lt;span id="cb45-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; ax &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb45-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(FIG_WIDTH, FIG_WIDTH))&lt;/span&gt;
&lt;span id="cb45-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb45-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        fig &lt;span class="op"&gt;=&lt;/span&gt; ax.figure&lt;/span&gt;
&lt;span id="cb45-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb45-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; heatmap_kwargs &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb45-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        heatmap_kwargs &lt;span class="op"&gt;=&lt;/span&gt; {}&lt;/span&gt;
&lt;span id="cb45-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb45-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    plot_board(boards[&lt;span class="dv"&gt;0&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb45-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               cmap&lt;span class="op"&gt;=&lt;/span&gt;cmap, cbar&lt;span class="op"&gt;=&lt;/span&gt;cbar, ax&lt;span class="op"&gt;=&lt;/span&gt;ax,&lt;/span&gt;
&lt;span id="cb45-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               &lt;span class="op"&gt;**&lt;/span&gt;heatmap_kwargs)&lt;/span&gt;
&lt;span id="cb45-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb45-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    quadmesh, &lt;span class="op"&gt;*&lt;/span&gt;_ &lt;span class="op"&gt;=&lt;/span&gt; ax.get_children()&lt;/span&gt;
&lt;span id="cb45-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb45-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; ani_func(i):&lt;/span&gt;
&lt;span id="cb45-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        quadmesh.set_array(boards[i])&lt;/span&gt;
&lt;span id="cb45-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb45-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; quadmesh,&lt;/span&gt;
&lt;span id="cb45-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb45-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ani_kwargs.setdefault(&lt;span class="st"&gt;'blit'&lt;/span&gt;, &lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb45-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ani_kwargs.setdefault(&lt;span class="st"&gt;'frames'&lt;/span&gt;, &lt;span class="bu"&gt;len&lt;/span&gt;(boards))&lt;/span&gt;
&lt;span id="cb45-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb45-26"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb45-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; FuncAnimation(fig, ani_func, &lt;span class="op"&gt;**&lt;/span&gt;ani_kwargs)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb46"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb46-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb46-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%%&lt;/span&gt;capture&lt;/span&gt;
&lt;span id="cb46-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb46-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ani &lt;span class="op"&gt;=&lt;/span&gt; animate_boards(turn_revealed, interval&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;300&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb47"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb47-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb47-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;HTML(ani.to_html5_video())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;video width="576" height="576" controls autoplay loop&gt;
&lt;source type="video/mp4" src="data:video/mp4;base64,AAAAIGZ0eXBNNFYgAAACAE00ViBpc29taXNvMmF2YzEAAAAIZnJlZQAACgttZGF0AAACrgYF//+q%0A3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE2MSByMzAzME0gOGJkNmQyOCAtIEguMjY0L01Q%0ARUctNCBBVkMgY29kZWMgLSBDb3B5bGVmdCAyMDAzLTIwMjAgLSBodHRwOi8vd3d3LnZpZGVvbGFu%0ALm9yZy94MjY0Lmh0bWwgLSBvcHRpb25zOiBjYWJhYz0xIHJlZj0zIGRlYmxvY2s9MTowOjAgYW5h%0AbHlzZT0weDM6MHgxMTMgbWU9aGV4IHN1Ym1lPTcgcHN5PTEgcHN5X3JkPTEuMDA6MC4wMCBtaXhl%0AZF9yZWY9MSBtZV9yYW5nZT0xNiBjaHJvbWFfbWU9MSB0cmVsbGlzPTEgOHg4ZGN0PTEgY3FtPTAg%0AZGVhZHpvbmU9MjEsMTEgZmFzdF9wc2tpcD0xIGNocm9tYV9xcF9vZmZzZXQ9LTIgdGhyZWFkcz02%0AIGxvb2thaGVhZF90aHJlYWRzPTEgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50%0AZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MyBi%0AX3B5cmFtaWQ9MiBiX2FkYXB0PTEgYl9iaWFzPTAgZGlyZWN0PTEgd2VpZ2h0Yj0xIG9wZW5fZ29w%0APTAgd2VpZ2h0cD0yIGtleWludD0yNTAga2V5aW50X21pbj0zIHNjZW5lY3V0PTQwIGludHJhX3Jl%0AZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAu%0ANjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAF%0AZ2WIhAAT//73sY+BTcgADZc6inof4RWx9JBRerHZoGTqAAADAAADAABOFqne+b9ctAjWAAAHoACZ%0ABoxnyHjmGgOknhxlCRU0gAKSx/GfJv8QAyuRIYdlbxF3Q0ZZ3nsNhTHogxkZ2QZ0H99af9E7BMkc%0AOBBoSIpfCBJoAhu6sySKjMlnxX+UfyLIi7YHDI/77e0FTWCEzQy6z1UUflgpdtl5FlX9eMIBHan8%0A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"&gt;
Your browser does not support the video tag. &lt;/source&gt;&lt;/video&gt;
&lt;/center&gt;
&lt;h5 id="getting-the-first-hit"&gt;Getting the first hit&lt;/h5&gt;
&lt;p&gt;Immediately it is clear that we only have to search one of the conrguence classes of the cell index mod the ship size to guarantee a hit. In the following plot of a row of length ten, each congruence class mod three is colored differently.&lt;/p&gt;
&lt;div class="sourceCode" id="cb48"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb48-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb48-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(np.arange(&lt;span class="dv"&gt;10&lt;/span&gt;) &lt;span class="op"&gt;%&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;, cmap&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'plasma'&lt;/span&gt;, vmin&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;, vmax&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_68_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;A moment’s consideration shows that the congruence class of -1 modulo the ship size will always have the fewest elements of any of the congruence class, so we choose to search along these cells. The following plot shows the cells to be searched until a hit is found in red.&lt;/p&gt;
&lt;div class="sourceCode" id="cb49"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb49-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb49-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; get_search_cells_1d(grid_length, ship_size):&lt;/span&gt;
&lt;span id="cb49-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb49-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    i &lt;span class="op"&gt;=&lt;/span&gt; np.arange(grid_length)&lt;/span&gt;
&lt;span id="cb49-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb49-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb49-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb49-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; i[i &lt;span class="op"&gt;%&lt;/span&gt; ship_size &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="op"&gt;%&lt;/span&gt; ship_size]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb50"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb50-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb50-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;row &lt;span class="op"&gt;=&lt;/span&gt; np.zeros(&lt;span class="dv"&gt;10&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb50-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb50-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;row[get_search_cells_1d(&lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;3&lt;/span&gt;)] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb51"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb51-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb51-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(row)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_72_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The following subclass of &lt;code&gt;Strategy&lt;/code&gt; implements the optimal strategy of searching along this grid until a hit is found, then greedily filling out the ship.&lt;/p&gt;
&lt;div class="sourceCode" id="cb52"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb52-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb52-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; Single1DOptimalStrategy(Strategy):&lt;/span&gt;
&lt;span id="cb52-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb52-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;__init__&lt;/span&gt;(&lt;span class="va"&gt;self&lt;/span&gt;, grid_length, ship_size):&lt;/span&gt;
&lt;span id="cb52-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb52-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="va"&gt;self&lt;/span&gt;._grid_length &lt;span class="op"&gt;=&lt;/span&gt; grid_length&lt;/span&gt;
&lt;span id="cb52-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb52-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="va"&gt;self&lt;/span&gt;._ship_size &lt;span class="op"&gt;=&lt;/span&gt; ship_size&lt;/span&gt;
&lt;span id="cb52-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb52-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb52-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb52-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; next_guess(&lt;span class="va"&gt;self&lt;/span&gt;, revealed):&lt;/span&gt;
&lt;span id="cb52-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb52-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;if&lt;/span&gt; revealed.mask.&lt;span class="bu"&gt;all&lt;/span&gt;() &lt;span class="kw"&gt;or&lt;/span&gt; revealed.&lt;span class="bu"&gt;sum&lt;/span&gt;() &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb52-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb52-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            search_j &lt;span class="op"&gt;=&lt;/span&gt; get_search_cells_1d(&lt;span class="va"&gt;self&lt;/span&gt;._grid_length,&lt;/span&gt;
&lt;span id="cb52-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb52-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                           &lt;span class="va"&gt;self&lt;/span&gt;._ship_size)            &lt;/span&gt;
&lt;span id="cb52-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb52-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            next_j &lt;span class="op"&gt;=&lt;/span&gt; search_j[revealed.mask[&lt;span class="dv"&gt;0&lt;/span&gt;, search_j].argmax()]&lt;/span&gt;
&lt;span id="cb52-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb52-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb52-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb52-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;, next_guess_1d_with_hit(revealed[&lt;span class="dv"&gt;0&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb52-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb52-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;/span&gt;
&lt;span id="cb52-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb52-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;, next_j&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now use this strategy to play all three games with a length three ship on a length five row.&lt;/p&gt;
&lt;div class="sourceCode" id="cb53"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb53-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb53-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;all_rows_5_3 &lt;span class="op"&gt;=&lt;/span&gt; get_all_ship_rows(&lt;span class="dv"&gt;5&lt;/span&gt;, &lt;span class="dv"&gt;3&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb54"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb54-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb54-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;opt_row_games_5_3 &lt;span class="op"&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb54-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb54-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    play(ship_row[np.newaxis, np.newaxis],&lt;/span&gt;
&lt;span id="cb54-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb54-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;         Single1DOptimalStrategy(&lt;span class="dv"&gt;5&lt;/span&gt;, &lt;span class="dv"&gt;3&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb54-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb54-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;for&lt;/span&gt; ship_row &lt;span class="kw"&gt;in&lt;/span&gt; all_rows_5_3&lt;/span&gt;
&lt;span id="cb54-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb54-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;
&lt;span id="cb54-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb54-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;opt_row_turns_5_3 &lt;span class="op"&gt;=&lt;/span&gt; Pmf.from_seq([game.turns &lt;span class="cf"&gt;for&lt;/span&gt; game &lt;span class="kw"&gt;in&lt;/span&gt; opt_row_games_5_3])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb55"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb55-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb55-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_turn_dist(opt_row_turns_5_3)&lt;/span&gt;
&lt;span id="cb55-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb55-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb55-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb55-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_pct_yaxis(ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb55-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Optimal play&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;Ship size 3, row length 5"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_78_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Two of the games take four turns and one takes three turns. Notably, no games take five turns. This is because we know that the third cell is a guaranteed hit in this configuration.&lt;/p&gt;
&lt;p&gt;We can repeat this exercise for a row of length ten.&lt;/p&gt;
&lt;div class="sourceCode" id="cb56"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb56-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb56-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;all_rows_10_3 &lt;span class="op"&gt;=&lt;/span&gt; get_all_ship_rows(&lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;3&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb57"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb57-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb57-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;opt_row_games_10_3 &lt;span class="op"&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb57-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb57-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    play(ship_row[np.newaxis, np.newaxis],&lt;/span&gt;
&lt;span id="cb57-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb57-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;         Single1DOptimalStrategy(&lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;3&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb57-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb57-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;for&lt;/span&gt; ship_row &lt;span class="kw"&gt;in&lt;/span&gt; all_rows_10_3&lt;/span&gt;
&lt;span id="cb57-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb57-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;
&lt;span id="cb57-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb57-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;opt_row_turns_pmf_10_3 &lt;span class="op"&gt;=&lt;/span&gt; Pmf.from_seq([game.turns &lt;span class="cf"&gt;for&lt;/span&gt; game &lt;span class="kw"&gt;in&lt;/span&gt; opt_row_games_10_3])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb58"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb58-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb58-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_turn_dist(opt_row_turns_pmf_10_3)&lt;/span&gt;
&lt;span id="cb58-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb58-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb58-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb58-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_pct_yaxis(ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb58-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb58-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Optimal play&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;Ship size 3, row length 10"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_82_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that no games take more than six turns with this configuration. Since the equivalence class of -1 modulo 3 contains three members (2, 5, and 8), we are guaranteed to get our first hit in at most three guesses, and once we have a first hit it will take at most three guesses to sink the ship (two hits and potentially one miss if the first hit was not on the rightmost cell of the ship).&lt;/p&gt;
&lt;h4 id="bayesian-thompson-sampling"&gt;Bayesian (Thompson sampling)&lt;/h4&gt;
&lt;p&gt;The above thought exercise is interesting, but it involves several domain-specific insights (the optimal search grid, how to optimally sink a ship that has been located) that do not generalize immediately to two-dimensional grids that allow ships to be oriented in either rows or columns. (Note that if we restrict our ship in an &lt;span class="math inline"&gt;\(m \times n\)&lt;/span&gt; grid to be oriented along a row, we’re essentially playing a one-dimensional game on a row of length &lt;span class="math inline"&gt;\(m \cdot n\)&lt;/span&gt;.) In this section we will show how to reproduce the above results using a Bayesian approach to this game of simplified Battleship. This approach will generalize to a near-optimal strategy for standard Battleship with many fewer hard coded rules than the above optimal one-dimensional strategy requires to generalize.&lt;/p&gt;
&lt;center&gt;
&lt;img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/18/Bayes%27_Theorem_MMB_01.jpg/1280px-Bayes%27_Theorem_MMB_01.jpg" width="500"&gt;
&lt;/center&gt;
&lt;p&gt;We begin by enumerating all possible boards for a given row/ship configuration (in this case 5/3).&lt;/p&gt;
&lt;div class="sourceCode" id="cb59"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb59-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb59-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_board(all_rows_5_3)&lt;/span&gt;
&lt;span id="cb59-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb59-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yticklabels([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_85_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We consider this set of ships as a uniform prior distribution on the set of possible board layouts. With this perspective, when we take the average in each columns, we get the prior probability that each cell contains a ship.&lt;/p&gt;
&lt;p&gt;We already see that this Bayesian approach thhat we can conclude that the third cell must contain a ship without doing any modular arithmetic.&lt;/p&gt;
&lt;p&gt;For a configuration with a longer row (10/3), we see that the middle six cells have the higest prior probability of containing a ship. This makes sense as there are three configurations in which each of these cells contains a ship, but only one configuration in which the first cell contains a ship, and similarly for the other cells near the edges.&lt;/p&gt;
&lt;div class="sourceCode" id="cb60"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb60-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb60-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;all_rows_10_3 &lt;span class="op"&gt;=&lt;/span&gt; get_all_ship_rows(&lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;3&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb61"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb61-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb61-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(all_rows_10_3.mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;), cbar&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_89_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Looking at these probabilities, a resonable strategy would seem to be to guess the next cell with the highest probability of containing a hit. In both the 5/3 and 10/3 cases, this would result in guessing the third cell next. (By convention when many cells have the same hit probability, we will choose the one wit smallest coordinates.)&lt;/p&gt;
&lt;p&gt;Let’s focus on the 5/3 configuration for the moment and return to 10/3 after. Suppose the true 5/3 board is as follows.&lt;/p&gt;
&lt;div class="sourceCode" id="cb62"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb62-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb62-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;board_5_3 &lt;span class="op"&gt;=&lt;/span&gt; np.zeros(&lt;span class="dv"&gt;5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb62-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb62-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;board_5_3[&lt;span class="dv"&gt;1&lt;/span&gt;:&lt;span class="dv"&gt;4&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb63"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb63-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb63-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(board_5_3)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_92_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Guessing the third cell must result in a hit in the 5/3 configuration, so after one guess the following board has been revealed.&lt;/p&gt;
&lt;div class="sourceCode" id="cb64"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb64-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb64-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed_5_3 &lt;span class="op"&gt;=&lt;/span&gt; np.ma.masked_all_like(board_5_3)&lt;/span&gt;
&lt;span id="cb64-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb64-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed_5_3[&lt;span class="dv"&gt;2&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; board_5_3[&lt;span class="dv"&gt;2&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb65"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb65-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb65-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(revealed_5_3)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_95_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;With this information, what should our next guess be? For the first guess we chose the cell with the highest prior probability of yielding a hit, so it seems intuitive that we would choose the cell with the highest &lt;em&gt;posterior&lt;/em&gt; probability of yielding a hit, given the observation from our first guess.&lt;/p&gt;
&lt;p&gt;We can get this posterior distribution by eliminating the boards that do not match the cells that have been revealed to us.&lt;/p&gt;
&lt;div class="sourceCode" id="cb66"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb66-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb66-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; is_compat(ships, revealed, board_axis&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, &lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)):&lt;/span&gt;
&lt;span id="cb66-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb66-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; (ships &lt;span class="op"&gt;==&lt;/span&gt; revealed).&lt;span class="bu"&gt;all&lt;/span&gt;(axis&lt;span class="op"&gt;=&lt;/span&gt;board_axis)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb67"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb67-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb67-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;compat_5_3 &lt;span class="op"&gt;=&lt;/span&gt; all_rows_5_3[&lt;/span&gt;
&lt;span id="cb67-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb67-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    is_compat(all_rows_5_3, revealed_5_3, board_axis&lt;span class="op"&gt;=-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb67-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb67-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb68"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb68-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb68-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_board(compat_5_3)&lt;/span&gt;
&lt;span id="cb68-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb68-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yticklabels([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_99_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Since the third cell is guaranteed to be a hit in the 5/3 configuration, all ship layouts are compatible with the result of our first guess, and the posterior is the same as the prior &lt;em&gt;restricted to unknown cells&lt;/em&gt;. With this restriction our posterior is as follows.&lt;/p&gt;
&lt;div class="sourceCode" id="cb69"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb69-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb69-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(&lt;/span&gt;
&lt;span id="cb69-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb69-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    np.ma.masked_array(compat_5_3.mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb69-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb69-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                       mask&lt;span class="op"&gt;=~&lt;/span&gt;revealed_5_3.mask),&lt;/span&gt;
&lt;span id="cb69-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb69-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    cbar&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb69-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb69-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_101_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that out of all the unknown cells, the second and third are tied for the highest posterior probability of being a hit. By our convention, we will choose the second cell as the next guess, which we know will reveal a hit.&lt;/p&gt;
&lt;div class="sourceCode" id="cb70"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb70-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb70-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed_5_3[&lt;span class="dv"&gt;1&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; board_5_3[&lt;span class="dv"&gt;1&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb71"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb71-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb71-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(revealed_5_3)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_104_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;With this observations we are able to eliminate one of the potential boards.&lt;/p&gt;
&lt;div class="sourceCode" id="cb72"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb72-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb72-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;compat_5_3 &lt;span class="op"&gt;=&lt;/span&gt; all_rows_5_3[&lt;/span&gt;
&lt;span id="cb72-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb72-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    is_compat(all_rows_5_3, revealed_5_3, board_axis&lt;span class="op"&gt;=-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb72-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb72-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb73"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb73-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb73-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_board(compat_5_3)&lt;/span&gt;
&lt;span id="cb73-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb73-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yticklabels([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_107_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Combining these two compatible boards to form the posterior distribution, we get the following.&lt;/p&gt;
&lt;div class="sourceCode" id="cb74"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb74-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb74-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_board(&lt;/span&gt;
&lt;span id="cb74-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb74-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    np.ma.masked_array(compat_5_3.mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb74-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb74-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                       mask&lt;span class="op"&gt;=~&lt;/span&gt;revealed_5_3.mask),&lt;/span&gt;
&lt;span id="cb74-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb74-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    cbar&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb74-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb74-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb74-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb74-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yticklabels([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_109_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that it is impossible for the fourth cell to contain a hit, and there’s a 50% chance that the first and fourth cells will be a hit. By our convention above, we guess the first cell, resulting in a miss.&lt;/p&gt;
&lt;div class="sourceCode" id="cb75"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb75-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb75-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed_5_3[&lt;span class="dv"&gt;0&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; board_5_3[&lt;span class="dv"&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb76"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb76-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb76-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(revealed_5_3)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_112_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Finally we see that there is only one board compatible with the information that has been revealed, so we guess the fourth cell to end the game.&lt;/p&gt;
&lt;div class="sourceCode" id="cb77"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb77-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb77-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;compat_5_3 &lt;span class="op"&gt;=&lt;/span&gt; all_rows_5_3[&lt;/span&gt;
&lt;span id="cb77-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb77-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    is_compat(all_rows_5_3, revealed_5_3, board_axis&lt;span class="op"&gt;=-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb77-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb77-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb78"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb78-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb78-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_board(compat_5_3)&lt;/span&gt;
&lt;span id="cb78-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb78-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yticklabels([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_115_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We now return to the 10/3 case. Suppose we are working with the following board.&lt;/p&gt;
&lt;div class="sourceCode" id="cb79"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb79-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb79-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;board_10_3 &lt;span class="op"&gt;=&lt;/span&gt; np.zeros(&lt;span class="dv"&gt;10&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb79-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb79-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;board_10_3[&lt;span class="dv"&gt;5&lt;/span&gt;:&lt;span class="dv"&gt;8&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb80"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb80-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb80-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(board_10_3)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_118_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Recalling the prior distribution on hits in the 10/3 configuration, we see first guess the third cell, revealing a miss.&lt;/p&gt;
&lt;div class="sourceCode" id="cb81"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb81-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb81-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(all_rows_10_3.mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;), cbar&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_120_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb82"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb82-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb82-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed_10_3 &lt;span class="op"&gt;=&lt;/span&gt; np.ma.masked_all_like(board_10_3)&lt;/span&gt;
&lt;span id="cb82-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb82-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed_10_3[&lt;span class="dv"&gt;2&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; board_10_3[&lt;span class="dv"&gt;2&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb83"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb83-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb83-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(revealed_10_3)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_122_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Excluding boards that are incompatible with a miss in the third cell, we see that we have already ruled out a ship in the first two cells as well.&lt;/p&gt;
&lt;div class="sourceCode" id="cb84"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb84-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb84-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;compat_10_3 &lt;span class="op"&gt;=&lt;/span&gt; all_rows_10_3[&lt;/span&gt;
&lt;span id="cb84-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb84-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    is_compat(all_rows_10_3, revealed_10_3, board_axis&lt;span class="op"&gt;=-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb84-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb84-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb85"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb85-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb85-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_board(compat_10_3)&lt;/span&gt;
&lt;span id="cb85-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb85-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yticklabels([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_125_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Unsurprisingly, the sixth through eight cells are tied for the highest probability of yielding a hit, so we guess the six cell, revealing a hit.&lt;/p&gt;
&lt;div class="sourceCode" id="cb86"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb86-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb86-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(compat_10_3.mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;), cbar&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_127_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb87"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb87-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb87-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed_10_3[&lt;span class="dv"&gt;5&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; board_10_3[&lt;span class="dv"&gt;5&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb88"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb88-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb88-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(revealed_10_3)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_129_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Hitting the rest of the ship will proceed similarly to the 5/3 case, so we stop playing here.&lt;/p&gt;
&lt;p&gt;This approach of calculating the posterior distribution by enumerating the possible grids and eliminating those that are incompatible with the observed hits and misses is a very simple type of &lt;a href="https://en.wikipedia.org/wiki/Approximate_Bayesian_computation"&gt;approximate Bayesian computation&lt;/a&gt; (ABC). ABC is a fascinating and deep field of research in its own right, and we are really only scratching its surface here.&lt;/p&gt;
&lt;p&gt;Choosing to guess the cell with the &lt;a href="https://en.wikipedia.org/wiki/Maximum_a_posteriori_estimation"&gt;maximum a posteriori&lt;/a&gt; (MAP) is a simplified (greedy) form of &lt;a href="https://en.wikipedia.org/wiki/Thompson_sampling"&gt;Thompson sampling&lt;/a&gt;, a Bayesian approach to playing games of incomplete information that chooses the next action according to the probability that it maximizes the expected reward. In the simple situation of a single ship (in both one and two dimensions) we can calculate the cell(s) that has the MAP probability chance of yielding a hit (the expected reward) exactly, so this strategy becomes greedy. (I have a soft spot for Thompsons sampling in general as we use it in a number of our machine-learning based products at &lt;a href="https://kibocommerce.com/"&gt;Kibo&lt;/a&gt;, where I work. For a discussion of the applications of Thompson sampling to e-commerce optimization, take a look at my &lt;a href="https://austinrochford.com/talks.html"&gt;talks&lt;/a&gt;.)&lt;/p&gt;
&lt;div class="sourceCode" id="cb89"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb89-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb89-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; argmax_2d(x):&lt;/span&gt;
&lt;span id="cb89-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb89-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    max_i &lt;span class="op"&gt;=&lt;/span&gt; x.&lt;span class="bu"&gt;max&lt;/span&gt;(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;).argmax()&lt;/span&gt;
&lt;span id="cb89-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb89-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    max_j &lt;span class="op"&gt;=&lt;/span&gt; x[max_i].argmax()&lt;/span&gt;
&lt;span id="cb89-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb89-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb89-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb89-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; max_i, max_j&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb90"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb90-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; SingleThompsonStrategy(Strategy):&lt;/span&gt;
&lt;span id="cb90-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;__init__&lt;/span&gt;(&lt;span class="va"&gt;self&lt;/span&gt;, poss_ships):&lt;/span&gt;
&lt;span id="cb90-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="va"&gt;self&lt;/span&gt;._poss_ships &lt;span class="op"&gt;=&lt;/span&gt; poss_ships&lt;/span&gt;
&lt;span id="cb90-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb90-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; compat_ships(&lt;span class="va"&gt;self&lt;/span&gt;, revealed):&lt;/span&gt;
&lt;span id="cb90-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;if&lt;/span&gt; revealed.mask.&lt;span class="bu"&gt;all&lt;/span&gt;():&lt;/span&gt;
&lt;span id="cb90-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;._poss_ships&lt;/span&gt;
&lt;span id="cb90-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb90-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            is_compat_ &lt;span class="op"&gt;=&lt;/span&gt; is_compat(&lt;span class="va"&gt;self&lt;/span&gt;._poss_ships, revealed)&lt;/span&gt;
&lt;span id="cb90-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb90-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;._poss_ships[is_compat_]&lt;/span&gt;
&lt;span id="cb90-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb90-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; next_guess(&lt;span class="va"&gt;self&lt;/span&gt;, revealed):&lt;/span&gt;
&lt;span id="cb90-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        post &lt;span class="op"&gt;=&lt;/span&gt; np.ma.masked_array(&lt;/span&gt;
&lt;span id="cb90-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="va"&gt;self&lt;/span&gt;.compat_ships(revealed).mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb90-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            mask&lt;span class="op"&gt;=~&lt;/span&gt;revealed.mask&lt;/span&gt;
&lt;span id="cb90-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        )&lt;/span&gt;
&lt;span id="cb90-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb90-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb90-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; argmax_2d(post)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We watch this strategy play the game we started above.&lt;/p&gt;
&lt;div class="sourceCode" id="cb91"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb91-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb91-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ts &lt;span class="op"&gt;=&lt;/span&gt; SingleThompsonStrategy(all_rows_10_3[:, np.newaxis, :])&lt;/span&gt;
&lt;span id="cb91-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb91-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;game_10_3 &lt;span class="op"&gt;=&lt;/span&gt; play(board_10_3[np.newaxis, np.newaxis, :], ts,&lt;/span&gt;
&lt;span id="cb91-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb91-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 progress_bar&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;100%|██████████| 3/3 [00:00&amp;lt;00:00, 391.81it/s]&lt;/p&gt;
&lt;div class="sourceCode" id="cb92"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb92-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb92-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%%&lt;/span&gt;capture&lt;/span&gt;
&lt;span id="cb92-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb92-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ani &lt;span class="op"&gt;=&lt;/span&gt; animate_boards(game_10_3.turn_revealed)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb93"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb93-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb93-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;HTML(ani.to_html5_video())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;video width="576" height="576" controls autoplay loop&gt;
&lt;source type="video/mp4" src="data:video/mp4;base64,AAAAIGZ0eXBNNFYgAAACAE00ViBpc29taXNvMmF2YzEAAAAIZnJlZQAACuJtZGF0AAACrgYF//+q%0A3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE2MSByMzAzME0gOGJkNmQyOCAtIEguMjY0L01Q%0ARUctNCBBVkMgY29kZWMgLSBDb3B5bGVmdCAyMDAzLTIwMjAgLSBodHRwOi8vd3d3LnZpZGVvbGFu%0ALm9yZy94MjY0Lmh0bWwgLSBvcHRpb25zOiBjYWJhYz0xIHJlZj0zIGRlYmxvY2s9MTowOjAgYW5h%0AbHlzZT0weDM6MHgxMTMgbWU9aGV4IHN1Ym1lPTcgcHN5PTEgcHN5X3JkPTEuMDA6MC4wMCBtaXhl%0AZF9yZWY9MSBtZV9yYW5nZT0xNiBjaHJvbWFfbWU9MSB0cmVsbGlzPTEgOHg4ZGN0PTEgY3FtPTAg%0AZGVhZHpvbmU9MjEsMTEgZmFzdF9wc2tpcD0xIGNocm9tYV9xcF9vZmZzZXQ9LTIgdGhyZWFkcz02%0AIGxvb2thaGVhZF90aHJlYWRzPTEgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50%0AZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MyBi%0AX3B5cmFtaWQ9MiBiX2FkYXB0PTEgYl9iaWFzPTAgZGlyZWN0PTEgd2VpZ2h0Yj0xIG9wZW5fZ29w%0APTAgd2VpZ2h0cD0yIGtleWludD0yNTAga2V5aW50X21pbj01IHNjZW5lY3V0PTQwIGludHJhX3Jl%0AZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAu%0ANjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAE%0AkGWIhAAS//73rd+BTcBA7Wu6Vzi0y6uUND1R9pSmeLZIAAADAAADAAIRcKTdcx9EHWf4AAAhYALW%0AHqH8JyQ4gBKC1ImXhdEKAApKn8Z8m/xAD2TXBZ6JSrZPQJZbqHUXqu9KcDl/RE/0Z1dyxsifoduF%0Ad5I4LCAjieysNMXLIWJQbtOt9VlFXE5wQdeMjQkA79A0hvYMTyUEmYHtBjTar4kE5isdGzhbLlTb%0A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%0AYXZmNTguNDUuMTAw"&gt;
Your browser does not support the video tag. &lt;/source&gt;&lt;/video&gt;
&lt;/center&gt;
&lt;p&gt;As with our optimal row strategy, we can play every possible 10/3 game with the Thompson sampling strategy and compare the distributions of the number of turns.&lt;/p&gt;
&lt;div class="sourceCode" id="cb94"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb94-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb94-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ts_row_games_10_3 &lt;span class="op"&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb94-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb94-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    play(row[np.newaxis, np.newaxis],&lt;/span&gt;
&lt;span id="cb94-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb94-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;         SingleThompsonStrategy(all_rows_10_3[:, np.newaxis, :]))&lt;/span&gt;
&lt;span id="cb94-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb94-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;for&lt;/span&gt; row &lt;span class="kw"&gt;in&lt;/span&gt; all_rows_10_3&lt;/span&gt;
&lt;span id="cb94-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb94-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;
&lt;span id="cb94-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb94-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ts_row_turns_pmf_10_3 &lt;span class="op"&gt;=&lt;/span&gt; Pmf.from_seq([&lt;/span&gt;
&lt;span id="cb94-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb94-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    game.turns &lt;span class="cf"&gt;for&lt;/span&gt; game &lt;span class="kw"&gt;in&lt;/span&gt; ts_row_games_10_3&lt;/span&gt;
&lt;span id="cb94-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb94-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb95"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb95-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb95-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, (opt_ax, ts_ax) &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(nrows&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb95-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb95-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                    figsize&lt;span class="op"&gt;=&lt;/span&gt;(FIG_WIDTH, &lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; FIG_HEIGHT))&lt;/span&gt;
&lt;span id="cb95-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb95-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb95-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb95-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_turn_dist(opt_row_turns_pmf_10_3, color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;opt_ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb95-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb95-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb95-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb95-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_pct_yaxis(opt_ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb95-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb95-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;opt_ax.set_title(&lt;span class="st"&gt;"Optimal play"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb95-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb95-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb95-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb95-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_turn_dist(ts_row_turns_pmf_10_3, color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C1'&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;ts_ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb95-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb95-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb95-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb95-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_pct_yaxis(ts_ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb95-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb95-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ts_ax.set_title(&lt;span class="st"&gt;"Thompson sampling"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb95-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb95-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb95-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb95-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.suptitle(&lt;span class="st"&gt;"Ship size 3, row length 10"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb95-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb95-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_139_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;It turns out that for a single row with a single ship, the Thompson sampling strategy is optimal!&lt;/p&gt;
&lt;center&gt;
&lt;figure&gt;
&lt;img src="https://sinmantyx.files.wordpress.com/2015/05/m6xj1.jpg"&gt; &lt;br&gt;
&lt;caption&gt;
Image credit &lt;a href="https://sinmantyx.wordpress.com/2015/05/29/bayes-theorem-205-hypothesis-fever-and-falsification/"&gt;SINMANTYX&lt;/a&gt;
&lt;/caption&gt;
&lt;/figure&gt;
&lt;/center&gt;
&lt;p&gt;It is extremely cool to me that we can reproduce the optimal strategy without too much domain-specific thought, but just by enumerating all possible boards and sequentially eliminating the ones that are no longer compatible with the observed (revealed) data! This result is particularly exciting because, as we will see, the generalization of the row-optimal strategy to a two-dimensional grid is not straightforward (even for just one ship), but the Thompson sampling approach generalizes much more readily.&lt;/p&gt;
&lt;h3 id="square-one-ship"&gt;Square, one ship&lt;/h3&gt;
&lt;p&gt;We now turn to the case of a square grid with one ship on it to see how these strategies generalize to something closer to standard Battleship.&lt;/p&gt;
&lt;h4 id="random-guessing-1"&gt;Random guessing&lt;/h4&gt;
&lt;p&gt;Once again the number of turns it takes to sink the ship follows a negative hypergeometric distribution. For the 5/5/3 configuration, this distribution is shown below.&lt;/p&gt;
&lt;div class="sourceCode" id="cb96"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb96-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb96-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;random_5_5_3_pmf &lt;span class="op"&gt;=&lt;/span&gt; get_random_guess_dist(&lt;span class="dv"&gt;5&lt;/span&gt;&lt;span class="op"&gt;**&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, &lt;span class="dv"&gt;3&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb97"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb97-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb97-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_turn_dist(random_5_5_3_pmf, kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'line'&lt;/span&gt;, mean&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb97-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb97-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb97-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb97-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_pct_yaxis(ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb97-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb97-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="vs"&gt;r"5/5/3"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_143_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;There are not really any surprises here; the geometry of the board and the ability to have ships orient along rows or columns doesn’t affect the random guessing strategy at all.&lt;/p&gt;
&lt;h4 id="near-optimal"&gt;Near optimal&lt;/h4&gt;
&lt;p&gt;We now construct a near optimal strategy for one ship on a two-dimensional grid based on trying to reduce the problem to search on a one-dimensional row/column as quickly as possible. We call this strategy “near optimal” because we will see that it takes slightly more turns, on average, than a Thompson sampling strategy to sink the ship.&lt;/p&gt;
&lt;p&gt;It is tempting to treat an &lt;span class="math inline"&gt;\(m \times n\)&lt;/span&gt; two-dimensional grid as a &lt;span class="math inline"&gt;\(m \cdot n\)&lt;/span&gt; one-dimensional grid and use the search grid from the above strategy, but this grid will only minimize the turns-to-first-hit when &lt;span class="math inline"&gt;\(m\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(n\)&lt;/span&gt; are &lt;a href="https://en.wikipedia.org/wiki/Coprime_integers"&gt;relatively prime&lt;/a&gt;. To illustrate this fact, we show the results of wrapping the search grid for the 100/2 configuration to the 10/10/2 configuration below.&lt;/p&gt;
&lt;div class="sourceCode" id="cb98"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb98-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb98-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;bad_search_j_1d &lt;span class="op"&gt;=&lt;/span&gt; get_search_cells_1d(&lt;span class="dv"&gt;100&lt;/span&gt;, &lt;span class="dv"&gt;2&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb98-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb98-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;bad_search_i, bad_search_j &lt;span class="op"&gt;=&lt;/span&gt; np.&lt;span class="bu"&gt;divmod&lt;/span&gt;(bad_search_j_1d, &lt;span class="dv"&gt;10&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb98-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb98-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;bad_search_grid &lt;span class="op"&gt;=&lt;/span&gt; np.zeros((&lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;10&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb98-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb98-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;bad_search_grid[bad_search_i, bad_search_j] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb99"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb99-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb99-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_board(bad_search_grid)&lt;/span&gt;
&lt;span id="cb99-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb99-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="vs"&gt;r"Don't do this!"&lt;/span&gt;, fontweight&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'bold'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_147_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Clearly this search strategy can fail to locate a column-oriented ship in an even-numbered column even after fifty guesses!&lt;/p&gt;
&lt;p&gt;Instead, the optimal grid to search for the initial hit (at least for a square grid) is to cycle through the equivalence classes modulo the ship size in each row, as shown below for both the 10/10/2 and the 5/5/3 configurations.&lt;/p&gt;
&lt;div class="sourceCode" id="cb100"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb100-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb100-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; get_search_cells_2d(grid_shape, ship_size):&lt;/span&gt;
&lt;span id="cb100-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb100-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    i, j &lt;span class="op"&gt;=&lt;/span&gt; np.indices(grid_shape)&lt;/span&gt;
&lt;span id="cb100-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb100-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    in_grid &lt;span class="op"&gt;=&lt;/span&gt; (i &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;) &lt;span class="op"&gt;%&lt;/span&gt; ship_size &lt;span class="op"&gt;==&lt;/span&gt; j &lt;span class="op"&gt;%&lt;/span&gt; ship_size&lt;/span&gt;
&lt;span id="cb100-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb100-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb100-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb100-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; i[in_grid], j[in_grid]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb101"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb101-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb101-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;search_i, search_j &lt;span class="op"&gt;=&lt;/span&gt; get_search_cells_2d((&lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;10&lt;/span&gt;), &lt;span class="dv"&gt;2&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb101-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb101-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;search_grid &lt;span class="op"&gt;=&lt;/span&gt; np.zeros((&lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;10&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb101-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb101-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;search_grid[search_i, search_j] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb102"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb102-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb102-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_board(search_grid)&lt;/span&gt;
&lt;span id="cb102-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb102-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="vs"&gt;r"Ship size 3, $5 \times 5$ grid"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_151_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb103"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb103-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb103-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;search_i, search_j &lt;span class="op"&gt;=&lt;/span&gt; get_search_cells_2d((&lt;span class="dv"&gt;5&lt;/span&gt;, &lt;span class="dv"&gt;5&lt;/span&gt;), &lt;span class="dv"&gt;3&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb103-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb103-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;search_grid &lt;span class="op"&gt;=&lt;/span&gt; np.zeros((&lt;span class="dv"&gt;5&lt;/span&gt;, &lt;span class="dv"&gt;5&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb103-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb103-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;search_grid[search_i, search_j] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb104"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb104-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb104-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_board(search_grid)&lt;/span&gt;
&lt;span id="cb104-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb104-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="vs"&gt;r"Ship size 3, $5 \times 5$ grid"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_153_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We can tell that these search grids are optimal because each cell highlighted in red is one cell less than the ship shize away from any other hightlighted cell.&lt;/p&gt;
&lt;p&gt;Once a hit has been found by searching these cells, we have to determine if the ship is oriented along the row or column passing through that cell. For hits near a boundary (in cells less than a ship’s length away from either the top/bottom or left/right edge) we only have to test one cell to decide which way the ship is oriented. For hits at the interior we have to, in general, test two adjacent cells (either left and right or above and below) to determine the orientation of the ship.&lt;/p&gt;
&lt;p&gt;The following plot highlights the cells that only require one test guess to determine the row/column orientation following a hit for the 10/10/3 configuration.&lt;/p&gt;
&lt;div class="sourceCode" id="cb105"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb105-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb105-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;near_edge &lt;span class="op"&gt;=&lt;/span&gt; np.zeros((&lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;10&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb105-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb105-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;i, j &lt;span class="op"&gt;=&lt;/span&gt; np.indices((&lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;10&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb105-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb105-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;near_edge[(i &lt;span class="op"&gt;&amp;lt;&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;) &lt;span class="op"&gt;|&lt;/span&gt; (&lt;span class="dv"&gt;7&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt; i) &lt;span class="op"&gt;|&lt;/span&gt; (j &lt;span class="op"&gt;&amp;lt;&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;) &lt;span class="op"&gt;|&lt;/span&gt; (&lt;span class="dv"&gt;7&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&lt;/span&gt; j)] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb106"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb106-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb106-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(near_edge)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_156_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The strategy outlined here is implemented below.&lt;/p&gt;
&lt;div class="sourceCode" id="cb107"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb107-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; SingleGridStrategy(Strategy):&lt;/span&gt;
&lt;span id="cb107-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;__init__&lt;/span&gt;(&lt;span class="va"&gt;self&lt;/span&gt;, ship_size):&lt;/span&gt;
&lt;span id="cb107-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="va"&gt;self&lt;/span&gt;._ship_size &lt;span class="op"&gt;=&lt;/span&gt; ship_size&lt;/span&gt;
&lt;span id="cb107-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb107-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; next_guess(&lt;span class="va"&gt;self&lt;/span&gt;, revealed):&lt;/span&gt;
&lt;span id="cb107-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;if&lt;/span&gt; revealed.mask.&lt;span class="bu"&gt;all&lt;/span&gt;() &lt;span class="kw"&gt;or&lt;/span&gt; revealed.&lt;span class="bu"&gt;sum&lt;/span&gt;() &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb107-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            next_unmasked &lt;span class="op"&gt;=&lt;/span&gt; (revealed.mask&lt;/span&gt;
&lt;span id="cb107-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                     [search_i, search_j]&lt;/span&gt;
&lt;span id="cb107-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                     .argmax())&lt;/span&gt;
&lt;span id="cb107-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb107-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;return&lt;/span&gt; search_i[next_unmasked], search_j[next_unmasked]&lt;/span&gt;
&lt;span id="cb107-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb107-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            grid_length, _ &lt;span class="op"&gt;=&lt;/span&gt; revealed.shape&lt;/span&gt;
&lt;span id="cb107-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            hit_i, hit_j &lt;span class="op"&gt;=&lt;/span&gt; argmax_2d(revealed)&lt;/span&gt;
&lt;span id="cb107-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ship_size &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;._ship_size&lt;/span&gt;
&lt;span id="cb107-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;/span&gt;
&lt;span id="cb107-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;if&lt;/span&gt; revealed.&lt;span class="bu"&gt;sum&lt;/span&gt;() &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;:                &lt;/span&gt;
&lt;span id="cb107-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;if&lt;/span&gt; hit_i &lt;span class="op"&gt;&amp;lt;&lt;/span&gt; ship_size &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;or&lt;/span&gt; grid_length &lt;span class="op"&gt;-&lt;/span&gt; ship_size &lt;span class="op"&gt;&amp;lt;&lt;/span&gt; hit_i:&lt;/span&gt;
&lt;span id="cb107-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    next_i &lt;span class="op"&gt;=&lt;/span&gt; hit_i &lt;span class="op"&gt;+&lt;/span&gt; (&lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="cf"&gt;if&lt;/span&gt; hit_i &lt;span class="op"&gt;&amp;lt;&lt;/span&gt; ship_size &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="cf"&gt;else&lt;/span&gt; &lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb107-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    &lt;/span&gt;
&lt;span id="cb107-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    &lt;span class="cf"&gt;if&lt;/span&gt; revealed.mask[next_i, hit_j]:&lt;/span&gt;
&lt;span id="cb107-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        &lt;span class="cf"&gt;return&lt;/span&gt; next_i, hit_j&lt;/span&gt;
&lt;span id="cb107-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb107-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        is_row &lt;span class="op"&gt;=&lt;/span&gt; revealed[next_i, hit_j] &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb107-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;elif&lt;/span&gt; hit_j &lt;span class="op"&gt;&amp;lt;&lt;/span&gt; ship_size &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="kw"&gt;or&lt;/span&gt; grid_length &lt;span class="op"&gt;-&lt;/span&gt; ship_size &lt;span class="op"&gt;&amp;lt;&lt;/span&gt; hit_j:&lt;/span&gt;
&lt;span id="cb107-26"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    next_j &lt;span class="op"&gt;=&lt;/span&gt; hit_j &lt;span class="op"&gt;+&lt;/span&gt; (&lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="cf"&gt;if&lt;/span&gt; hit_j &lt;span class="op"&gt;&amp;lt;&lt;/span&gt; ship_size &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="cf"&gt;else&lt;/span&gt; &lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb107-27"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    &lt;/span&gt;
&lt;span id="cb107-28"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    &lt;span class="cf"&gt;if&lt;/span&gt; revealed.mask[hit_i, next_j]:&lt;/span&gt;
&lt;span id="cb107-29"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        &lt;span class="cf"&gt;return&lt;/span&gt; hit_i, next_j&lt;/span&gt;
&lt;span id="cb107-30"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb107-31"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        is_row &lt;span class="op"&gt;=&lt;/span&gt; revealed[hit_i, next_j] &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb107-32"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;elif&lt;/span&gt; revealed.mask[hit_i, hit_j &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;]:&lt;/span&gt;
&lt;span id="cb107-33"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    &lt;span class="cf"&gt;return&lt;/span&gt; hit_i, hit_j &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb107-34"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;elif&lt;/span&gt; revealed.mask[hit_i, hit_j &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;]:&lt;/span&gt;
&lt;span id="cb107-35"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    &lt;span class="cf"&gt;return&lt;/span&gt; hit_i, hit_j &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb107-36"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb107-37"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    is_row &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="va"&gt;False&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb107-38"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;else&lt;/span&gt;:                &lt;/span&gt;
&lt;span id="cb107-39"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                is_row &lt;span class="op"&gt;=&lt;/span&gt; revealed[hit_i].&lt;span class="bu"&gt;sum&lt;/span&gt;() &lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb107-40"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;/span&gt;
&lt;span id="cb107-41"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-41" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;if&lt;/span&gt; is_row:&lt;/span&gt;
&lt;span id="cb107-42"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-42" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;return&lt;/span&gt; hit_i, next_guess_1d_with_hit(revealed[hit_i])&lt;/span&gt;
&lt;span id="cb107-43"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-43" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb107-44"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb107-44" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;return&lt;/span&gt; next_guess_1d_with_hit(revealed[:, hit_j]), hit_j&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This strategy involves quite a bit of branching logic and more than a few magic numbers. While I do not doubt that this implementation can be simplified, avoiding complex branching logic is one of the motivations for a simulation-based Bayesian approach to Battleship.&lt;/p&gt;
&lt;p&gt;To understand the distribution of turns required by this strategy to sink the ship, we define a function that generates all square grids of a given shape with a single ship of a given size.&lt;/p&gt;
&lt;div class="sourceCode" id="cb108"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb108-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; get_all_ships(grid_length, ship_size):&lt;/span&gt;
&lt;span id="cb108-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    rows &lt;span class="op"&gt;=&lt;/span&gt; get_all_ship_rows(grid_length, ship_size)&lt;/span&gt;
&lt;span id="cb108-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    n_rows, _ &lt;span class="op"&gt;=&lt;/span&gt; rows.shape&lt;/span&gt;
&lt;span id="cb108-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb108-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    i &lt;span class="op"&gt;=&lt;/span&gt; np.arange(grid_length)&lt;/span&gt;
&lt;span id="cb108-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb108-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    boards &lt;span class="op"&gt;=&lt;/span&gt; np.zeros((&lt;/span&gt;
&lt;span id="cb108-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        n_rows, grid_length,&lt;/span&gt;
&lt;span id="cb108-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        grid_length, grid_length,&lt;/span&gt;
&lt;span id="cb108-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ))&lt;/span&gt;
&lt;span id="cb108-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    boards[:, i, i, :] &lt;span class="op"&gt;=&lt;/span&gt; rows[:, np.newaxis]&lt;/span&gt;
&lt;span id="cb108-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    long_boards &lt;span class="op"&gt;=&lt;/span&gt; boards.reshape((&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;, grid_length, grid_length))&lt;/span&gt;
&lt;span id="cb108-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb108-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; np.concatenate((&lt;/span&gt;
&lt;span id="cb108-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        long_boards,&lt;/span&gt;
&lt;span id="cb108-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        long_boards.transpose(&lt;span class="dv"&gt;0&lt;/span&gt;, &lt;span class="dv"&gt;2&lt;/span&gt;, &lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb108-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb108-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We generate all possible boards for the 5/5/3 configuration and visualize a few of them.&lt;/p&gt;
&lt;div class="sourceCode" id="cb109"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb109-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb109-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;all_ships_5_5_3 &lt;span class="op"&gt;=&lt;/span&gt; get_all_ships(&lt;span class="dv"&gt;5&lt;/span&gt;, &lt;span class="dv"&gt;3&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb110"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb110-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb110-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(nrows&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb110-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb110-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         figsize&lt;span class="op"&gt;=&lt;/span&gt;(FIG_WIDTH, FIG_WIDTH))&lt;/span&gt;
&lt;span id="cb110-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb110-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb110-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb110-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plt_boards &lt;span class="op"&gt;=&lt;/span&gt; rng.choice(all_ships_5_5_3, size&lt;span class="op"&gt;=&lt;/span&gt;axes.size, replace&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb110-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb110-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb110-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb110-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;for&lt;/span&gt; (board, ax) &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;zip&lt;/span&gt;(plt_boards, axes.flat):&lt;/span&gt;
&lt;span id="cb110-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb110-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    plot_board(board, ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb110-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb110-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb110-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb110-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.suptitle(&lt;span class="st"&gt;"Four boards, 5/5/3"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb110-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb110-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_163_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We now play all 5/5/3 games using this strategy.&lt;/p&gt;
&lt;div class="sourceCode" id="cb111"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb111-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb111-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid_games_5_5_3 &lt;span class="op"&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb111-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb111-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    play(ship[np.newaxis], SingleGridStrategy(&lt;span class="dv"&gt;3&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb111-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb111-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;for&lt;/span&gt; ship &lt;span class="kw"&gt;in&lt;/span&gt; all_ships_5_5_3&lt;/span&gt;
&lt;span id="cb111-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb111-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;
&lt;span id="cb111-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb111-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid_turns_pmf_5_5_3 &lt;span class="op"&gt;=&lt;/span&gt; Pmf.from_seq([&lt;/span&gt;
&lt;span id="cb111-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb111-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    game.turns &lt;span class="cf"&gt;for&lt;/span&gt; game &lt;span class="kw"&gt;in&lt;/span&gt; grid_games_5_5_3&lt;/span&gt;
&lt;span id="cb111-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb111-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb112"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb112-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb112-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_turn_dist(grid_turns_pmf_5_5_3,&lt;/span&gt;
&lt;span id="cb112-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb112-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C1'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Near optimal"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb112-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb112-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    mean&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, mean_kwargs&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;'c'&lt;/span&gt;: &lt;span class="st"&gt;'C1'&lt;/span&gt;})&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb112-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb112-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_turn_dist(random_5_5_3_pmf,&lt;/span&gt;
&lt;span id="cb112-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb112-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'line'&lt;/span&gt;, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb112-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb112-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               mean&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, mean_kwargs&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;'c'&lt;/span&gt;: &lt;span class="st"&gt;'C0'&lt;/span&gt;},&lt;/span&gt;
&lt;span id="cb112-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb112-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Random"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb112-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb112-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;/span&gt;
&lt;span id="cb112-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb112-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb112-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb112-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_pct_yaxis(ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb112-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb112-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb112-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb112-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_166_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that this near optimal strategy is an significant improvement over random guessing (which is expected). Intuitively, it seems odd that the distribution is bimodal. In fact, we will see after implementing Thompson sampling in the two-dimensional case, that this strategy is definitely not optimal.&lt;/p&gt;
&lt;h4 id="bayesian-thompson-sampling-1"&gt;Bayesian (Thompson sampling)&lt;/h4&gt;
&lt;p&gt;The generalization of one-dimensional Thompson sampling to a two-dimensional grid is much simpler than the above generalization of the one-dimensional optimal strategy. The implementation of Thompson sampling for a single ship in two dimensions is shown below.&lt;/p&gt;
&lt;div class="sourceCode" id="cb113"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb113-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; SingleThompsonStrategy(Strategy):&lt;/span&gt;
&lt;span id="cb113-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;__init__&lt;/span&gt;(&lt;span class="va"&gt;self&lt;/span&gt;, poss_ships):&lt;/span&gt;
&lt;span id="cb113-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="va"&gt;self&lt;/span&gt;._poss_ships &lt;span class="op"&gt;=&lt;/span&gt; poss_ships&lt;/span&gt;
&lt;span id="cb113-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb113-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; compat_ships(&lt;span class="va"&gt;self&lt;/span&gt;, revealed):&lt;/span&gt;
&lt;span id="cb113-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;if&lt;/span&gt; revealed.mask.&lt;span class="bu"&gt;all&lt;/span&gt;():&lt;/span&gt;
&lt;span id="cb113-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;._poss_ships&lt;/span&gt;
&lt;span id="cb113-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb113-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            is_compat_ &lt;span class="op"&gt;=&lt;/span&gt; is_compat(&lt;span class="va"&gt;self&lt;/span&gt;._poss_ships, revealed)&lt;/span&gt;
&lt;span id="cb113-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb113-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="va"&gt;self&lt;/span&gt;._poss_ships[is_compat_]&lt;/span&gt;
&lt;span id="cb113-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb113-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; next_guess(&lt;span class="va"&gt;self&lt;/span&gt;, revealed):&lt;/span&gt;
&lt;span id="cb113-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        post &lt;span class="op"&gt;=&lt;/span&gt; np.ma.masked_array(&lt;/span&gt;
&lt;span id="cb113-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="va"&gt;self&lt;/span&gt;.compat_ships(revealed).mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb113-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            mask&lt;span class="op"&gt;=~&lt;/span&gt;revealed.mask&lt;/span&gt;
&lt;span id="cb113-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        )&lt;/span&gt;
&lt;span id="cb113-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb113-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb113-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; argmax_2d(post)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now play all 5/5/3 games with this strategy to understand its turn distribution.&lt;/p&gt;
&lt;div class="sourceCode" id="cb114"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb114-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb114-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ts_games_5_5_3 &lt;span class="op"&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb114-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb114-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    play(ship[np.newaxis], SingleThompsonStrategy(all_ships_5_5_3))&lt;/span&gt;
&lt;span id="cb114-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb114-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;for&lt;/span&gt; ship &lt;span class="kw"&gt;in&lt;/span&gt; all_ships_5_5_3&lt;/span&gt;
&lt;span id="cb114-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb114-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;
&lt;span id="cb114-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb114-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ts_turns_pmf_5_5_3 &lt;span class="op"&gt;=&lt;/span&gt; Pmf.from_seq([&lt;/span&gt;
&lt;span id="cb114-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb114-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    game.turns &lt;span class="cf"&gt;for&lt;/span&gt; game &lt;span class="kw"&gt;in&lt;/span&gt; ts_games_5_5_3&lt;/span&gt;
&lt;span id="cb114-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb114-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As alluded to above, we see that the turn distribution for Thompson sampling is concentrated to the left of the turn distribution for our near optimal strategy.&lt;/p&gt;
&lt;div class="sourceCode" id="cb115"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb115-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb115-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_turn_dist(grid_turns_pmf_5_5_3,&lt;/span&gt;
&lt;span id="cb115-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb115-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C1'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Near optimal"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb115-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb115-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    mean&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, mean_kwargs&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;'c'&lt;/span&gt;: &lt;span class="st"&gt;'C1'&lt;/span&gt;})&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb115-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb115-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_turn_dist(random_5_5_3_pmf,&lt;/span&gt;
&lt;span id="cb115-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb115-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'line'&lt;/span&gt;, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb115-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb115-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               mean&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, mean_kwargs&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;'c'&lt;/span&gt;: &lt;span class="st"&gt;'C0'&lt;/span&gt;},&lt;/span&gt;
&lt;span id="cb115-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb115-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Random"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb115-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb115-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;/span&gt;
&lt;span id="cb115-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb115-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_turn_dist(ts_turns_pmf_5_5_3,&lt;/span&gt;
&lt;span id="cb115-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb115-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C2'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Thompson sampling"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb115-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb115-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               mean&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, mean_kwargs&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;'c'&lt;/span&gt;: &lt;span class="st"&gt;'C2'&lt;/span&gt;},&lt;/span&gt;
&lt;span id="cb115-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb115-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb115-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb115-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb115-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb115-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_pct_yaxis(ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb115-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb115-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb115-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb115-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'upper right'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_173_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Note that while the turn distribution for Thompson sampling is concentrated further to the left, the expected numbers of turns for Thompson sampling and our near optimal strategy, indicated by the dashed vertical lines, are quite close.&lt;/p&gt;
&lt;p&gt;No doubt we could improve the logic of our near optimal strategy to match (or perhaps even beat) Thompson sampling, but the generalization of Thompson sampling to the two-dimensional grid is so much more elegant that it seems hardly worthwhile.&lt;/p&gt;
&lt;h3 id="standard-battleship"&gt;Standard battleship&lt;/h3&gt;
&lt;p&gt;Now that we understand these approaches to simplified versions of Battleship, we are ready to tackle the Thompson sampling approach to standard Battleship.&lt;/p&gt;
&lt;h4 id="random"&gt;Random&lt;/h4&gt;
&lt;p&gt;From above we recall the turn distribution for random guessing at standard Battleship.&lt;/p&gt;
&lt;div class="sourceCode" id="cb116"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb116-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb116-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_turn_ax.figure&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_176_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;h4 id="optimistic-expected-values"&gt;Optimistic expected values&lt;/h4&gt;
&lt;p&gt;Generalizing the optimal one-dimensional strategy to two dimensions was sufficiently difficult that we do not attempt to define even a near optimal strategy for standard Battleship. Configurations where several ships are adjacent, such as the one shown below, will certainly lead to complex and bug-prone branching logic.&lt;/p&gt;
&lt;div class="sourceCode" id="cb117"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb117-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb117-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships &lt;span class="op"&gt;=&lt;/span&gt; np.zeros((n_ships, GRID_LENGTH, GRID_LENGTH))&lt;/span&gt;
&lt;span id="cb117-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb117-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships[&lt;span class="dv"&gt;0&lt;/span&gt;, &lt;span class="dv"&gt;0&lt;/span&gt;, :&lt;span class="dv"&gt;5&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb117-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb117-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships[&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;1&lt;/span&gt;, :&lt;span class="dv"&gt;4&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb117-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb117-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships[&lt;span class="dv"&gt;2&lt;/span&gt;, &lt;span class="dv"&gt;2&lt;/span&gt;, :&lt;span class="dv"&gt;3&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb117-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb117-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships[&lt;span class="dv"&gt;3&lt;/span&gt;, &lt;span class="dv"&gt;3&lt;/span&gt;, :&lt;span class="dv"&gt;3&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb117-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb117-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships[&lt;span class="dv"&gt;4&lt;/span&gt;, &lt;span class="dv"&gt;4&lt;/span&gt;, :&lt;span class="dv"&gt;2&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb118"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb118-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb118-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(ncols&lt;span class="op"&gt;=&lt;/span&gt;n_ships, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb118-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb118-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         figsize&lt;span class="op"&gt;=&lt;/span&gt;(n_ships &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="fl"&gt;2.5&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb118-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb118-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb118-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb118-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;for&lt;/span&gt; (ship, name, ax) &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;zip&lt;/span&gt;(ships, SHIP_NAMES, axes):&lt;/span&gt;
&lt;span id="cb118-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb118-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    plot_board(ship, ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb118-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb118-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb118-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb118-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_xticklabels([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb118-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb118-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_yticklabels([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb118-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb118-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_title(name)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb118-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb118-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb118-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb118-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_179_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb119"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb119-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb119-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(to_board(ships))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_180_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;In spite of these challenges, we will want to at least be able to benchmark the average number of turns Thompson sampling requires against other approaches. Fortunately we can propose several scenarios for which the expected number of turns is straightforward to calculate.&lt;/p&gt;
&lt;h3 id="extremely-optimistic"&gt;Extremely optimistic&lt;/h3&gt;
&lt;p&gt;We can make two assumptions to get a reasonable floor on the expected number of turns.&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;The first five hits we get are each from a different ship.&lt;/li&gt;
&lt;li&gt;As soon as we hit a ship, we know the complete location of that ship.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Together with a search strategy for the first five hits, we can calculate the expected value in this unrealistic but instructive scenario. Weakening these assumptions also leads to more realistic expected values to which we can compare the performance of Thompson sampling.&lt;/p&gt;
&lt;p&gt;A fairly efficient search strategy for the first five hits in standard Battle ship is to search a mod-two grid (since the smallest ship has size two).&lt;/p&gt;
&lt;div class="sourceCode" id="cb120"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb120-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb120-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;search_i, search_j &lt;span class="op"&gt;=&lt;/span&gt; get_search_cells_2d((&lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;10&lt;/span&gt;), &lt;span class="dv"&gt;2&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb120-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb120-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;search_grid &lt;span class="op"&gt;=&lt;/span&gt; np.zeros((&lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;10&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb120-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb120-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;search_grid[search_i, search_j] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb121"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb121-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb121-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_board(search_grid)&lt;/span&gt;
&lt;span id="cb121-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb121-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="vs"&gt;r"Standard Battleship"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_183_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The distribution of the number of turns it takes to get five hits in these fifty cells is given below.&lt;/p&gt;
&lt;div class="sourceCode" id="cb122"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb122-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb122-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;extreme_hit_pmf &lt;span class="op"&gt;=&lt;/span&gt; get_random_guess_dist(search_grid.&lt;span class="bu"&gt;sum&lt;/span&gt;(),&lt;/span&gt;
&lt;span id="cb122-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb122-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                        np.ceil(SHIP_SIZES &lt;span class="op"&gt;/&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;).&lt;span class="bu"&gt;sum&lt;/span&gt;(),&lt;/span&gt;
&lt;span id="cb122-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb122-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                        n_hit&lt;span class="op"&gt;=&lt;/span&gt;SHIP_SIZES.size)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb123"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb123-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb123-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_turn_dist(extreme_hit_pmf, mean&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb123-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb123-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb123-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb123-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_pct_yaxis(ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb123-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb123-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Finding five ships on a&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb123-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb123-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             &lt;span class="vs"&gt;r"$10 \times 10$ grid (optimistically)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_186_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Under the second assumption, it will take us 12 more guesses to sink all the ships, so the expected number of turns to solve the game (optimistically) is&lt;/p&gt;
&lt;div class="sourceCode" id="cb124"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb124-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb124-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;extreme_ev &lt;span class="op"&gt;=&lt;/span&gt; extreme_hit_pmf.mean() &lt;span class="op"&gt;+&lt;/span&gt; (SHIP_SIZES &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;).&lt;span class="bu"&gt;sum&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb125"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb125-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb125-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;extreme_ev&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;40.18181818181814&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Under the slightly more conservative (but still optimistic) assumption that it takes on average one and a half misses to determine the location and orientation of a ship, the expected value becomes&lt;/p&gt;
&lt;div class="sourceCode" id="cb127"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb127-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb127-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;optim_ev &lt;span class="op"&gt;=&lt;/span&gt; extreme_hit_pmf.mean() &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="fl"&gt;1.5&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; SHIP_SIZES.size &lt;span class="op"&gt;+&lt;/span&gt; (SHIP_SIZES &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;).&lt;span class="bu"&gt;sum&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb128"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb128-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb128-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;optim_ev&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;42.68181818181814&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We will use these two figures to benchmark the performance of Thompson sampling for standard Battleship in the next section.&lt;/p&gt;
&lt;h4 id="bayesian-thompson-sampling-2"&gt;Bayesian (Thompson sampling)&lt;/h4&gt;
&lt;p&gt;Generalizing the Thompson sampling strategy from one ship on a two-dimensional grid to standard Battleship is slighly more conceptually involved than generalize from one- to two-dimensional grids with one ship, but not too much more.&lt;/p&gt;
&lt;p&gt;The generalization also requires some computational optimizations, as we can no longer expect to enumerate and store all possible configurations of the board on reasonably sized hardware. To illustrate this and facilitate our eventual solution to this issue, we generate all possible configurations of each ship.&lt;/p&gt;
&lt;div class="sourceCode" id="cb130"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb130-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb130-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;all_ships &lt;span class="op"&gt;=&lt;/span&gt; [get_all_ships(GRID_LENGTH, ship_size) &lt;span class="cf"&gt;for&lt;/span&gt; ship_size &lt;span class="kw"&gt;in&lt;/span&gt; SHIP_SIZES]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Even though we can enumerate the possibilities for each ship easily,&lt;/p&gt;
&lt;div class="sourceCode" id="cb131"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb131-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb131-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_ship_grids &lt;span class="op"&gt;=&lt;/span&gt; np.array([&lt;span class="bu"&gt;len&lt;/span&gt;(ships) &lt;span class="cf"&gt;for&lt;/span&gt; ships &lt;span class="kw"&gt;in&lt;/span&gt; all_ships])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb132"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb132-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb132-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_ship_grids&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;array([120, 140, 160, 160, 180])&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;there are more than &lt;span class="math inline"&gt;\(10^{10}\)&lt;/span&gt; possible combinations in the cartesian product of these configurations&lt;/p&gt;
&lt;div class="sourceCode" id="cb134"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb134-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb134-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;np.log10(n_ship_grids).&lt;span class="bu"&gt;sum&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;10.88882175214102&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, not all elements of the Cartesian product produce valid boards (the ships may overlap). An example of such an element is given below.&lt;/p&gt;
&lt;div class="sourceCode" id="cb136"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb136-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb136-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships &lt;span class="op"&gt;=&lt;/span&gt; np.zeros((n_ships, GRID_LENGTH, GRID_LENGTH))&lt;/span&gt;
&lt;span id="cb136-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb136-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships[&lt;span class="dv"&gt;0&lt;/span&gt;, &lt;span class="dv"&gt;0&lt;/span&gt;, :&lt;span class="dv"&gt;5&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb136-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb136-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships[&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;0&lt;/span&gt;, :&lt;span class="dv"&gt;4&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb136-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb136-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships[&lt;span class="dv"&gt;2&lt;/span&gt;, &lt;span class="dv"&gt;0&lt;/span&gt;, :&lt;span class="dv"&gt;3&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb136-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb136-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships[&lt;span class="dv"&gt;3&lt;/span&gt;, &lt;span class="dv"&gt;0&lt;/span&gt;, :&lt;span class="dv"&gt;3&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb136-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb136-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships[&lt;span class="dv"&gt;4&lt;/span&gt;, &lt;span class="dv"&gt;0&lt;/span&gt;, :&lt;span class="dv"&gt;2&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb137"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb137-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb137-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(ncols&lt;span class="op"&gt;=&lt;/span&gt;n_ships, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb137-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb137-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         figsize&lt;span class="op"&gt;=&lt;/span&gt;(n_ships &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="fl"&gt;2.5&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb137-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb137-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb137-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb137-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;for&lt;/span&gt; (ship, name, ax) &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;zip&lt;/span&gt;(ships, SHIP_NAMES, axes):&lt;/span&gt;
&lt;span id="cb137-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb137-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    plot_board(ship, ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb137-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb137-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb137-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb137-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_xticklabels([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb137-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb137-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_yticklabels([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb137-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb137-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_title(name)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb137-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb137-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb137-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb137-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_203_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb138"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb138-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb138-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(to_board(ships), vmax&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;5.&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb138-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb138-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           cbar&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb138-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb138-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           cbar_kwargs&lt;span class="op"&gt;=&lt;/span&gt;{&lt;/span&gt;
&lt;span id="cb138-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb138-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               &lt;span class="st"&gt;'format'&lt;/span&gt;: &lt;span class="st"&gt;'&lt;/span&gt;&lt;span class="sc"&gt;%d&lt;/span&gt;&lt;span class="st"&gt;'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb138-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb138-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               &lt;span class="st"&gt;'label'&lt;/span&gt;: &lt;span class="st"&gt;"Number of ships"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb138-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb138-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           })&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_204_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The following function tests to see if an array of ship grids constitutes a valid board (has no overlap).&lt;/p&gt;
&lt;div class="sourceCode" id="cb139"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb139-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb139-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; has_no_overlap(ships, ship_axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;, board_axis&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, &lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)):&lt;/span&gt;
&lt;span id="cb139-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb139-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; (to_board(ships, ship_axis&lt;span class="op"&gt;=&lt;/span&gt;ship_axis)&lt;/span&gt;
&lt;span id="cb139-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb139-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .&lt;span class="bu"&gt;max&lt;/span&gt;(axis&lt;span class="op"&gt;=&lt;/span&gt;board_axis) &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb139-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb139-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb140"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb140-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb140-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;has_no_overlap(ships)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;False&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Even eliminating sets of ships that do overlap, there are still too many possible boards to enumerate. To address this challenge we will switch from Thompson &lt;em&gt;enumeration&lt;/em&gt;, which is a more proper description of what we’ve been doing so far to Thompson &lt;em&gt;sampling&lt;/em&gt;. Instead of enumerating all boards compatible with the currently revealed information and choosing the unknown cell with the highest posterior probability of yielding a hit, we will draw a sample from the posterior distribution of compatible boards, calculate the cell most likely to yield a hit based on this sample to use as the next guess.&lt;/p&gt;
&lt;p&gt;This sampling approach means we only need to be able to simulate random games of Battleship and check if they are compatible with the currently revealed information in order to generalize Thompson sampling to standard Battleship. Simulating random games of Battleship is not particularly hard, but simulating games compatible with boards that have many spots revealed can take a prohibitively long time if done naively by sampling from each ship’s possible configurations and then testing to see if the product of the samples is compatible. (I have tried this and had it take over an hour to generate a compatible sample with approximately 30 cells revealed.)&lt;/p&gt;
&lt;p&gt;Fortunately we can address this issue by intelligently propagating hits and misses from the aggregate board to each ship’s grid and restricting to a subset of each ship’s position that is more likely to produce a compatible board when combined with all the other ship samples.&lt;/p&gt;
&lt;p&gt;Before walking through this process, we introduce the machinery necessary to sample random (compatible) boards.&lt;/p&gt;
&lt;div class="sourceCode" id="cb142"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb142-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; _sample_compat_ships_block(poss_ships, revealed,&lt;/span&gt;
&lt;span id="cb142-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               rng&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, block_size&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;10_000&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb142-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; rng &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb142-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        rng &lt;span class="op"&gt;=&lt;/span&gt; np.random.default_rng()&lt;/span&gt;
&lt;span id="cb142-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb142-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    samples &lt;span class="op"&gt;=&lt;/span&gt; np.stack([&lt;/span&gt;
&lt;span id="cb142-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            rng.choice(ships, size&lt;span class="op"&gt;=&lt;/span&gt;block_size, shuffle&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb142-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;for&lt;/span&gt; ships &lt;span class="kw"&gt;in&lt;/span&gt; poss_ships&lt;/span&gt;
&lt;span id="cb142-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ],&lt;/span&gt;
&lt;span id="cb142-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb142-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb142-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb142-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    has_no_overlap_ &lt;span class="op"&gt;=&lt;/span&gt; has_no_overlap(samples, ship_axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb142-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    valid_samples &lt;span class="op"&gt;=&lt;/span&gt; samples[has_no_overlap_]&lt;/span&gt;
&lt;span id="cb142-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb142-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; revealed.mask.&lt;span class="bu"&gt;all&lt;/span&gt;():&lt;/span&gt;
&lt;span id="cb142-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; valid_samples&lt;/span&gt;
&lt;span id="cb142-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb142-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        is_compat_ &lt;span class="op"&gt;=&lt;/span&gt; is_compat(to_board(valid_samples, ship_axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;), revealed)&lt;/span&gt;
&lt;span id="cb142-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb142-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; valid_samples[is_compat_]&lt;/span&gt;
&lt;span id="cb142-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb142-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; sample_compat_ships_block(poss_ships, revealed,&lt;/span&gt;
&lt;span id="cb142-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                              rng&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, block_size&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;10_000&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb142-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    block &lt;span class="op"&gt;=&lt;/span&gt; []&lt;/span&gt;
&lt;span id="cb142-26"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb142-27"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;while&lt;/span&gt; &lt;span class="bu"&gt;len&lt;/span&gt;(block) &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb142-28"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        block &lt;span class="op"&gt;=&lt;/span&gt; _sample_compat_ships_block(&lt;/span&gt;
&lt;span id="cb142-29"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            poss_ships, revealed,&lt;/span&gt;
&lt;span id="cb142-30"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            rng&lt;span class="op"&gt;=&lt;/span&gt;rng, block_size&lt;span class="op"&gt;=&lt;/span&gt;block_size&lt;/span&gt;
&lt;span id="cb142-31"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        )&lt;/span&gt;
&lt;span id="cb142-32"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb142-33"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; block&lt;/span&gt;
&lt;span id="cb142-34"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb142-35"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb142-36"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; generate_compat_ships(poss_ships, revealed,&lt;/span&gt;
&lt;span id="cb142-37"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                          rng&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, block_size&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;10_000&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb142-38"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;while&lt;/span&gt; &lt;span class="va"&gt;True&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb142-39"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;yield&lt;/span&gt; &lt;span class="im"&gt;from&lt;/span&gt; sample_compat_ships_block(&lt;/span&gt;
&lt;span id="cb142-40"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            poss_ships, revealed,&lt;/span&gt;
&lt;span id="cb142-41"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-41" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            rng&lt;span class="op"&gt;=&lt;/span&gt;rng, block_size&lt;span class="op"&gt;=&lt;/span&gt;block_size&lt;/span&gt;
&lt;span id="cb142-42"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb142-42" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        )&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb143"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb143-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb143-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; take(n, gen, progress_bar&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb143-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb143-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    n_range &lt;span class="op"&gt;=&lt;/span&gt; trange(n) &lt;span class="cf"&gt;if&lt;/span&gt; progress_bar &lt;span class="cf"&gt;else&lt;/span&gt; &lt;span class="bu"&gt;range&lt;/span&gt;(n)&lt;/span&gt;
&lt;span id="cb143-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb143-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb143-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb143-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; [x &lt;span class="cf"&gt;for&lt;/span&gt; _, x &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;zip&lt;/span&gt;(n_range, gen)]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb144"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb144-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; sample_compat_ships(poss_ships, revealed, n,&lt;/span&gt;
&lt;span id="cb144-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        rng&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, block_size&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;10_000&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb144-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        progress_bar&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb144-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    compat_gen &lt;span class="op"&gt;=&lt;/span&gt; generate_compat_ships(poss_ships, revealed,&lt;/span&gt;
&lt;span id="cb144-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                       rng&lt;span class="op"&gt;=&lt;/span&gt;rng)&lt;/span&gt;
&lt;span id="cb144-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb144-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; np.array(take(n, compat_gen,&lt;/span&gt;
&lt;span id="cb144-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         progress_bar&lt;span class="op"&gt;=&lt;/span&gt;progress_bar))&lt;/span&gt;
&lt;span id="cb144-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb144-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; sample_ships(poss_ships, n,&lt;/span&gt;
&lt;span id="cb144-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 rng&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, block_size&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;10_000&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb144-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 progress_bar&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb144-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    empty &lt;span class="op"&gt;=&lt;/span&gt; np.ma.masked_all_like(all_ships[&lt;span class="dv"&gt;0&lt;/span&gt;][&lt;span class="dv"&gt;0&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb144-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb144-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; sample_compat_ships(poss_ships, empty, n,&lt;/span&gt;
&lt;span id="cb144-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               rng&lt;span class="op"&gt;=&lt;/span&gt;rng, block_size&lt;span class="op"&gt;=&lt;/span&gt;block_size,&lt;/span&gt;
&lt;span id="cb144-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb144-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               progress_bar&lt;span class="op"&gt;=&lt;/span&gt;progress_bar)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We plot four randomly sampled boards below.&lt;/p&gt;
&lt;div class="sourceCode" id="cb145"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb145-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb145-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ships &lt;span class="op"&gt;=&lt;/span&gt; sample_ships(all_ships, &lt;span class="dv"&gt;4&lt;/span&gt;, rng&lt;span class="op"&gt;=&lt;/span&gt;rng)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb146"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb146-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb146-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(nrows&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb146-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb146-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         figsize&lt;span class="op"&gt;=&lt;/span&gt;(FIG_WIDTH, FIG_WIDTH))&lt;/span&gt;
&lt;span id="cb146-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb146-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb146-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb146-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;for&lt;/span&gt; (ships_, ax) &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;zip&lt;/span&gt;(ships, axes.flat):&lt;/span&gt;
&lt;span id="cb146-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb146-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    plot_board(to_board(ships_), ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb146-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb146-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb146-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb146-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.suptitle(&lt;span class="st"&gt;"Four boards, standard Battleship"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb146-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb146-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_214_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;To illustrate how long it can take to sample compatible boards from the full Cartesian product, we randomly mask one third of the cells in the first board above and attempt to sample a compatible board.&lt;/p&gt;
&lt;div class="sourceCode" id="cb147"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb147-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb147-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;masked_i, masked_j &lt;span class="op"&gt;=&lt;/span&gt; rng.choice(&lt;/span&gt;
&lt;span id="cb147-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb147-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    np.indices((GRID_LENGTH, GRID_LENGTH)).reshape(&lt;span class="dv"&gt;2&lt;/span&gt;, &lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb147-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb147-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    size&lt;span class="op"&gt;=&lt;/span&gt;GRID_LENGTH&lt;span class="op"&gt;**&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="op"&gt;//&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;, axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb147-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb147-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    replace&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, shuffle&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb147-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb147-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb147-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb147-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;mask &lt;span class="op"&gt;=&lt;/span&gt; np.full((GRID_LENGTH, GRID_LENGTH), &lt;span class="va"&gt;False&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb147-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb147-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;mask[masked_i, masked_j] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="va"&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb147-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb147-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb147-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb147-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed &lt;span class="op"&gt;=&lt;/span&gt; np.ma.masked_array(to_board(ships[&lt;span class="dv"&gt;0&lt;/span&gt;]), mask&lt;span class="op"&gt;=&lt;/span&gt;mask)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb148"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb148-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb148-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(revealed)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_217_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb149"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb149-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb149-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;start &lt;span class="op"&gt;=&lt;/span&gt; datetime.datetime.now()&lt;/span&gt;
&lt;span id="cb149-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb149-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb149-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb149-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;try&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb149-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb149-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    sample_compat_ships(all_ships, revealed, &lt;span class="dv"&gt;1&lt;/span&gt;, rng&lt;span class="op"&gt;=&lt;/span&gt;rng)&lt;/span&gt;
&lt;span id="cb149-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb149-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;except&lt;/span&gt; &lt;span class="pp"&gt;KeyboardInterrupt&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb149-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb149-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    end &lt;span class="op"&gt;=&lt;/span&gt; datetime.datetime.now()&lt;/span&gt;
&lt;span id="cb149-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb149-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb149-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb149-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="bu"&gt;print&lt;/span&gt;(&lt;span class="st"&gt;"You gave up trying to sample a compatible board"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb149-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb149-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          &lt;span class="ss"&gt;f"after &lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;(end &lt;span class="op"&gt;-&lt;/span&gt; start)&lt;span class="sc"&gt;.&lt;/span&gt;total_seconds()&lt;span class="sc"&gt;:.1f}&lt;/span&gt;&lt;span class="ss"&gt; seconds"&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You gave up trying to sample a compatible boardafter 59.4 seconds&lt;/p&gt;
&lt;p&gt;In order to implement the strategy for sampling compatible boards outlined above, we need to think about how to propagate hit/miss information about the combined board to each ship. For a miss, this propagation is easy, as all ships must have been missed. Propagating the information from a hit is much trickier, since in general we don’t know which ship was hit. We do however, know which ship was hit when our opponent announces that we sank one of their ships, because they have to tell us which one.&lt;/p&gt;
&lt;p&gt;To implement Thompson sampling for standard Battleship then, we track not just what has been revealed, but what we can conclude has been revealed per ship. We use this per-ship revealed information to reduce our possibilities the compatible ship grids &lt;em&gt;before&lt;/em&gt; sampling, then sample from the Cartesian product of these reduced sets, which produces compatible samples in at most seconds, even when many cells have been revealed.&lt;/p&gt;
&lt;p&gt;Of course there are many situations where we can infer which ship has been hit. Consider the following board.&lt;/p&gt;
&lt;div class="sourceCode" id="cb150"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb150-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb150-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed &lt;span class="op"&gt;=&lt;/span&gt; np.ma.masked_all((&lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;10&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb150-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb150-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed[&lt;span class="dv"&gt;0&lt;/span&gt;, :&lt;span class="dv"&gt;2&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb150-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb150-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed[&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;2&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb150-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb150-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;revealed[&lt;span class="dv"&gt;2&lt;/span&gt;, :&lt;span class="dv"&gt;2&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb151"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb151-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb151-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_board(revealed)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_221_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;If guessing (1, 0) results in a hit, we can obviously conclude that the patrol boat was hit. We do not account for situations such as this when propagating hit information from the combined board to individual ships to avoid cumbersome and error-prone conditional logic in our strategy. (In fact, Thompson sampling accounts for this automatically without a special rule, as there will be only one possible position for the patrol boat compatible with this revealed information.)&lt;/p&gt;
&lt;p&gt;We implement Thompson sampling for standard Battleship as described above.&lt;/p&gt;
&lt;div class="sourceCode" id="cb152"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb152-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; ThompsonStrategy(Strategy):&lt;/span&gt;
&lt;span id="cb152-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;__init__&lt;/span&gt;(&lt;span class="va"&gt;self&lt;/span&gt;, all_ships, rng&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, block_size&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;10_000&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb152-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="va"&gt;self&lt;/span&gt;._ship_strats &lt;span class="op"&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb152-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            SingleThompsonStrategy(ships) &lt;span class="cf"&gt;for&lt;/span&gt; ships &lt;span class="kw"&gt;in&lt;/span&gt; all_ships&lt;/span&gt;
&lt;span id="cb152-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ]&lt;/span&gt;
&lt;span id="cb152-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb152-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        n_ship &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="bu"&gt;len&lt;/span&gt;(all_ships)&lt;/span&gt;
&lt;span id="cb152-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        grid_shape &lt;span class="op"&gt;=&lt;/span&gt; all_ships[&lt;span class="dv"&gt;0&lt;/span&gt;][&lt;span class="dv"&gt;0&lt;/span&gt;].shape&lt;/span&gt;
&lt;span id="cb152-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="va"&gt;self&lt;/span&gt;._ships_revealed &lt;span class="op"&gt;=&lt;/span&gt; np.ma.masked_all((n_ship,) &lt;span class="op"&gt;+&lt;/span&gt; grid_shape)&lt;/span&gt;
&lt;span id="cb152-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb152-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="va"&gt;self&lt;/span&gt;._rng &lt;span class="op"&gt;=&lt;/span&gt; rng &lt;span class="cf"&gt;if&lt;/span&gt; rng &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="kw"&gt;not&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt; &lt;span class="cf"&gt;else&lt;/span&gt; np.random.default_rng()&lt;/span&gt;
&lt;span id="cb152-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="va"&gt;self&lt;/span&gt;._block_size &lt;span class="op"&gt;=&lt;/span&gt; block_size&lt;/span&gt;
&lt;span id="cb152-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb152-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; next_guess(&lt;span class="va"&gt;self&lt;/span&gt;, revealed, n&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb152-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        post &lt;span class="op"&gt;=&lt;/span&gt; np.ma.masked_array(&lt;/span&gt;
&lt;span id="cb152-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="va"&gt;self&lt;/span&gt;.sample_post(revealed, n&lt;span class="op"&gt;=&lt;/span&gt;n),&lt;/span&gt;
&lt;span id="cb152-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            mask&lt;span class="op"&gt;=~&lt;/span&gt;revealed.mask&lt;/span&gt;
&lt;span id="cb152-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        )&lt;/span&gt;
&lt;span id="cb152-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb152-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; argmax_2d(post)&lt;/span&gt;
&lt;span id="cb152-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb152-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; sample_post(&lt;span class="va"&gt;self&lt;/span&gt;, revealed, n&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb152-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        all_compat_ships &lt;span class="op"&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb152-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ship_strat.compat_ships(ship_revealed)&lt;/span&gt;
&lt;span id="cb152-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="cf"&gt;for&lt;/span&gt; (ship_strat, ship_revealed)&lt;/span&gt;
&lt;span id="cb152-26"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;zip&lt;/span&gt;(&lt;span class="va"&gt;self&lt;/span&gt;._ship_strats, &lt;span class="va"&gt;self&lt;/span&gt;._ships_revealed)&lt;/span&gt;
&lt;span id="cb152-27"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ]&lt;/span&gt;
&lt;span id="cb152-28"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb152-29"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;if&lt;/span&gt; n &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb152-30"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            compat_samples &lt;span class="op"&gt;=&lt;/span&gt; sample_compat_ships_block(&lt;/span&gt;
&lt;span id="cb152-31"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                all_compat_ships, revealed,&lt;/span&gt;
&lt;span id="cb152-32"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                rng&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;self&lt;/span&gt;._rng, block_size&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;self&lt;/span&gt;._block_size&lt;/span&gt;
&lt;span id="cb152-33"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            )&lt;/span&gt;
&lt;span id="cb152-34"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb152-35"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            compat_samples &lt;span class="op"&gt;=&lt;/span&gt; sample_compat_ships(&lt;/span&gt;
&lt;span id="cb152-36"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                all_compat_ships, revealed, n&lt;span class="op"&gt;=&lt;/span&gt;n,&lt;/span&gt;
&lt;span id="cb152-37"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                rng&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;self&lt;/span&gt;._rng, block_size&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;self&lt;/span&gt;._block_size&lt;/span&gt;
&lt;span id="cb152-38"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            )&lt;/span&gt;
&lt;span id="cb152-39"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb152-40"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; to_board(compat_samples, ship_axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;).mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb152-41"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-41" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb152-42"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-42" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; reveal(&lt;span class="va"&gt;self&lt;/span&gt;, i, j, hit_or_miss, sunk):&lt;/span&gt;
&lt;span id="cb152-43"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-43" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;if&lt;/span&gt; hit_or_miss &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="kw"&gt;or&lt;/span&gt; sunk &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="kw"&gt;not&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb152-44"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-44" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="va"&gt;self&lt;/span&gt;._ships_revealed[:, i, j] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb152-45"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-45" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;/span&gt;
&lt;span id="cb152-46"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-46" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="cf"&gt;if&lt;/span&gt; sunk &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="kw"&gt;not&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb152-47"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb152-47" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="va"&gt;self&lt;/span&gt;._ships_revealed[sunk, i, j] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We use this strategy to play a game and visualize the results.&lt;/p&gt;
&lt;div class="sourceCode" id="cb153"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb153-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb153-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;strat &lt;span class="op"&gt;=&lt;/span&gt; ThompsonStrategy(all_ships, rng&lt;span class="op"&gt;=&lt;/span&gt;rng)&lt;/span&gt;
&lt;span id="cb153-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb153-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;game &lt;span class="op"&gt;=&lt;/span&gt; play(ships[&lt;span class="dv"&gt;0&lt;/span&gt;], strat,&lt;/span&gt;
&lt;span id="cb153-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb153-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            progress_bar&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;100%|██████████| 17/17 [00:02&amp;lt;00:00, 7.06it/s]&lt;/p&gt;
&lt;div class="sourceCode" id="cb154"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb154-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb154-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;game.turns&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;46&lt;/code&gt;&lt;/pre&gt;
&lt;div class="sourceCode" id="cb156"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb156-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb156-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%%&lt;/span&gt;capture&lt;/span&gt;
&lt;span id="cb156-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb156-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ani &lt;span class="op"&gt;=&lt;/span&gt; animate_boards(game.turn_revealed)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb157"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb157-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb157-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;HTML(ani.to_html5_video())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;video width="576" height="576" controls autoplay loop&gt;
&lt;source type="video/mp4" src="data:video/mp4;base64,AAAAIGZ0eXBNNFYgAAACAE00ViBpc29taXNvMmF2YzEAAAAIZnJlZQAARKBtZGF0AAACrgYF//+q%0A3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE2MSByMzAzME0gOGJkNmQyOCAtIEguMjY0L01Q%0ARUctNCBBVkMgY29kZWMgLSBDb3B5bGVmdCAyMDAzLTIwMjAgLSBodHRwOi8vd3d3LnZpZGVvbGFu%0ALm9yZy94MjY0Lmh0bWwgLSBvcHRpb25zOiBjYWJhYz0xIHJlZj0zIGRlYmxvY2s9MTowOjAgYW5h%0AbHlzZT0weDM6MHgxMTMgbWU9aGV4IHN1Ym1lPTcgcHN5PTEgcHN5X3JkPTEuMDA6MC4wMCBtaXhl%0AZF9yZWY9MSBtZV9yYW5nZT0xNiBjaHJvbWFfbWU9MSB0cmVsbGlzPTEgOHg4ZGN0PTEgY3FtPTAg%0AZGVhZHpvbmU9MjEsMTEgZmFzdF9wc2tpcD0xIGNocm9tYV9xcF9vZmZzZXQ9LTIgdGhyZWFkcz02%0AIGxvb2thaGVhZF90aHJlYWRzPTEgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50%0AZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MyBi%0AX3B5cmFtaWQ9MiBiX2FkYXB0PTEgYl9iaWFzPTAgZGlyZWN0PTEgd2VpZ2h0Yj0xIG9wZW5fZ29w%0APTAgd2VpZ2h0cD0yIGtleWludD0yNTAga2V5aW50X21pbj01IHNjZW5lY3V0PTQwIGludHJhX3Jl%0AZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAu%0ANjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAS%0A9mWIhAAT//73sY+BTcgADZc6inof4RWx9JBRerHZoGTqAAADAAADAABOFqne+b9ctAjWAAAHoACZ%0AByc9/EUe/4AG2qc6+aThpBBRCwKukp7fa/Etl/WEUZs41IlOPXfYIL4Aa8xPnr8xL5GnERvmdsxs%0AOq6CLcxGd3VglmGCombmrcQYxlNSTuu2FUcWrShnMv/3Yr9vCtVSBbd4S+IgXYiVQyxbFEqjqMjc%0A61otLyICqeZ/PF2I+TVG1NxxFFeiYKRyvpiD2VThm9+xCfNInpAhDqj+jWEtqp1yPAH5Rg/UgLx6%0AVEOLqfCys/ml1inh2efLDFwO4O71ythTVdxbWjflE4/6pMlj7jdIjfItMsdAHh5PBd4aOsm0M47M%0AhMI+xYiajiZmneWctDLGF2K1RIDr7iAnbXe9lbdokG2tv0aVWLw+TVSKkLGTG56y3NuFVW3SIp55%0AlJX+o2vfkiR6p4UvWRrYLQ9jhhZlBOfWD/dTfWr8yDH9ogKZMbyyPBeDWprmjhDvjI7yxfiUKwAA%0AAwAUNAGnQbzS8K05B5djkc5GgagVX16pnykstIJbhv1+Vo5gwMAtUj1EUzjjBEN02S6dCi5QYmjK%0AEqhdlSuM+HfQmJNm8pGmOXqcj12+8383czstnvitwHklr71YbvFncW9MOkUKIrCFNb12+85Jdp4+%0AOjOgedqxLiOkTlPNSWVxQwVOrQKiCVn8fQdlgdXQA+aZXij/q1afEEd/PUSpGOPbLLH6ce9uQZuC%0Ax2Kd8KsGOsVfNPyoKnYrwBF2Y23skgI/pAYPOkHiZ6Be6Tbs6Wtc7HmosbERTUo05Ftz7MAjuq2o%0ARd1TG1Vpt89p5cz9Dk0uDr///YYNLpQz/akCKQTvdpws0MqujnewWoSng78cBCE6g4UqOslDx4zc%0AjxaGGy0TWQTU1iSavU8XLJlAAAB9p67dxYuGPewvcHLDK03oY40X8O/JXKr1uUu+pbxnupeB4io2%0AkH6Zhq30fIXV8iGSTZt0S729ibNHlq5FoBICgZMcME6npfFCV22QG5t0S716zAPT3P30CcwaNdFO%0AuyG1yu2kalF7JCEpNKHP3knnIF/hR3gktPQc8AWEffILh9iTQAxp18tXRkYUyuAs2HpZgi9yLVIO%0A6LDQBLfN3rUCr8o/QKDCvDc3Z/+G/+L/+CyyESLDCf/FFVftyFF9bcK9Tz0zhy5rkO0HytR6TOG/%0A9Rs9MB2IifrjHZmrTWIA4LPedFGREbxMoj1BIGAUd+e3V8ECsMa9mdoQOdhXiun3ve12lBGNFxcX%0AryZQmamW7Qf5kGoH/fQfoGojsjNFMYhVGufdd2L0Jo1SvB+XTv/FuWZCf0arrTU9ue3w9T+92pFL%0AlUBqIBJKj4BVjlYMKDblATDh3dgtsq7PFyPtvrZAZcS6CzfvC4k+Teu6Rm+pn1KTxgnFfLVWxICl%0APhnQJo3Ey7BJUV2y3qhTXec4n5X6gHRSsFhzT9+2EkrhIYOEPyfJxfoUydqgBUNRn+qjn8jm8S7h%0A+JpQRnl8Y2b1ifswC5yOTcCAYpP7oPdvvGVu5u3S5FEQFnSr5iyVJRzyHLJHo8LdxL1kg9CUMHhW%0APuK+NYFAy2EVkDD99gQ2AelG7PvffoO/LYy2AM4psQAABv9VjboagnvhGjJAA1wDz5B0qXT75p5v%0Ag5OCkA00PyD+7tbfd+dZGGF8w+Ti8PKiWnMSnYi7hx+qDWGsZjHBCGVoXwwkWZ+mu2zlb5pt8s0U%0A7s+AemQ78RIv+4wwaLQCQFAt7fRtsK4HEOKGkYZxE8Z2lJpQ5+8k9FQk3uFzAau7HxMG5eqxcP5A%0ADt4dchPA+NQ+qWOyJ+FZbp/0a620L6wkGMUFti+GOm/r+nA3ev+7IwOa4jJCKdxe53NQXg/D3tgq%0AOt1IWq1DKl6GZ8iSKFZBoV6cTpEyoQ3kuAr91XKNJZc0RZIoEbQab5AS4OYq2iJflcsN6NY9Vbq1%0Av9nqNVwrew9xXmtCOI8V2SEY+QMC1BjsSwwbLHa/jxFj2g6yhz5U1oD/5eD75rDJbTsZU3FQOARQ%0AHPBB0JK2/2ysgJtf1KllbU9HWR95uzuZUHF7YlvD0aveNI+KJxzjEhHqqBFNSyeYnZ9hGbHeS4RQ%0AZvZ0E2IjBSZ8pWh0xPIrHasmKMTUVKfDOgTRztnOma7MLYNTbrlK5OpmL0KpmBxf40L9tUr5S8sI%0A2KKHQkX0fO4sUCpkyrUP2OUc9IHRkkKPdaQ49zP10IKT1JzbIVdJRX/m2kvHqdV5FaJK6qGhKfk9%0AYYqtRbDWGI7fYG545C2PfE0RKkKDUsiunR4ArFelP5cb38ZLAJAfzvEHD7c/vy4AAAyltcSL7sPa%0A6wt8xurZ0PzUUolx8A2NmUUep0F3XRUgkfUVzyroUJrVOKrAUPw4JFQLpgF3lKX5buAa2g5NHdg5%0ApG71fURhasxuPYKRga8FL03H1sllOu/8FQLDzqWzHz7AG3ixjPxAnonAeVPdD6wZNACPJcBityzW%0A07+y1vsNuGtoIn6UT8LRU8SpinBQBUb/yWNsDq8KyctWNFC+u+2TPOVuTHD3rpHsQ2+dT9I+QHq5%0AxpirdcD5o8P6lUHQf7xDKrET/3Z7aT9xh9nLePkPUwIBJK0qtncY4gXXORPwNoM0IoJOcYZ6m+vt%0ARwIDXFjz/19Kq3yPiUgsMpmniSFupr9KBnoxI7IAuSMf4RV38C14Ifl+efmuZRg/cJLThW4UPmYE%0AbAO2hP7wgW1vuzhm4nye2XD+73iEb65OfoLvLMgC4Lud1lovk7eBWkGz8NTdW8Zl6QQtDc3zpYpL%0Ago8w3hi2HRVT1ZU0WN7vGMdflWbmj9oXSuNkH/ulfKHFp6xAn2wKK6Gh2bcHGigBu4aIn2Yb2s9j%0AfJav/4EzVUxgRg9vws4wHvKPDDc+IzVzv56ixu9vvbbLEUGDG/QmtWgVEUzI/YcBaztW5tApzFjG%0AfiBOKf63yVxv0Ein7epMdj5knjwg9Yz4CRWO1mFTHw/TSukJ84AMrPInnPFiPBvelDp3YJFOSils%0A7qoQCBXw7EJ55HabfYNmWB92rRkWLfc/uVw4CPEAPztiVcgS4quE3e0gpVXrr7NDqDdTKRkbXoCx%0ADajskz2PMcF9N2/utY465AVcLWnRcTOiTNZ5fryxn71bdP99Xj9ySHjlgBSBVpHCKgBkLQNsebS6%0Agb45isbeFC1hA44mDekpwVMBKQSYp+5/bzGRZzkTouUg+Wi2oePjZAUxrhNqS5UpDI9HjF9tC9w1%0AlqWenVbKn7pBjEruAb3TrO3/rwenSgdXAmJcwygMuk9ysnSAyfRjwTFMXWGp9fvRiBO9TY0MTnQp%0Ao665RQ8L224qj8fKdyEQmZcSCNfmTsd/ujbej0Ia9BnmXL3UbIlk2QyrPV+MH3rHZ6kvobBrakMW%0AL9zBYtyihJ3hAP8gmsDz+WqgAAAQGnNJHzFCpsXbiWOJ/agXvqaWvbKvvs4P9dokt92kyBEv02SJ%0AMq2dMQFR3jXSmtdgrpfUp4AlTAbivWRXU3k9i28s/4EGjXsTGceb1fcQplCub5UgDHyNp0TofeCD%0A0LAsEVHNU+dNLeZhpvqVQhlDHoLx3sRMxOH99YUUMMdHvA4jwEN06bFJ4Sz8UQkDGo/0MgmL1++h%0ABPZhew7/jiO0oWYV6jaOg6yrm7ggXFn/AxGwNtQko4SxGW8eQgYalG2XpQNPBYl2fubR8udgeSFm%0AdntltpNauzsrJj2S3Utru8LOtnib3iTyHVTbdZM6akeFa5eYk1KLKS12uBvS0F+ZAj0TXvAS2Jy/%0AaKwI13HE7gsVw5KdxrT3uIjDjNLP7SsxjU8NQfHLW359v93SRqrcYxG1/OVGs8noMPnlUAukvjwT%0AgV7wOZzmJcI3cLbnoZRT4tzuHS03yYsBpIf0cxy5blV3+ninSX/9Yy2WkZwBpO4DGCV5xXpT4HaG%0AhUjUx3tVRwlJI484HcuDz3/OG3fP4ziV9J8dw6QXJxHVKMQzzNpRC9z5/CytdNMz9T0V+n1BXTUY%0ANI727/OKDWpkSidJ7fTHdmsVfV5g5NLJe44sdOoHaBo+KzSVHq4h94IOK+PrmylCXjikbDctlXEV%0AawkBi4AdGc0F+C9OIYGN2C4e4DqqaInA1aD+qBn/GWX/V/ct9VECQKHrIK1Ki9jEI/kuraqYhU0j%0ASXcxncl1K3Y4RoHDthuGX6SZZZVZqrsrwNXyGjpADNn9C7hsQe85BVfVvSE2M4IpCTo9bFIlPJsS%0AK8heoUylFMrxZiVdy1Yl7fV2DUYUvyDWcqQQUiTYbkkX57Vs1LKHbPO1yDDGjvLQ/h2qsDRB86P2%0A6LiFNuEtd/GPVb5WKOYnzPSU8S2cjwcYn9ZJBLJb2bpN+JDE5YhEfDofASj9OXs4fLLhWlfetSxD%0AFppH8MwRPVtNkShf1DwGVLdVI4gIPr2dqB03EEnWN3bF/VQwafuMSC04IgTPgdcYEyIKzvD1CtVH%0A9MjOCCIe8NL8QSPPNzkr3sQ4fZe3LYbbNbyodJQEPcqQeESHdPBloL9O+JvZRZYvlcSYk1aAfQsL%0AIHM4MhMjXPbjEXQHD30jIYY9i/kuBnf8YrYkUwA7AWsSF4csVZzkZOaOdYXJHbhYFTE/bbcdoSgW%0ASDlR9p753dLJwpK24+eDxUJ0+12al5gC09LbBN+WmY50CVykVvVN38kOndanFcP/gOLlNVchUfZW%0AzgWN7RzjU9peBT60VGgQlecQo5zCm/0NJT0DV06rhBXu5KhLm3gNIeQ4THkWStkobqkb0XZhNDrV%0AqVOXM0XVUQb6lbmamDlrYUrjQxCAVAcmQeQpE4YpT3V2yGFM68Yr9qJIX6BBgtqExpB476PRC1qy%0A5G04t4bYLTLclnreusA09eUoExyDFnQgWIJ6fm09dPFxcE8GTjsMhneMfhoLjRb+Tjoon2hWrhXB%0AjKzb/2M57bhvTJPpCIYAlCAmU9MXHTtn+0SCXtDCDRFewFppyU2W5yEgJhnEUDrJSwW9WMie2z1Y%0AW1oJFuAMihRRI7R+EAVmQSLMASgN8LKImd5nAOwSzjqCqzfTcFF1n9iY3brqrx8jUUh7SY8yWpRH%0AjpUqnsfyyVJP9WiyUfunLuuLeAAADvZw/zAbwXm4OWPzwQ0iWYLdWslU4DPyhZe0gW/kJWhjpZQM%0AAO4DMSXNF6U5sQjbeWXwlx5zBFK7biz81NWrmgdqSRQFs6jdTNtqQZSIniwt9btVeALT1n0meTaH%0AoVYs+eMhVTAfDp7p7hXiXEts/VhNoMxEqtrH1jLn2w/v5kU+wb/zYLwbZNlXgM9I8C1gkW9qjfwg%0A4InCwfq98wQESN/uJyQz0judcUOaTXQ79bUj3IpRQXFZ03zZvxw9g1TTPxVW/3b8uRS3QL/Z23GB%0AoOHermKPzeMxVS4hTD0CO2b8jTN8BKKZALfBQdcTdsHgsZI4jv/WZeu+o2ABrTn2ZhIemgNanRNI%0Az0qmuPuuf8arqPRjv04AVh/9I/mcsFwxSAYH4D/1TWfCC3WfAocbrrpSt4iQn0hp/rDr3d3F2MkG%0ATcozzjrykL3isyL6pMfw0bKKnlhEriMs2Bc22SwnoCMmaYYM/ZPfmhHz5hZX+vG75rIrKGvmTkFZ%0ASKcgjD/VMCzE+5XnQeLGdaI00OcsF1yyPldtNN9Bts/wB7V7UmGqMzgVokRyMLWUT4F4sO4nYYvo%0AP12YNGK9/B57EL3Li1GVduQZyKfo76J0ZiCTFtBd4U11MxJXpqQu648nfFI3FYklQrDjOR2y7bmW%0AsShaYnDYkzPeRLJ74iwvdeZ2m4FzxdU2aI6J/Ky1V782tIMctdfvuUJGFujlj5bdCqr+AtrdFdEf%0AcOCSmhiEe/NKxNXF873GdEyf0HETnQN1nOYI+z7TbwfwFy1mcV56m1NrlxfQuXmmO0If8wQhEiJs%0A5+Xn9SAAh2SAzPa6qDheL+Lg1HMLzeVRHk23qopu66fujfJ8YQbYl8reO/eABmh2mIGku+O/UopU%0AaBANsxDCjn8BIH8zpJcxXQDAx4++vLlCtWjOLDoqtT+4+ekAEorrAJe/yBCwDM55tAoGT+cDyiuE%0AD1K5zjODgNJ99QJimNetyJ2xsaLZ0ULKrBEdvOEwASYMMfk8vS0ojLju/dy0ngq+dSg3ohLhvZwB%0A2FTVoSNQBEKnQa+jA7FoVKL8UjSZ+gdFnLfApnE7/+A+0qgPTlh2BNVSYGGQ12iXw3M2rLlAnY5i%0Av8f6Fe2Ntr4VgmOs4lQf2dj/mO1qCaSFR1MkohzhOtMintDe3c28y4sZvRhgZnfFqx6brqzvHSWg%0AW6qv3HuIRKfCu1XF2rviJkyAbwhfrUmiQfrDbswweDKvaKCQbjaVkI60AoeSKN6ySOHfeWVxu17e%0AqlNeWAAMRdWIu4ld5tTKVmz21RTVB9kR4uWWnq3FNsSQdd57WkwIz4gJdkf7o4udCjskhuAAAAMA%0AAAMAAAMAAAMDIwAAA7BBmiNsQT/+tSqAAhDS/AA5m87E1wow3qa8mFI3V/+4phHz4YlX3TMj8M80%0ABxz0lLpC6GQbbWx5kC3JmFz5+fzLJfN+OaNVeSoiDZWg8338UgvYYy4G3Bx/a5Hi9xOeUSpiDY2a%0ARWHD/ygtlDlhCscZEg/5DjCcCEzOEuJUEAnAbgmMYHwnMqsCcfkxl+66sGOLtofPtpzxpRH9OQhM%0ASYfypi9eLCCwKKH6RirDh31Cb/FRdaI7XmFHBp5kwC/ATOX9Yq8EIx3k3KtsAkJMUB7TjVJ5A5ez%0ATzzxTivCYDJOeHt9JEy9oLWZQDn4mKNPzjyfGAQCEIumHXSsGP+r/yvI509qY/0p40zOZdXXznWy%0Ab9OPjYZhQZboYbBa4uGwndK8qrO+HYTdT0teumfeEKLjEVKnuCSsWR2vxynIcPdYSpO8zNXBGoH1%0AA4cuV39cMDX4bNf1Dop9EZqwFqQEqJhCZmee5D9EIKPmVMgS7r2HlLdaeTXwxZkOOE8x7HmYWtpY%0AIRiHlMemKxGF5+2YDkR/iapHjtpg1d00tdKikbAcfl1NQkv9yDqFqr6ZU49T37/MSC1JRWMQt8E2%0Au+JOrZeFf+cOI3Uep1FszzpG9voYxQX3PuOjQHVcJg0cIZHfSBcknP1YLqObHXnn0GJATQscUv3o%0ACptcHSATKXog9abhe5SWTFSZELPtXNYAQLvs9DI/6cguaOY9iN0Evco2YX+oZThZ/Qsz4Hkd4CDp%0A4WmJ4n6yA8F/xbEe+E04TdiT2DPw0xvVRpycfbDE9nNsXlfd4B6gBfwflJWsYqfDtObawLaMreAt%0AzXoCCuDEFzgzOvGu+lvAGIQF3tmY1Dj4OSWpAPgks7+ope9rbAQRLu9tkSQ53RmxQO1vvML0lSL5%0Afcgst9cuUhFRmoyotBwZV40SMGMnLuqdW5KWkr0OCysgzZwrsC5pjBikmpCpjdL5i+ohk3f2P3hb%0ASZ5m5SBilLjQVKMwKXuxvYigau4p0x+ZG+cKNjjfAeSDFYvtGh3kFx8vWBlBGRRmAZosP+8FVwvv%0A5GUNI7e39X6otIicHJ6P1+fv1QX+6N3Qd9kmlAdYZcq/zX4OlRLL+3KO3o42iJTuXFjZlbP4Yzlp%0AcRluE40LyOE8YsvXCXX84n6mHTzUsdxYlnPPj87zeRUk3ZRT9eJAJI0/0XL2sFP+ebYCD20Du0Jh%0A8OjzqYBB643Z7Kqyt18KaMoDQt4knqVMDBTKGH6fTzP0sHgXOOQw7thoVWEx8AAAAK5BnkF4gh8A%0AAp/z7NJBTmt8dS4OeAAQnlELJumIuwLg+zQGIhwmwupNLqlpwfpZyGBs07X6l3jH/qkT3/TqPDcu%0APTRr/6FyDhUFTdFesrIc9XQdRrTa8kVRj4cj8ZYvkZltUsEHthycCqrRkEMFSY+KRin5BvJYMx6W%0AhqmFEToHMxMqbwm39u1MazQaLs3hnGd/8pBwBWY05UOPcRRbKKeHqgKdrvhAPGDSDFQ64Y8AAACG%0AAZ5iakP/AAAOsxetVvkaACH63BoXSuJuOl4Y3Ubxzt6vT9KO8Zug4uitB58XHvbb8NDF2jbVy/Wy%0AUmea7IuskwWp+JZM53YTbFXuyOl1wYao27WoGcVxZO9RXaCDkt/jjzDekLOqFXrZljEacXEGsyZb%0A57Eq17YS/PahUHzVEaoGKYeQklYAAAMMQZpmSahBaJlMCCn//taMsAABbgPQ4AQRKfgUgRLGwXvy%0An1oaCbyQ63ACvRAdm64Q8qgjne97t5/XFDyzrJgDPUlc564u+/g2KnzavtTZKvcbi3tZGdAnLSsc%0AbPwhv/usy5z3dYZxnVA+RWVNWKLBGUXLJoTYe67L8AtMgo85nf+MHx8DqpIlI4aJGWyPgVtVDCn/%0AL1yx//wAkwxrqGraIP3du5dF6vpMaazIFtkI/b3H6/l4DWi4QDWq0bPRxCSCKip0MVfSBHFF4veE%0AhvNAhFXxpXpuo5N3MVcEc/cXHj8EWry/E53RUsfG6uYtJJeIsNgvkfca3NiIbAMQ5FEOLUsD/AC5%0AdVnDOrbhH+UbpR7JCdmZrYxpLI0GB2Hj4y+WGZlpwMjWu6Ntn5TskcQsct8wNY0JYCR1IdFaUuXh%0Al7OiAv7zW8tUA8oSjMPshNkgSbrJRa/j/GAzcTJ9S5RA3bs67Gdy7Wuls3JSFt686Xrp5Ot6X8CB%0ALWFczRmn0IiwfwLdeAUmerRPqdT7cuYnDIFY/biLTPxPdbYAACJ/5Ijv3DOB9QLfJOwwxgiu1QIg%0AhCvq6pLvVgQqbOTs9KGI79XAc46P//WElCmNnKfiK9b6XuFvlJ83g66Y+MH1fa2lQJ1qUDbP5TYb%0AiGfAxHInNqQKPlebCyblHshm4Ef7AjLvIHH7cthljCDQaGBSgk79lb/Y9j00V9cpoSfAYDwX7rXU%0AdtmfWH8XgVpselgYnMP1QWZVnaWjiGTmiRFB7fsc+sSMw6QZgIUHaUtlQOey8NMEfV0gY51/FKax%0AobYjsShQsIKfWJiJ50wos10yUzL1tOYFwu4YHUtgN/Ep98CnP2CtxoRP+KF5v89D65GLBIvOqsB7%0AOa0x/SpGEXYWSdAKhyKCYr8qZa3chnN1vvEJP+xaAZV5JxJrt+68EMDmh4EoLsnrqNXfIIc1aq8e%0ARRxWUMJxkrOyXVV7OKUalaTQ7m+wLfYniua3qbHaHn/gDzUpaqrfnE0VsVhonO4ZnHKiFZmrnKWA%0AeiONIAk5AAAAjUGehEURLBD/AAAG5oW9O9Hgh4iAA2lHXqkgq7V2VQuEz1lHV8yRlPclGDz3cHXx%0AN5r19d5BvNl+2MW0tM3FxO0sAitI044zHv5OyY6Kj7PaUAagcoaqMYNvj7sN0KrsITXHpylNKzh/%0AFCUmC99ni9A1CYJKGR/XQo886dKqzFjRfHU/8l5/RUGEznjHgQAAAF4BnqVqQ/8AAA7XYrC4N1tA%0ABtIvZKQhIp+rl51h17Q39yYWAP9o6M+FhnjPK+QMPJVWfF+ebqCyWiSKvl7xEIDTZMFjLPYK6y9g%0AxzFG89tF19RCNX0GnbN0/7w0OAfNAAADRkGaqkmoQWyZTAgn//61KoAABXfs5YHOAHRBg//n/OS9%0AwkgMmm45tLnOWRmYoyl1P77etDelH/hXzKdz8HwiecOoEeUS+so0yp+91Y0GKNXPZhQwD7UPgB9a%0ACtK96L12kBJ37ZXX+3zxbHjsvqx1GEWVj/2kymgBD4yIh6zfMqzGDRVPUXw1NUfvB5h+WO46TWtD%0ABx3+S14E7BQcH5I9u8qvki54iQ6DbtB8dSOpot+zjpGeQQ8rT2l0GAq5XrbcL0oRVZbydI2N5f0W%0ArwjBKuAwuq0cJ0xliLiZFAvHGM+N2OIb+oK2d6+73IIFAL1rbeppkSu8+yjuWf8caAHV+dSt+W6K%0Aed3LjUIRrg5xtSiTUthqT73+XmpKORqE/eRjiNzzPAafNPqFfJ8zxJXVPMbTex8DKhPYYEC4Iqk8%0AYBj1EynGREGD8p3ELk4+ZxmL5MVYX9nnOJysN1d+VixYloe5JKm8oSo668uSgze5jmD2/71ChmYf%0AeahMWUkk8aVKe8pRcJTqpo/uhF1Bz2AhI/JpJbBV/JwiMxA96kO12qRcJPvTo7vTLp//8gW3pfH3%0A8vbEmOJIb7NGqH5QCaWO5yhrVS4kI95AdkxxCOGw+sy1kzu6um/nmTQWPSL5eTPOYpXLhbvGzqLd%0AyVSIVNJrOOdGUVutn1oBNblK8R/jbdySaSC+ns+wqp4N3ekl/K7wzgA5+0kxGQRSptqjR6Ho0E60%0A6iy9lvBjfXymgmIXn5fXjuJJmA7N6BAUqoKISJIHD3v7MjZSqziEjKSN9ZLjLV+pSqCLawwTCyAH%0A6HHltXW3WFW/srFPhI05mgLwlvazPHUgUTmRcJCnnKvkengYyqJ25RH4+kVySpPLM+4q1OpJbMZF%0AcVBVu0Ggal6/GElEGV5oP0jAoxB8dmWSmfEs2AdDqBzmsCSQ2gW0n8JSYsqCZ3G9sFDB/xwvVey9%0AuEktV8URsgiyyll5yS2Qcuq/xGi3t9P/zJ/0MovqYH8FbRBOR5kD3mVMCeon4UOgFmDjW5/Z8k79%0A4v2rxUM2Xw+HVjMM87xrYnOmYVJqAbvK0PLibXOvwfi/6ICChjSyAoilZC1wJYlqp1O6+OYB/txm%0AlXUmCedAIeEAAACgQZ7IRRUsEP8AAAa+hVpDuUAAG0bAP2aBLUuMH+BBQk4B//Cv9VV4+JrlamAD%0A+Gb7gc9WEQ2kn+BdYhJCVQBFiprEOfAnAoRCTCmV7PFtraZBI1Tc7oL3x9jC4H4zcuIh3wW16/Sf%0AFWvfvgKq4PbOaG1MJrdwQmwbknkr6rYwt/DC1qoVYX5vuXizE5y4tXhBPgMDGiTwDi7kS+0cOAEU%0A0AAAAE0Bnud0Q/8AAA7Wt5y3UAEP1lWe+AZ7JPUstrJxSUg5bthybrXgpeIh5bQ5AMX1OwURn/Bf%0ATaiSjm8k/gwWpzJRx3CjPy3/Ph+0RyBvQAAAADgBnulqQ/8AAA5/ZPbHsaNH05JYpDJrQASkzi4j%0AlGTVdQoFI6ZdR6udDRrt1K5kwQwHnamQjoIBZQAAA1BBmu5JqEFsmUwIJ//+tSqAAAVRIhx4AOGc%0AJK+zcSVnn0VYJU+/ZM6pEMiEuPXZbc1p5hF5Vm20EAnDcq9S22HAO7H2Mw9TV4WOyvv6Uog05X4i%0ArRnn/BS7IkWFf9h8b/TQIhpoYC/5+iYo4bTzzmG/2NXYoQMSnPvCjf8INVzeC48Xuka1lTgl/6nh%0Af6oczFMRFHbCo0MpaQBVpeTokVO1+pnWA+B051X51rngTerO0xP/O78JT5oRq1EgJGgt3nteA9Mt%0Ari8Idq5cFUWd6hezIUgKSq4Bk2zZofVujYLbh3pp3r96+00nURxIRBXSnEKx0z0LkbngZMw4SWWz%0AJaPbidEW0jo/s6OR5UObn6+7obaIAVOnk9tHvFCp5TdJp+zUp3X9H1J1c0To9Gm777hMgwQf1lyk%0AgQie/z5pSijbUj87BYDjNa2+nXavdKs8luJRleM7Q98Mp8tY1DjIYBQWXxilYuSmekBsHpCdY5K1%0ADace+1w9Ow49MntsQ2rhZOC9fYT5iUqrUbYhPJlmWrV037N+EmPh4xfV5sc2EMcvc7KRQMbegXf+%0A5GH2a8he8x0/BdhOmsVm+U6NaE0Ce8eP0TFLt621pjQ5/uiGqJp9YmX4LvXMqkxV/KCO7+k7gNh1%0AfFhGmHb9ljoxhAbjSiDaVf3mQbtqjpsLZpgSEjw5Acz8wvtH9/KZ5U0hj6/6m8ITfS92VFKGefla%0A/Nxdhukjxq6Iopr0Vki/4cmbO8ZEMwN8b5YEza2R0s1fQTS5JeOKomoJHNb4cD6xuXIAAiQKgTNf%0AvBlzkzPjX2U/OiI4aEbmKer76e9e562qQVhJojOcoUTzwH5BivEG734mU+uEhiea2LiCbVrmnRcX%0AVPZmrHmkV3AoXRutkTAJlyTM4mMEejNBZ0AknqQ6giXpYtocNj2tyKeeXUh70TvDPQUqHQiGUy+N%0AvDawo0AVWdXZSxSgQv43fx5wbd3bzNcY5bA6CunwiWQs4zRsLAVhyNWIaMJuvrMZbon0en8LADPd%0ADHCS1RH6Anws+4NQmjKGCoNEmCfaNOA8+ya2pgmByt06VyEOzX9L2XNuxy4cOBxrC7YOPSx6iA3c%0ASIT9E6Gn+dbrc//S8672DnhfQkYcmcAD/AAAAGNBnwxFFSwQ/wAABpaIU2xbdh/YuqSIp6A/SxQv%0Ac6iXE7yYao4W3Lm00ALk/zsx31hDhlMC1ytmihjV6l3zLmz+maPgG2mvvp9++tUQCVnOkLQJTHs+%0AOXq2sZobiiBkgp7IBDwAAAA0AZ8rdEP/AAAOfX2g4dnCG1aFsxoxSwotolApmEok1TVrf7/J4gsj%0Adg5WH8Yk6UhvC7YB9wAAAC4Bny1qQ/8AAA0vjmooUL892T5HL5p47nKLRovLizN4kpicllunibkR%0ADQicQEXBAAAClUGbMUmoQWyZTAgn//61KoAABMEsCa7BRToAEYuO8FdOXpq4Yxlmq/G0vRq2DDd/%0AwPyRvjDr39Pbnw5BYKeASiX1lNMwkmmvDwJKVTWxC9Atmgmxdhejzj3yHOQwejssiz4U90gcunuZ%0AfkbUeAqFAXvKI0FZJwPpvonZfXqZuycxd4z6wq2GzUkE1nF3pjE7e61be2yc7xu+XzYvcKW1Hz2E%0AYwR2ohykB6Tx66DblQXaIIjuCV+lRBMrMebA2aNofOOx7yEAM4gdCUfz6ImrzLOqI5RSJcOyIQN8%0AaeK1RbTcaoCFS4IeACVM7JGiFsTpTyKjipbkQPP2ntvNjpbnAh5kroNdd4aLWQO1622E6V45xgy7%0AK86KPWueFzJ+NLFNG8cjN4zy0IJ4o2g8cpUbOO1QCwZARpUbJr+euLEWpyfq23+1Ku/trsbxHzav%0AuO2eURVMZtlkUN1m//50WS5Ov4iQiI/dQQLE7LwTqOmQxddeR56AakW20P7BgliBDGGfbkSCnDbZ%0Anw72EbZqI/zYkvustp1t1GGM8ciNSmrDKk2v5Q4fzQ3LnpkLfR5VTLlDCszjFhXMlCgDwXsdowPA%0AePtmYFWWo5NsEJLbepDNDgEfxiuAE76aOyfCSK/ST/O/pNaAshUkWXal6q+kyy1a/qtmQO6TuRQZ%0ACDgLjWr47kkPj6wqoYKBDFMrlE8yHB5QKgolfjW/xegcwBtNHgRrrcVkgOYmFdXBAJyge31Wqfxy%0Ayhha0wugptAsgawx47tyo0XAU8Ab9P2foL1b9cg8J61fwKK+h1RA/UAnK1xIzH/0oPHRev+ccdE5%0Acxy6lEFxCeFMcVizK1OHcuFTzVOsqsZfCRMCsBWj7NXhii68+15ufZeuAvMAAAA8QZ9PRRUsEP8A%0AAAX2h00LrvRWE0o+x2iFC4cxZDGl0W6TayPagTmHKykanjez4k5NHa4J7ofLXgEJoDegAAAAIwGf%0AcGpD/wAACxI/qghiU/fNsUlgAf9TAxLJzmvfg+tzdXf4AAACe0GbdEmoQWyZTAgn//61KoAAG+6v%0AKCCB3ZjgeNz0Vlq55sZx2CUPLDKfZmszDRNt5+kV22LdQcE+Eckv3wJ2Pbb+E3WvkGkUldMZ2ecV%0AFOOrF55/o5UAg/YSyJqGDfnEH0B5cRfIzVwiP1wcHNP+W5Nu4x19uX7lv/Svzng5u9FqfWYtelQb%0Ayfp/aKpYtl00bxf41Kp2dvywOiem4U3JH7qgBuNW9jUjND7g+jWzlhUnVnV7EcinVeo/5Wx8lc+C%0AyGbsbN2Muhp1a/ImgIPYAD0Syrae7Rus4sEXd/J1GGznLtvQg2b8unHw5Su2yaM9MOyqQNEfYABq%0AUp/In6KevURS4mtAgC9FiaRtxoVCWD2sGE89JoA9dsqzwQ7vaSHFxFS6P+62om4rpjbOqd79pbLS%0AOmg8M160NYAbUZVas7JsgGy8n8HVzhxhh0rZG8CVAf8bs/IsUf0f/haN/Hx/hqKw5rnoG1rmh5cH%0AuXW34L79wV/UgRASLAtIzQyhmFg75qJpQiTRVR6UlwlmUwcrVZ6Ikmf4SIfiuhSmIktqPtGmSI6G%0AewTiqmH1kpETWj/VhJDU1Z0suRu/33/GkT8+VbHz88x31iMJrreQYC+MnGscL+c4cWsZTCPTwfHR%0ALoIlazOiclsqdNQA38tqrg7slhKf0QvCZaYaVZLzWZaBzjKCK0zDKvk8DOYws4P1Bl3cT0lKslPj%0Aah+FXm4A4DryHX4gQ47YwbomzGjZfSZEPv6yqAyuwrq9NjXMUUz+CCs5jwg9bSih1aZha/3SBsHl%0A8l2j4GZ7eDwTs8ZfIGoTCE6Zy32JoAqWhtQlxsDUo3dfH1u7yRDalKISEIGLAAAAWUGfkkUVLBD/%0AAAAE9+hTbrdT9r5Uo2TU/nnam2ECs5ABuKu6f0AJeLIB9p3Np6IfFh/zq0ItaIYv3YIYe4w4vfmP%0AtxWKX0v1yi/zbI3Lj3zwtQxmy3+vckPAAAAAKwGfs2pD/wAAAwAAAwAtaPmoCdv2QIvKQvR+btq8%0A+AchAAiD1VCa9az4KmAAAAMjQZu4SahBbJlMCCf//rUqgABdyoaVXhUkK1e8/XHqdJOf79fQCKt/%0A/NukA23+VL4FCP/2YOttDSPm+j0TFpEo8X6jgDqGYFHqef//VAH/gYUunwTrcin3OA/T27BnemW3%0AQclfwLjBQK55D2JS85S95ranA9GNzuDsJ8BSqAVUcnU1vMt+ePfoEG7d+iR81ZBJ7T6cdMhaVV4p%0A5zqvNEfcHPmJbbqO2QbuWWXqN54Wq+7oNGYWBqGFkXTl79lYBDL73dhX8yhTB7oxP9QlAYtoc3QF%0AFzYdWz0YZuCC0V0SyMesngb1RJlaoSajrfYBR2wpKANmVgF8u3SRrCD9II1X7mNfd8u3EIYZ2BMq%0A7vqDZ6bUBSzqLH0IsdjDM8q6XQondswZRvbDmFbh1OVrBeL8sQaHyxe3dzksaOAZ5qJFIav9+510%0AzsXHrrRVZUdv5hFAFxu0L6nejLuGSCkSh0mUWBUPvHHnc/XiR/OLZPkUUIgF4erKOn3jVpH/ReRn%0AIwjoJ4vIJtoGw3gitKwseLCMBamwZ5XaazpdQnJ9fgqbXs4avgiYWWazTrHTZKg5tV+EFyi+DWju%0Abldih46RODM7apQHnNm4cntq0Vry2DIj1rG6zHwXKNIbC1miLcBYGv9fpuNs4rj3+8fQXhSI7IIu%0AE7kKlA2HZzab78+sIeLNo88aAnvNx4yKsQrc7CDecbipoA6JwuCVi5z9rsjL/7YmmEgV8KzrdPPS%0A3zBeTDPS6NBPYOPJ5qq5cX0uJtnRnUJiZiEKHJvKNXmgFdn4RPwguqa+B2rSOE0LzKNtzReadBKV%0AF6sFHZD+vmUc/BoAQbIHRRI8nXyT/n11Be1zTTdhzExu3yKD23kOSxDSX94xeLgMG7ECsg/+TXaF%0AUvx6u9iutK+qH1gEVQBW3TNMMVMHLyAr8y0s5zIiEZd1CpYL+pe6Cm119KVYwqZDLqxAiUBaxTOP%0A8609GLBb8LbLEL75iGyVvJNzMu/2BRhZeSkGub5kMgKQqZW4nvwO43pRnCjJExdBfKqOK0cD2AqU%0A3bpuBjSZC/Bz09/KBqLakl3jGaNEiykAAABDQZ/WRRUsEP8AAC+39Y0QIJSf0ltzySwHUMcqHJtW%0AedXao7gAAOxZXESsPvOxM85rLJrMAATVtW8LpaJ6YR6CCjQKCAAAACgBn/V0Q/8AAFZUrKmTq59W%0ABszEQgAC5e9g7iI33cVE4syXX3rzDAwJAAAARAGf92pD/wAAaXxzUBQ4kYBJjSd5WHHEADsrzn+M%0ARVGw2rEFAYrAH2JE8UWXIfRZzOVxtPfzcKjSqNVS7XwDweyIbA1JAAACu0Gb+0moQWyZTAgn//61%0AKoAATBwQKKXXeQnTV6bYL29Z//DOr4YQn5G/3dUMNdHAbrvorBzj0+GInQ+Qsr+ytPmIg+olaGSh%0AwBprEh/zfDewC6IyhS5+wIyep4rRfHAjIxN1+Rjj3UAnKTfR7LdMbAgqH6M/8PO1wbMbU16HOam2%0AMFj8SXVMFKAWnSG8Z4+49E10B939Kf/ICrzdpPy/tyLaY5U0JvUZ+A+rNH+NEGvLFbzafe70MGZ4%0ATyYnbYqSpbXocEoHlX0rXKwHqtlC0pSO+YROvoqh8Xq/7ir6R62okt+WPYnbiaR/gEVEBtg5sL2w%0AstLuAn3DX6+RlWBz4kvh6Tg8TyDwQcFao/kRCTuOMTFmzyjJEw9XUvoisuCvWAb+qpdo+oAn/mho%0AJJn8n2PtqrSHxht3oX4rDXUQqSUQJERMFDlv6vK+1He+VeU99XxuLR21uQeSvoORiQTWNtN695vu%0Ay/TCMkFvSPZsenclHAnQwk7mH1hRn5j7S/1vtYZXYx7byapRbezxZn7S5K2nzuTbcdln2QJmo1IX%0A5KGb3itkFb9q+B6fR8fX1fvVqA8tyPMTrJhZj32lQCbTXIrNVzSQcvliAN8NV097nCorN8MZiy89%0A23BnQeDijP4eUiBp8ZTMJR9FhOLCZbPsO10JMU2txrtwf8Fu7h/sqgg3HVsQWubLwWz1tqcnLUHY%0AH+pqhyK3EjqVbzRaMkeXA3HbeGcxf5+FaqloEqKLyq8hIqg9p0Bmj7+inyHWS2s57/5OtpXONg3g%0Aq/LdOdDknUm6LUhD+40oP1rcKWGvN6EbrlTRVL1T8RyayrbOKIdYQMFb/hK6BZk4PjvygRVw8Bdw%0AHZ4ym42MtS4XE/LuKlE4CXgAUTCwNmG0RdKGNd0NySMNENp/wnhdmjA5eg2pMe+gqygTXu5wXmgO%0AmAAAAENBnhlFFSwQ/wAAJah2pygPHIDG/P6aaz9QS6TZZee8Bx85ZhPfQ+h1TqnPDJUpISHnXJIj%0ABbj07QGAAhbA07Fd+8pJAAAAJwGeOmpD/wAAD99kmnUKzZkBkV6qQJuWImZ/BELzisGAwfCLL+0E%0AhAAAATFBmjxJqEFsmUwIJ//+tSqAAAXb4Syj5TozKtMVWrLZ84JdPmUonzZTGvvvKumpV1MdPJq1%0AjLxdT3o9y56NIIt6kAA/7XcztCaWRwGLxevgUi4XV1wz4wBUi5KRP/IW6LT1YnSS6K9kPP2uO+VN%0AtnEWzbJxkqDKdw//OPBPbEpxqDiUqYpXret2A7L/AkdIMzCO7XQyf9da0GJOgJRl0WkJJJ9KsUWP%0A4n0GVT96uaSdneKl90Z4b5weF5T9HGdzLx85he6hkYQprZQz89OYiJk1Xt6qKyEr4z0JAvQO0Wyy%0A2AgmQ3+VWD2RWJfApPAM8KDg47rJFkvbLTsM3/E/7catCcyQ3iT7gYPIKnE5K0BmuSWyGXwW+mYQ%0ABYOepHS8t9uq898eKLPEIWM6ewWCIGjF3QAAAsVBmkBJ4QpSZTAgn//+tSqAAjPxkEANYixjaFFr%0AdWIoXm3h3d7Tz6P9ExO+TpsLcbCS0I/v//nYABLhbT0MSHIfLJib6ngbNEK5XG4nEEHW1DmWf+Ng%0AfM/NQrgqqAEYv722BKl0/ItoeWjFZUL0nHauRmfkB8WIr4dgH2oXfug62nyeqitYnWm4izsKL+yK%0Acgo/Hw8J3cWqM8vpwqi5g/87uK7W39WYT8B5E+E12e2fpwWTWf7ltoewh7MbGa5dLLmGkCc6aLRM%0A7Z4rFQSufc7zGR70DqaYAfNSJe7KjSdrVw4ZbeKa1jLC5J/gI3OS0mcEJUJV6F4YG50rYSBNDDGu%0A21rUoL1F5fnciXvwxjloM7wgf8re7PNXLZRaWQPQ1Iu/Tiudd7TZ7M+romeYW1DNDArR8KLjXWLe%0ACaSKZ18NVTpnrlARBCj8YUakN47OmyuhEwCvCr/rAFuzt+OfyqYA7xlCqQ7lUk4Vx/uybFoNajLb%0Aum/hRyCR39fc5tPzizTXfLL0n6lIks/0EUY2mpoINfChqwaux2Va5wTr7iy9fph5hQ7ASgbLsTrx%0AEC9Vhr8/SLlh9q2PpGBEa6zq5TbdlqoP38cY/GAA1pFgec2Jg09TPNqWty9AY6bakHQX7Y66L5dg%0AsC5O9/zcIlr1FTUUikIP00SPShCLQJw46x6KFf2eSWDAka47FKDxDmYjLpDfWiv4A+AsgAJ3oOUS%0AMvdJbbN6KtH4WwU+hNdw24yN744bwIp5ujf61jQaoGYfbG7aeJ01PQ0Js5svyNKqETyyQ40yevAh%0A8nQcLPscXRMQmCp7ekOHgBBfEQSyXpcbZoFU1iYOUIOyOJBy5k9zF4d8gLFWECACVzHiP143CjYU%0AzzO0b+ZorqMDMc7gu2rPkfzX1cHbONJ/WLvhhre4eH0MKdHQCxScHzN5YMdeCJMyx+XPDD/BAAAA%0ARUGefkU0TBD/AALEL1jRAgq2356Bw+wLOnjHyfO3HjEuk2FuAABy8uftgi13wAFjGH4LsH/VqnPB%0AIey37dyx/HAaoF2/wAAAACkBnp10Q/8AAA3N0m/AABSfV9eYfaINDiRXhi25IDx4n2F3t9nsSTLR%0AgAAAACgBnp9qQ/8ABh/HNQFKFHkoEIujjix7eGsG5rWrwAAAC5/FOGwboIOBAAADMEGahEmoQWiZ%0ATAgn//61KoACMxs9jg0uKAC6t0tkym1W37l2cGETEIRV/Zh/tJKgsoADtCRpBCKu7O00fwOnGR6P%0A/A4zUkEbu/jJXhzXR4FAbaYPicTVwI2hhZN+Or3sB7oSf8ZgRBvnoFveyQZsrajdg8CiRX7rD6oD%0A+S/kuzObBH/GFLnlZP+UglYzw0qmhI3RJrXi+LLeSA1e+XOLNwGI3WVF5/nx16f93kQIIjm28jSs%0AfZ5Qn/kQMGUUq+DMJsLKFarE9YelKChXfxwtU3qf1Yd95y1zG3zA9owvxK/woiFovtPeeY1yXdUY%0AXKlRdh42kWK0YW6+UkHMfunLJWC/x9CzdpKYcUr5Lr8zXSqSVF3saCsyHLBoXhK/o44uNn+hakUX%0AFBSht0UU52r7xh/UST0LvX3kCCfTTX5uDL39nLkpnv0P3vKb7hO3f3+KYbeAY8h3eqoE3hRFWOm2%0Ae5f77WonqiaZQSteW4fts7T/49eLOFu1aYrK7uUiPwE/PimoZ3TueQeeRzm6QsejLf3SVQpwQMp7%0Aki6uCvr82x2xfGXTLq8yIQ8/phRSdv8zzZi9si3Re5CejdhCSOzVqBFnzCkNKXoyz3MDXGReRHKt%0AcS7ixaapdRANDQ8LvQCLA6p5QFlCwxq7l9D1jWXx/5h5TM77lUdzPYFNbIdT7/eRxhTJZF5JcrN4%0Amq4evoqMUQuitRA5qECbUm6UzZtdaAo1wOj9tv3nqFWAX7MqdRVn5cbsEBO49NrlTJ3SBvS01Bts%0Av1roB5lbqilyMM/Ww/+yvbQcuTZjB/18AcEZuAk1yfBIDYRyRWME5+VzWQ9+PxpxejU0qlyQnV4d%0AEyBJpbuhbP5fL86HMw0J3d8Uhbl8Uf4DmIhdtFLOYIjJ/49sYpOq9LzudXI+8DJGfP5U0IHz3ol0%0Axn27tRnqalQYHgsOpCVSm9CNz/7vXW9LLt/PazY8uqWt3SUP+UWI+87V79oHyv2DFX45uxZv1PWZ%0Av6iVKW6Lu014nKRLQT01xmv5c/SW3i580ShH/gjskLSPm0VgO8s6UC/1tuu7Jg5bSBrW2BkEz+tw%0AdcGEpd8eXzNz4AAAADlBnqJFESwQ/wACn/Psqg9RakAOfQ9qiBJQAZaQN2+qB4Hm13TZ0qJ5w5ga%0A2oBm3hcW2khH3bdg2YEAAAAnAZ7BdEP/AAXQW/onUDrrEXhbVNnSpH6f+4bH/0FvEJkDizmgx85o%0AAAAAJAGew2pD/wAAS2DW5nHb2ewJYzqBPBunyjsPFbFsMVQGYW7m9QAAAmZBmshJqEFsmUwIJf/+%0AtSqAABn6w0xZvuvKeA98cg83SgCox2EtuRKXVm1s0tpbrROa1Xq8++kjoIzl47f5kFbQ4wH/efT4%0AVn6++ZT6D9BpW4/v+rVh/zAxgTBOg+fzgnbm8w7u5eveBWbAN3T0GCYoAG/BzFKMFrGv/8DUOB8Q%0AEaupziE8/lU5ZKp4gWsbzTDZfeahzgj83gBfS3T8Lp2UeYuzB7UfVe/gT74+gbBgOHet5Z0nGDSW%0ATGG8gAzELU8G6tS3PzV2rX+xKNv7srXN2emZ7CcE9aFzESYZa3rFFqcjANE+9Se9a8f3t7s/svBF%0A/nbtasElQBN3fH1jSquyc8RfeCFsfPt1yi3A9ttKZvg6jZNG5mU58r+SdHWa2WnZB5ssQ0q/HRz4%0ALrY7e/qMes+uhY+L+UbcxYsvb/rDFnqexhJThRPmvBpOYjnM7ZqMvyw8Ff4AWA6DbYc3oIIKepOX%0A27uxVy54rYSjyMFZZBDlvsdOoV9n0//8MHKsRkjWejx1O8Hv+mCihL3i48IlgZJSUycjAwUIBOWA%0AWa/RsFnjtzj60rdOi+X1XEa7T8K8nhpwnqVCyRFBqzHAERqCiIh5chQ1hBl+JMNdbfF9qM1Zi4+M%0AtK7bVb0Np8qlk60uY6H8H/+c1T5apLUk4KYQKMZcE23wqjNpadRsFBqIWUvniDtvPdk8Q7ClyO1w%0A4TwAmqDZeTXmuuo9onVv6lrEHDt2efhRESmwUIlgwuvbgriCZw0BcAIBy6ObEvA2cnTtnv1CZUVm%0Ajj0r8ltzC/coUtRrrx85uJbp0MYrRmufwHrew7vCgwAAAIhBnuZFFSwQ/wAABkdU3rzyiROYsZUL%0AZQACWX9Gut/7MjqtPFcWcx2AaT+YakgHa/Msvw487gEduYadwr18elXlBzuMIkTAcc8pgutk6/cd%0AV3B/+v2XWNCK1Ng8J2iMaIRiZyBYcO+BDE+8x/akEyRl6MAe1q5cuKB3RkEkcUKddgbhZ8oyqIm5%0AAAAAcQGfBXRD/wAADc3S+3FiCFk0aE2YWWAABA2WgJ7/5uKm2iwPMFAHD+EyBgSqvMw6diF5QOIo%0A+WZuJfTUMGILw/FIabwd5eoUBGr4f+/aVs3w2P+xdj3O27J19NN2J2iUXjuy8F/v1Yl/ueJE3TzW%0AUA+ZAAAAKAGfB2pD/wAADc+O9cI6mcr2CxS+If8W5bUdOUCljftFmGQBVpJUa+AAAAHKQZsLSahB%0AbJlMCCX//rUqgAAZ+sNMYbH7AANqtY3/7+AMBJ6LE0ciJjOTBIbHeBYicnELb19jGAcQQnjqDYc2%0A9Lh7z/828irg4A+73yqDRvfo8FYWvYBGVU50/HWwOW/l/Yl7/zhGHRwzERVsxW3W3w6c8KYLe8iO%0AdggM5otsjz6r/HQKm2oy2MMWGaD/pok3Tn0Cdq+bXvlNmazCWixJXrVSabRmknxsN0CRblofoIJn%0At8XX9Ww1RwDDMo2961wrjDfbQxySdFtL+/RscuJDgM0FGKBrng7L7x7fvolRAT7I+A5Gd31tHAR1%0AK18raSBdj1oeOh/3qlhlsQzmWv05DhmrR3jO1mSnEy/h8EKyqJ/Gctq6En8iGNPaKL6ZcOL9OgoA%0A4LjLJQh4V3nYiAf2G2sHh33URh+gwOWdf8fy6E6i1DK5/gtINdb8hFYw2InBQkV1Lk6HwFkkdlyN%0AL2hYYtzq/79kKcsU+gZX+3yxPQ0A22ampjI0VcUmJZe1NceDb5MhvvAkeCHGhz41KKp8WQWAjRR7%0A6UwiwOQCa3kc2g89xQWCj6GvjErog2A2M1hYB6iL1xpEUOBFqgv6SKZLC+nHt5RYT70HAz4AAAA1%0AQZ8pRRUsEP8AAAZHVOR9nnshVrkN7ZNKgVSextIetbdtU2xdeaF+ZRNwUq/ZbunCV1nksoEAAAAs%0AAZ9KakP/AAANz4+Znp6AB2ZwVzmYPUoMMOMBB/iqgINvANlL/rKgvn2XA6YAAAGBQZtOSahBbJlM%0ACH///qmWAADKkUKF4vK9AAvmsvl0OYRQN/TnwVdsYdfHtEdT5yHwZk8DobLiC66MSmvR64nzUpOH%0ASQ+31Rqchb7mYfnXQOylGxyo9sCc7pzzRdo1eHrvGJPrPxq6QIXu25cOOjY9npKJ4D5yN6/v9tRq%0A1wbLAlhoO26SoiVFml6b2Qea5rqXbPxRW/KQN8txhppFGH4Ekjq820GbixcFCavERl3tnGz6nxpd%0A5OIWj4n8p9gM44MDQpJINHz1BjKqMOV88pmdD2uPJ98Nrsn7shVMs66pQ6vF9Q6tggrZyjBA1zZD%0AxGx55/jZgm2GRAAQP/Sb2Im2JHS5EoC9VbQjfY2oUEk4kOqjcaj39/JE9D2TMgCiz98BJxN+pQc8%0AN/Xi92ACvbMu20izmI5ORAlNi/sQLGUNIAwxMSniX71IKtAAjWjJrDyTTE9wsFGyVYr+G62QsHI5%0AP4ARkVLA3D8RB20t3fUuwga6v28/TDO9VkckCZyomfhJswAAAE1Bn2xFFSwQ/wAABkdU5k2cNj34%0AemGwFT69uWfqS2juBcvSl33MAC+U93/mMPGrndZMNzOD1OfFsalzhv9JFiC2RHo90np3dITPkur5%0AOQAAAC8Bn41qQ/8AAA3Pj6oIYlAOI+EWMOj/cd2NfT51phVzOigUGAFjgQ5iwUyl3NGzsQAABS9t%0Ab292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAkuAABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAA%0AAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAE%0AWXRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAEAAAAAAAAkuAAAAAAAAAAAAAAAAAAAAAAAAQAA%0AAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAACQAAAAkAAAAAAACRlZHRzAAAAHGVsc3QA%0AAAAAAAAAAQAAJLgAABAAAAEAAAAAA9FtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAACgAAAF4AFXE%0AAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAN8bWluZgAA%0AABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAD%0APHN0YmwAAAC4c3RzZAAAAAAAAAABAAAAqGF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAACQAJA%0AAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAA2YXZj%0AQwFkABb/4QAZZ2QAFqzZQJASaEAAAAMAQAAAAwKDxYtlgAEABmjr48siwP34+AAAAAAcdXVpZGto%0AQPJfJE/FujmlG88DI/MAAAAAAAAAGHN0dHMAAAAAAAAAAQAAAC8AAAgAAAAAFHN0c3MAAAAAAAAA%0AAQAAAAEAAAFQY3R0cwAAAAAAAAAoAAAAAQAAEAAAAAABAAAgAAAAAAIAAAgAAAAAAQAAIAAAAAAC%0AAAAIAAAAAAEAACgAAAAAAQAAEAAAAAABAAAAAAAAAAEAAAgAAAAAAQAAKAAAAAABAAAQAAAAAAEA%0AAAAAAAAAAQAACAAAAAABAAAgAAAAAAIAAAgAAAAAAQAAIAAAAAACAAAIAAAAAAEAACgAAAAAAQAA%0AEAAAAAABAAAAAAAAAAEAAAgAAAAAAQAAIAAAAAACAAAIAAAAAAEAABAAAAAAAQAAKAAAAAABAAAQ%0AAAAAAAEAAAAAAAAAAQAACAAAAAABAAAoAAAAAAEAABAAAAAAAQAAAAAAAAABAAAIAAAAAAEAACgA%0AAAAAAQAAEAAAAAABAAAAAAAAAAEAAAgAAAAAAQAAIAAAAAACAAAIAAAAAAEAACAAAAAAAgAACAAA%0AAAAcc3RzYwAAAAAAAAABAAAAAQAAAC8AAAABAAAA0HN0c3oAAAAAAAAAAAAAAC8AABWsAAADtAAA%0AALIAAACKAAADEAAAAJEAAABiAAADSgAAAKQAAABRAAAAPAAAA1QAAABnAAAAOAAAADIAAAKZAAAA%0AQAAAACcAAAJ/AAAAXQAAAC8AAAMnAAAARwAAACwAAABIAAACvwAAAEcAAAArAAABNQAAAskAAABJ%0AAAAALQAAACwAAAM0AAAAPQAAACsAAAAoAAACagAAAIwAAAB1AAAALAAAAc4AAAA5AAAAMAAAAYUA%0AAABRAAAAMwAAABRzdGNvAAAAAAAAAAEAAAAwAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAA%0AAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExh%0AdmY1OC40NS4xMDA="&gt;
Your browser does not support the video tag. &lt;/source&gt;&lt;/video&gt;
&lt;/center&gt;
&lt;p&gt;With a bit of extra bookeeping, we can also watch the posterior distribution used for Thompson sampling evolve after each turn.&lt;/p&gt;
&lt;div class="sourceCode" id="cb158"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb158-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;game &lt;span class="op"&gt;=&lt;/span&gt; Battleship(ships[&lt;span class="dv"&gt;0&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb158-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;strat &lt;span class="op"&gt;=&lt;/span&gt; ThompsonStrategy(all_ships, rng&lt;span class="op"&gt;=&lt;/span&gt;rng)&lt;/span&gt;
&lt;span id="cb158-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb158-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;posts &lt;span class="op"&gt;=&lt;/span&gt; []&lt;/span&gt;
&lt;span id="cb158-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb158-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; tqdm(total&lt;span class="op"&gt;=&lt;/span&gt;SHIP_SIZES.&lt;span class="bu"&gt;sum&lt;/span&gt;()) &lt;span class="im"&gt;as&lt;/span&gt; pbar:&lt;/span&gt;
&lt;span id="cb158-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;while&lt;/span&gt; &lt;span class="kw"&gt;not&lt;/span&gt; game.is_solved:&lt;/span&gt;
&lt;span id="cb158-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        post &lt;span class="op"&gt;=&lt;/span&gt; strat.sample_post(game.revealed, n&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1_000&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb158-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        i, j &lt;span class="op"&gt;=&lt;/span&gt; argmax_2d(np.ma.masked_array(&lt;/span&gt;
&lt;span id="cb158-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            post, mask&lt;span class="op"&gt;=~&lt;/span&gt;game.revealed.mask&lt;/span&gt;
&lt;span id="cb158-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ))&lt;/span&gt;
&lt;span id="cb158-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb158-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        hit_or_miss, sunk &lt;span class="op"&gt;=&lt;/span&gt; game.guess(i, j)&lt;/span&gt;
&lt;span id="cb158-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        strat.reveal(i, j, hit_or_miss, sunk)&lt;/span&gt;
&lt;span id="cb158-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb158-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        posts.append(post)&lt;/span&gt;
&lt;span id="cb158-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb158-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;if&lt;/span&gt; hit_or_miss &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb158-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb158-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            pbar.update()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;100%|██████████| 17/17 [00:09&amp;lt;00:00, 1.83it/s]&lt;/p&gt;
&lt;div class="sourceCode" id="cb159"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb159-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb159-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%%&lt;/span&gt;capture&lt;/span&gt;
&lt;span id="cb159-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb159-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ani &lt;span class="op"&gt;=&lt;/span&gt; animate_boards(posts, cbar&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb160"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb160-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb160-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;HTML(ani.to_html5_video())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;video width="576" height="576" controls autoplay loop&gt;
&lt;source type="video/mp4" src="data:video/mp4;base64,AAAAIGZ0eXBNNFYgAAACAE00ViBpc29taXNvMmF2YzEAAAAIZnJlZQACem5tZGF0AAACrgYF//+q%0A3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE2MSByMzAzME0gOGJkNmQyOCAtIEguMjY0L01Q%0ARUctNCBBVkMgY29kZWMgLSBDb3B5bGVmdCAyMDAzLTIwMjAgLSBodHRwOi8vd3d3LnZpZGVvbGFu%0ALm9yZy94MjY0Lmh0bWwgLSBvcHRpb25zOiBjYWJhYz0xIHJlZj0zIGRlYmxvY2s9MTowOjAgYW5h%0AbHlzZT0weDM6MHgxMTMgbWU9aGV4IHN1Ym1lPTcgcHN5PTEgcHN5X3JkPTEuMDA6MC4wMCBtaXhl%0AZF9yZWY9MSBtZV9yYW5nZT0xNiBjaHJvbWFfbWU9MSB0cmVsbGlzPTEgOHg4ZGN0PTEgY3FtPTAg%0AZGVhZHpvbmU9MjEsMTEgZmFzdF9wc2tpcD0xIGNocm9tYV9xcF9vZmZzZXQ9LTIgdGhyZWFkcz02%0AIGxvb2thaGVhZF90aHJlYWRzPTEgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50%0AZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MyBi%0AX3B5cmFtaWQ9MiBiX2FkYXB0PTEgYl9iaWFzPTAgZGlyZWN0PTEgd2VpZ2h0Yj0xIG9wZW5fZ29w%0APTAgd2VpZ2h0cD0yIGtleWludD0yNTAga2V5aW50X21pbj01IHNjZW5lY3V0PTQwIGludHJhX3Jl%0AZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAu%0ANjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAu%0AzWWIhAAR//73iB8yy2n5OtdyEeetLq0fUO5GcV6kvf4gAAADAAADAA4SCLMzbu2wEQuAAAICADQi%0AVPOG7AQEEYBOTYrpcvzn2E2TFVCXvS6LV0auZBNFwwCPZB/8CagiT+Vpp230TwtlgZosQIqj+rwe%0AfUUZutt61kLxxfm6M8mowkQTukkJSr2xB0Irdgo2+WvRL+B8kSBNr/c7CYI+OD1rzvd5S39feUWH%0A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"&gt;
Your browser does not support the video tag. &lt;/source&gt;&lt;/video&gt;
&lt;/center&gt;
&lt;p&gt;I’m not really sure how interpretable this is, but it is kind of mesmerizing.&lt;/p&gt;
&lt;p&gt;Finally, we play 1,000 random games of standard Battleship using this strategy to understand the distributions of the number of turns required.&lt;/p&gt;
&lt;div class="sourceCode" id="cb161"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb161-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb161-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;N_GAME &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1_000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb162"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb162-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; pickleable_play(args):&lt;/span&gt;
&lt;span id="cb162-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    i, ships &lt;span class="op"&gt;=&lt;/span&gt; args&lt;/span&gt;
&lt;span id="cb162-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb162-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; play(&lt;/span&gt;
&lt;span id="cb162-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ships,&lt;/span&gt;
&lt;span id="cb162-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ThompsonStrategy(all_ships,&lt;/span&gt;
&lt;span id="cb162-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         rng&lt;span class="op"&gt;=&lt;/span&gt;np.random.default_rng(SEED &lt;span class="op"&gt;+&lt;/span&gt; i))&lt;/span&gt;
&lt;span id="cb162-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb162-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb162-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; mp.Pool(mp.cpu_count()) &lt;span class="im"&gt;as&lt;/span&gt; pool:&lt;/span&gt;
&lt;span id="cb162-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ts_games &lt;span class="op"&gt;=&lt;/span&gt; [game &lt;span class="cf"&gt;for&lt;/span&gt; game &lt;span class="kw"&gt;in&lt;/span&gt; tqdm(&lt;/span&gt;
&lt;span id="cb162-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        pool.imap_unordered(&lt;/span&gt;
&lt;span id="cb162-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            pickleable_play,&lt;/span&gt;
&lt;span id="cb162-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="bu"&gt;zip&lt;/span&gt;(&lt;span class="bu"&gt;range&lt;/span&gt;(N_GAME),&lt;/span&gt;
&lt;span id="cb162-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                sample_ships(all_ships, N_GAME, rng&lt;span class="op"&gt;=&lt;/span&gt;rng))&lt;/span&gt;
&lt;span id="cb162-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ),&lt;/span&gt;
&lt;span id="cb162-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        total&lt;span class="op"&gt;=&lt;/span&gt;N_GAME&lt;/span&gt;
&lt;span id="cb162-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb162-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;100%|██████████| 1000/1000 [15:32&amp;lt;00:00, 1.07it/s]&lt;/p&gt;
&lt;div class="sourceCode" id="cb163"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb163-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb163-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ts_turns &lt;span class="op"&gt;=&lt;/span&gt; np.array([game.turns &lt;span class="cf"&gt;for&lt;/span&gt; game &lt;span class="kw"&gt;in&lt;/span&gt; ts_games])&lt;/span&gt;
&lt;span id="cb163-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb163-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ts_turns_pmf &lt;span class="op"&gt;=&lt;/span&gt; Pmf.from_seq(ts_turns)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb164"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb164-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb164-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ts_turns_pmf.to_csv(&lt;span class="st"&gt;'./ts_turns_pmf.csv'&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb165"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb165-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_turn_dist(std_random_pmf, kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'line'&lt;/span&gt;, mean&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb165-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Random guessing"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb165-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_turn_dist(ts_turns_pmf, color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C1'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb165-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               mean&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, mean_kwargs&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;'c'&lt;/span&gt;: &lt;span class="st"&gt;'C1'&lt;/span&gt;},&lt;/span&gt;
&lt;span id="cb165-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Thompson sampling"&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb165-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.axvline(extreme_ev, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C2'&lt;/span&gt;, ls&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'--'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb165-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Extremely optimistic&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;expected value"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb165-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.axvline(optim_ev, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C3'&lt;/span&gt;, ls&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'--'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb165-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Optimistic&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;expected value"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb165-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb165-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.xaxis.set_major_locator(IndexLocator(base&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;5&lt;/span&gt;, offset&lt;span class="op"&gt;=-&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb165-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb165-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylim(&lt;span class="dv"&gt;0&lt;/span&gt;, &lt;span class="fl"&gt;0.0825&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb165-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_pct_yaxis(ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb165-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb165-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'upper right'&lt;/span&gt;, bbox_to_anchor&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="fl"&gt;0.825&lt;/span&gt;, &lt;span class="dv"&gt;1&lt;/span&gt;))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb165-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb165-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Standard Battleship"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/battleship_bayes_files/battleship_bayes_238_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb166"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb166-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb166-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="bu"&gt;print&lt;/span&gt;(&lt;span class="ss"&gt;f"""&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb166-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb166-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ss"&gt;Extremely optimistic expected value = &lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;extreme_ev&lt;span class="sc"&gt;:.2f}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb166-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb166-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ss"&gt;Optimistic expected value = &lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;optim_ev&lt;span class="sc"&gt;:.2f}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb166-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb166-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ss"&gt;Thompson sampling expected value = &lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;ts_turns_pmf&lt;span class="sc"&gt;.&lt;/span&gt;mean()&lt;span class="sc"&gt;:.2f}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb166-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb166-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ss"&gt;"""&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Extremely optimistic expected value = 40.18 Optimistic expected value = 42.68 Thompson sampling expected value = 45.89&lt;/p&gt;
&lt;p&gt;It’s very exciting to see that Thompson sampling is not too much less efficient (on average) than our (extremely) optimistic baseline expected values!&lt;/p&gt;
&lt;p&gt;For fun, we visualize the simulated games with the fewest and most turns, to see what it looks like when we get very lucky or unlucky.&lt;/p&gt;
&lt;div class="sourceCode" id="cb167"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb167-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb167-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;min_ts_game &lt;span class="op"&gt;=&lt;/span&gt; ts_games[(ts_turns &lt;span class="op"&gt;==&lt;/span&gt; ts_turns.&lt;span class="bu"&gt;min&lt;/span&gt;()).argmax()]&lt;/span&gt;
&lt;span id="cb167-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb167-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;max_ts_game &lt;span class="op"&gt;=&lt;/span&gt; ts_games[(ts_turns &lt;span class="op"&gt;==&lt;/span&gt; ts_turns.&lt;span class="bu"&gt;max&lt;/span&gt;()).argmax()]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb168"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb168-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb168-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%%&lt;/span&gt;capture&lt;/span&gt;
&lt;span id="cb168-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb168-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;min_ani &lt;span class="op"&gt;=&lt;/span&gt; animate_boards(min_ts_game.turn_revealed)&lt;/span&gt;
&lt;span id="cb168-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb168-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;max_ani &lt;span class="op"&gt;=&lt;/span&gt; animate_boards(max_ts_game.turn_revealed)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb169"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb169-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb169-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;HTML(min_ani.to_html5_video())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;video width="576" height="576" controls autoplay loop&gt;
&lt;source type="video/mp4" src="data:video/mp4;base64,AAAAIGZ0eXBNNFYgAAACAE00ViBpc29taXNvMmF2YzEAAAAIZnJlZQAALtNtZGF0AAACrgYF//+q%0A3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE2MSByMzAzME0gOGJkNmQyOCAtIEguMjY0L01Q%0ARUctNCBBVkMgY29kZWMgLSBDb3B5bGVmdCAyMDAzLTIwMjAgLSBodHRwOi8vd3d3LnZpZGVvbGFu%0ALm9yZy94MjY0Lmh0bWwgLSBvcHRpb25zOiBjYWJhYz0xIHJlZj0zIGRlYmxvY2s9MTowOjAgYW5h%0AbHlzZT0weDM6MHgxMTMgbWU9aGV4IHN1Ym1lPTcgcHN5PTEgcHN5X3JkPTEuMDA6MC4wMCBtaXhl%0AZF9yZWY9MSBtZV9yYW5nZT0xNiBjaHJvbWFfbWU9MSB0cmVsbGlzPTEgOHg4ZGN0PTEgY3FtPTAg%0AZGVhZHpvbmU9MjEsMTEgZmFzdF9wc2tpcD0xIGNocm9tYV9xcF9vZmZzZXQ9LTIgdGhyZWFkcz02%0AIGxvb2thaGVhZF90aHJlYWRzPTEgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50%0AZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MyBi%0AX3B5cmFtaWQ9MiBiX2FkYXB0PTEgYl9iaWFzPTAgZGlyZWN0PTEgd2VpZ2h0Yj0xIG9wZW5fZ29w%0APTAgd2VpZ2h0cD0yIGtleWludD0yNTAga2V5aW50X21pbj01IHNjZW5lY3V0PTQwIGludHJhX3Jl%0AZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAu%0ANjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAS%0AO2WIhAAT//73sY+BTcgADZc6inof4RWx9JBRerHZoGTqAAADAAADAABOFqne+b9ctAjWAAAHoACZ%0AByc9/EUZ3AAoA1yAjY2aIWsgS0VXFocH9xPJajdFAQgt5+76H1SkdMsUWwQmsqmTyBbj3DByB3ZW%0AC1al5iUrRusdG3mRRXT1j72tF2gK89bXWuYN5Ge6p6mAP3w/YzzMWeWY7835v19DJEa41SlTGEBY%0A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"&gt;
Your browser does not support the video tag. &lt;/source&gt;&lt;/video&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb170"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb170-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-09-02-battleship-bayes.html#cb170-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;HTML(max_ani.to_html5_video())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;video width="576" height="576" controls autoplay loop&gt;
&lt;source type="video/mp4" src="data:video/mp4;base64,AAAAIGZ0eXBNNFYgAAACAE00ViBpc29taXNvMmF2YzEAAAAIZnJlZQAAWd5tZGF0AAACrgYF//+q%0A3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE2MSByMzAzME0gOGJkNmQyOCAtIEguMjY0L01Q%0ARUctNCBBVkMgY29kZWMgLSBDb3B5bGVmdCAyMDAzLTIwMjAgLSBodHRwOi8vd3d3LnZpZGVvbGFu%0ALm9yZy94MjY0Lmh0bWwgLSBvcHRpb25zOiBjYWJhYz0xIHJlZj0zIGRlYmxvY2s9MTowOjAgYW5h%0AbHlzZT0weDM6MHgxMTMgbWU9aGV4IHN1Ym1lPTcgcHN5PTEgcHN5X3JkPTEuMDA6MC4wMCBtaXhl%0AZF9yZWY9MSBtZV9yYW5nZT0xNiBjaHJvbWFfbWU9MSB0cmVsbGlzPTEgOHg4ZGN0PTEgY3FtPTAg%0AZGVhZHpvbmU9MjEsMTEgZmFzdF9wc2tpcD0xIGNocm9tYV9xcF9vZmZzZXQ9LTIgdGhyZWFkcz02%0AIGxvb2thaGVhZF90aHJlYWRzPTEgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50%0AZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MyBi%0AX3B5cmFtaWQ9MiBiX2FkYXB0PTEgYl9iaWFzPTAgZGlyZWN0PTEgd2VpZ2h0Yj0xIG9wZW5fZ29w%0APTAgd2VpZ2h0cD0yIGtleWludD0yNTAga2V5aW50X21pbj01IHNjZW5lY3V0PTQwIGludHJhX3Jl%0AZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAu%0ANjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAT%0ABGWIhAAU//73x0/Apuj5ZsudRT0hMIrY+kgovVjs0DJ1AAADAAADAAAnC1TyJ9+uWgRrAAADA9AA%0ATIOTof+QgP/wAKAR8JeaTiaWRl1Y5/CnPVXYItmAZwzyJdiYfgtmtHL3qIbgkoRb3ejEN4QUHfiY%0A5xtap8TSzdmc+r1elFMH0FMeRBdxhxcRrDZhFpLNSpXmBB6wu8jfx0UvuFSipvMmrZiMcTbkpVom%0A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%0AACgAAAAAAQAAEAAAAAABAAAAAAAAAAEAAAgAAAAAAQAAKAAAAAABAAAQAAAAAAEAAAAAAAAAAQAA%0ACAAAAAABAAAoAAAAAAEAABAAAAAAAQAAAAAAAAABAAAIAAAAAAEAABgAAAAAAQAACAAAAAABAAAQ%0AAAAAAAEAACgAAAAAAQAAEAAAAAABAAAAAAAAAAEAAAgAAAAAAQAAKAAAAAABAAAQAAAAAAEAAAAA%0AAAAAAQAACAAAAAABAAAoAAAAAAEAABAAAAAAAQAAAAAAAAABAAAIAAAAAAEAABAAAAAAAQAAGAAA%0AAAABAAAIAAAAAAEAABAAAAAAAQAAKAAAAAABAAAQAAAAAAEAAAAAAAAAAQAACAAAAAABAAAoAAAA%0AAAEAABAAAAAAAQAAAAAAAAABAAAIAAAAAAEAACgAAAAAAQAAEAAAAAABAAAAAAAAAAEAAAgAAAAA%0AAQAAEAAAAAABAAAoAAAAAAEAABAAAAAAAQAAAAAAAAABAAAIAAAAAAEAABgAAAAAAQAACAAAAAAB%0AAAAoAAAAAAEAABAAAAAAAQAAAAAAAAABAAAIAAAAAAEAACgAAAAAAQAAEAAAAAABAAAAAAAAAAEA%0AAAgAAAAAAQAAKAAAAAABAAAQAAAAAAEAAAAAAAAAAQAACAAAAAABAAAoAAAAAAEAABAAAAAAAQAA%0AAAAAAAABAAAIAAAAAAEAACAAAAAAAgAACAAAAAABAAAQAAAAABxzdHNjAAAAAAAAAAEAAAABAAAA%0ARwAAAAEAAAEwc3RzegAAAAAAAAAAAAAARwAAFboAAAR5AAAAdQAAAEAAAABDAAADawAAAFIAAAAy%0AAAAALgAAA4gAAABQAAAANwAAADsAAAGrAAAANQAAAPQAAALMAAAASwAAAGMAAAA0AAADlwAAAFQA%0AAAA2AAAANwAAAv8AAABdAAAAMgAAACsAAAGGAAAByAAAACkAAAEZAAAD0gAAAGMAAAAsAAAAMQAA%0AAw4AAABIAAAALAAAACkAAANbAAAASgAAAC4AAAAtAAABSAAAA0QAAAA8AAAAMgAAACsAAAHTAAAA%0AKgAAAqgAAABEAAAAJwAAACoAAAK3AAAAdwAAACwAAAAtAAACawAAAGcAAAAtAAAASgAAAhAAAABb%0AAAAANQAAADAAAAFvAAAATwAAAE4AAADZAAAAFHN0Y28AAAAAAAAAAQAAADAAAABidWR0YQAAAFpt%0AZXRhAAAAAAAAACFoZGxyAAAAAAAAAABtZGlyYXBwbAAAAAAAAAAAAAAAAC1pbHN0AAAAJal0b28A%0AAAAdZGF0YQAAAAEAAAAATGF2ZjU4LjQ1LjEwMA=="&gt;
Your browser does not support the video tag. &lt;/source&gt;&lt;/video&gt;
&lt;/center&gt;
&lt;p&gt;Interestingly, we see that the fastest game three ships adjacent to each other. We likely got a bit of a speedup from finding two of those while attempting to sink the first one hit.&lt;/p&gt;
&lt;p&gt;These simulated games naturally invite the question of whether Thompson sampling is optimal for standard Battleship (in the appropriate sense) as we have implemented it. I strongly suspect that it is near-optimal, but not quite optimal. Likely Thompson sampling combined with a few simple rules (like a restricted initial search grid) will produce slightly better (and perhaps even optimal) results. Searching the internet for prior work on near optimal Battleship strategies yields a &lt;a href="https://slate.com/culture/2012/05/how-to-win-at-battleship.html"&gt;few&lt;/a&gt; &lt;a href="https://www.datagenetics.com/blog/december32011/"&gt;articles&lt;/a&gt; about strategies that take, on average, 42-44 guesses to complete the game. Our simple Thompson sampling approach is quite close to that range, and with a few heuristics bolted on would likely be able to shave off a few turns to reach that level of performance. We can also improve the performance of Thompson sampling at the cost of computational time by increasing the &lt;code&gt;block_size&lt;/code&gt; used for sampling, resulting in a more accurate approximation to the posterior distribution. Another interesting feature of the strategies in those articles is that they try to balance searching (exploration) and sinking known ships (exploitation) with rules, which we do not have to do explicitly when using Thompson sampling.&lt;/p&gt;
&lt;p&gt;Two other interesting extensions of this work would be to change the process of randomly generating ships (which is equivalent to changing the prior used in ABC) and to explore which strategies for initially placing ships take the longest for Thompson sampling to solve.&lt;/p&gt;
&lt;p&gt;This framework is generalizable to &lt;a href="https://en.wikipedia.org/wiki/Battleship_(game)#Variations"&gt;variations&lt;/a&gt; of Battleship such as salvo or or limited lying is allowed, and we may explore those generalizations in future posts.&lt;/p&gt;
&lt;p&gt;Many thanks to &lt;a href="https://kirilzvezdarov.com/about.html"&gt;Kiril Zvezdarov&lt;/a&gt; and &lt;a href="https://mjhajharia.com/"&gt;Meenal Jhajharia&lt;/a&gt; for providing helpful feedback on early drafts of this post.&lt;/p&gt;
&lt;p&gt;This post is available as a Jupyter notebook &lt;a href="https://nbviewer.jupyter.org/gist/AustinRochford/6e21325d33b2be35cdf835f2ddaa9f3b"&gt;here&lt;/a&gt;.&lt;/p&gt;</description><category>Approximate Bayesian Computation</category><category>Battleship</category><category>Bayesian Statistics</category><category>Search Theory</category><category>Thompson Sampling</category><guid>https://austinrochford.com/posts/2021-09-02-battleship-bayes.html</guid><pubDate>Thu, 02 Sep 2021 04:00:00 GMT</pubDate></item><item><title>Bayesian Splines with Heteroskedastic Noise in Python with PyMC3</title><link>https://austinrochford.com/posts/2021-08-11-splines-hetero.html</link><dc:creator>Austin Rochford</dc:creator><description>&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Spline_(mathematics)"&gt;Splines&lt;/a&gt; are a powerful tool when modeling nonlinear relationships. This post shows how to include splines in a Bayesian model in Python using &lt;a href="https://en.wikipedia.org/wiki/Spline_(mathematics)"&gt;&lt;code&gt;pymc3&lt;/code&gt;&lt;/a&gt;. In addition, we will show how to use a second spline component to handle &lt;a href="https://en.wikipedia.org/wiki/Heteroscedasticity"&gt;heteroskedastic&lt;/a&gt; data, that is, data where the noise scale is not constant.&lt;/p&gt;
&lt;center&gt;
&lt;fig&gt; &lt;img src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/ee/Cardinal_cubic_B-spline2.svg/1280px-Cardinal_cubic_B-spline2.svg.png" width="600"&gt; &lt;br&gt;
&lt;caption&gt;
Image credit &lt;a href="https://en.wikipedia.org/wiki/B-spline"&gt;Wikipedia&lt;/a&gt;
&lt;/caption&gt;
&lt;/fig&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;To illustrate these concepts, we will use &lt;a href="https://en.wikipedia.org/wiki/Lidar"&gt;Lidar&lt;/a&gt; data from Larry Wasserman’s excellent book &lt;a href="http://www.stat.cmu.edu/~larry/all-of-nonpar/"&gt;&lt;em&gt;All of Nonparametric Statistics&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="load-the-data"&gt;Load the Data&lt;/h2&gt;
&lt;p&gt;First we make the necessary Python imports and do some light housekeeping.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb1-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;matplotlib inline&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb2-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; warnings &lt;span class="im"&gt;import&lt;/span&gt; filterwarnings&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb3-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; aesara &lt;span class="im"&gt;import&lt;/span&gt; shared, tensor &lt;span class="im"&gt;as&lt;/span&gt; at&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; arviz &lt;span class="im"&gt;as&lt;/span&gt; az&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; matplotlib &lt;span class="im"&gt;as&lt;/span&gt; mpl&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib &lt;span class="im"&gt;import&lt;/span&gt; pyplot &lt;span class="im"&gt;as&lt;/span&gt; plt&lt;/span&gt;
&lt;span id="cb3-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb3-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; numpy &lt;span class="im"&gt;as&lt;/span&gt; np&lt;/span&gt;
&lt;span id="cb3-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb3-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pandas &lt;span class="im"&gt;as&lt;/span&gt; pd&lt;/span&gt;
&lt;span id="cb3-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb3-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pymc3 &lt;span class="im"&gt;as&lt;/span&gt; pm&lt;/span&gt;
&lt;span id="cb3-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb3-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; scipy &lt;span class="im"&gt;as&lt;/span&gt; sp&lt;/span&gt;
&lt;span id="cb3-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb3-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; seaborn &lt;span class="im"&gt;as&lt;/span&gt; sns&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;You are running the v4 development version of PyMC3 which currently still lacks key features. You probably want to use the stable v3 instead which you can either install via conda or find on the v3 GitHub branch: https://github.com/pymc-devs/pymc3/tree/v3&lt;/code&gt;&lt;/pre&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb5-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;filterwarnings(&lt;span class="st"&gt;'ignore'&lt;/span&gt;, category&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="pp"&gt;UserWarning&lt;/span&gt;, module&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'arviz'&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb6-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;mpl.rcParams[&lt;span class="st"&gt;'figure.figsize'&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb6-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb6-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.&lt;span class="bu"&gt;set&lt;/span&gt;(color_codes&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We are now ready to load the data.&lt;/p&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb7-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb7-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;DATA_URL &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="st"&gt;'http://www.stat.cmu.edu/~larry/all-of-nonpar/=data/lidar.dat'&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb8-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df &lt;span class="op"&gt;=&lt;/span&gt; pd.read_csv(DATA_URL, sep&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;' +'&lt;/span&gt;, engine&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'python'&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb9-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
range
&lt;/th&gt;
&lt;th&gt;
logratio
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
390
&lt;/td&gt;
&lt;td&gt;
-0.050356
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1
&lt;/th&gt;
&lt;td&gt;
391
&lt;/td&gt;
&lt;td&gt;
-0.060097
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2
&lt;/th&gt;
&lt;td&gt;
393
&lt;/td&gt;
&lt;td&gt;
-0.041901
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
3
&lt;/th&gt;
&lt;td&gt;
394
&lt;/td&gt;
&lt;td&gt;
-0.050985
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
4
&lt;/th&gt;
&lt;td&gt;
396
&lt;/td&gt;
&lt;td&gt;
-0.059913
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb10"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb10-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb10-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df.describe()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
range
&lt;/th&gt;
&lt;th&gt;
logratio
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
count
&lt;/th&gt;
&lt;td&gt;
221.000000
&lt;/td&gt;
&lt;td&gt;
221.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
mean
&lt;/th&gt;
&lt;td&gt;
554.751131
&lt;/td&gt;
&lt;td&gt;
-0.291156
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
std
&lt;/th&gt;
&lt;td&gt;
95.912396
&lt;/td&gt;
&lt;td&gt;
0.282475
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
min
&lt;/th&gt;
&lt;td&gt;
390.000000
&lt;/td&gt;
&lt;td&gt;
-0.949554
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
25%
&lt;/th&gt;
&lt;td&gt;
472.000000
&lt;/td&gt;
&lt;td&gt;
-0.542305
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
50%
&lt;/th&gt;
&lt;td&gt;
555.000000
&lt;/td&gt;
&lt;td&gt;
-0.108043
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
75%
&lt;/th&gt;
&lt;td&gt;
637.000000
&lt;/td&gt;
&lt;td&gt;
-0.054825
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
max
&lt;/th&gt;
&lt;td&gt;
720.000000
&lt;/td&gt;
&lt;td&gt;
0.026907
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;We standardize both &lt;code&gt;range&lt;/code&gt; and &lt;code&gt;logratio&lt;/code&gt; to make it easier to specify priors once we begin building our spline models.&lt;/p&gt;
&lt;div class="sourceCode" id="cb11"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb11-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb11-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_df &lt;span class="op"&gt;=&lt;/span&gt; (df &lt;span class="op"&gt;-&lt;/span&gt; df.mean()) &lt;span class="op"&gt;/&lt;/span&gt; df.std()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb12"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb12-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb12-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
range
&lt;/th&gt;
&lt;th&gt;
logratio
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
-1.717725
&lt;/td&gt;
&lt;td&gt;
0.852467
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1
&lt;/th&gt;
&lt;td&gt;
-1.707299
&lt;/td&gt;
&lt;td&gt;
0.817981
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2
&lt;/th&gt;
&lt;td&gt;
-1.686447
&lt;/td&gt;
&lt;td&gt;
0.882398
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
3
&lt;/th&gt;
&lt;td&gt;
-1.676020
&lt;/td&gt;
&lt;td&gt;
0.850240
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
4
&lt;/th&gt;
&lt;td&gt;
-1.655168
&lt;/td&gt;
&lt;td&gt;
0.818631
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h3 id="exploratory-data-analysis"&gt;Exploratory Data Analysis&lt;/h3&gt;
&lt;p&gt;The task at hand is to model (standardized) &lt;code&gt;logratio&lt;/code&gt; as a function of (standardized) &lt;code&gt;range&lt;/code&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb13"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb13-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, (std_ax, joint_ax) &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(&lt;/span&gt;
&lt;span id="cb13-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    nrows&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb13-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    gridspec_kw&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;'height_ratios'&lt;/span&gt;: [&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;4&lt;/span&gt;]}&lt;/span&gt;
&lt;span id="cb13-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb13-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"range"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"logratio"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;std_df,&lt;/span&gt;
&lt;span id="cb13-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;joint_ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(std_df.groupby(std_df[&lt;span class="st"&gt;"range"&lt;/span&gt;].&lt;span class="bu"&gt;round&lt;/span&gt;(&lt;span class="dv"&gt;1&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb13-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       [&lt;span class="st"&gt;"logratio"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb13-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .std()&lt;/span&gt;
&lt;span id="cb13-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .rolling(&lt;span class="dv"&gt;5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb13-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .mean()&lt;/span&gt;
&lt;span id="cb13-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .plot(ax&lt;span class="op"&gt;=&lt;/span&gt;std_ax))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_ax.set_ylabel(&lt;span class="st"&gt;"Standard&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;deviation&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;(binned)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb13-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/splines_hetero_files/splines_hetero_18_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The scatter plot shows that the relationship is definitely nonlinear, and there is no obvious (to me at least) transform of &lt;code&gt;logratio&lt;/code&gt; that will make the relationship linear. The top plot shows how the (binned, smoothed) standard deviation of &lt;code&gt;logratio&lt;/code&gt; varies with &lt;code&gt;range&lt;/code&gt;. As is evident from both plots, as &lt;code&gt;range&lt;/code&gt; increases, so does the scale of variation of &lt;code&gt;logratio&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="introduction-to-splines"&gt;Introduction to Splines&lt;/h2&gt;
&lt;p&gt;Regression splines are a type of of &lt;a href="https://en.wikipedia.org/wiki/Generalized_additive_model"&gt;generalized additive model&lt;/a&gt; (GAM) that use linear combinations of (generally low-degree) polynomials to introduce nonlinear relationships between covariates and responses.&lt;/p&gt;
&lt;p&gt;To begin constructing our spline model, we must choose a number of knots (also known as anchors or control points) in the domain of our co variate. In this post we will use twenty splines in the interval &lt;span class="math inline"&gt;\([-1.75, 1.75]\)&lt;/span&gt;, which comfortably contains the observed values of &lt;code&gt;range&lt;/code&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb14"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb14-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb14-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;N_KNOT &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;20&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb14-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb14-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb14-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;knots &lt;span class="op"&gt;=&lt;/span&gt; np.linspace(&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="fl"&gt;1.75&lt;/span&gt;, &lt;span class="fl"&gt;1.75&lt;/span&gt;, N_KNOT)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The following plot shows the location of the knots in the Lidar data.&lt;/p&gt;
&lt;div class="sourceCode" id="cb15"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb15-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, (std_ax, joint_ax) &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(&lt;/span&gt;
&lt;span id="cb15-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    nrows&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb15-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    gridspec_kw&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;'height_ratios'&lt;/span&gt;: [&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;4&lt;/span&gt;]}&lt;/span&gt;
&lt;span id="cb15-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb15-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb15-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"range"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"logratio"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;std_df,&lt;/span&gt;
&lt;span id="cb15-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;joint_ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.rugplot(knots, height&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.075&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb15-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Knots"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb15-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ax&lt;span class="op"&gt;=&lt;/span&gt;joint_ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb15-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(std_df.groupby(std_df[&lt;span class="st"&gt;"range"&lt;/span&gt;].&lt;span class="bu"&gt;round&lt;/span&gt;(&lt;span class="dv"&gt;1&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb15-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       [&lt;span class="st"&gt;"logratio"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb15-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .std()&lt;/span&gt;
&lt;span id="cb15-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .rolling(&lt;span class="dv"&gt;5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb15-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .mean()&lt;/span&gt;
&lt;span id="cb15-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .plot(ax&lt;span class="op"&gt;=&lt;/span&gt;std_ax))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.rugplot(knots, height&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.15&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb15-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Knots"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb15-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ax&lt;span class="op"&gt;=&lt;/span&gt;std_ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb15-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_ax.set_ylabel(&lt;span class="st"&gt;"Standard&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;deviation&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;(binned)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb15-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;joint_ax.legend()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb15-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/splines_hetero_files/splines_hetero_23_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Let &lt;span class="math inline"&gt;\(x^*_i\)&lt;/span&gt;, &lt;span class="math inline"&gt;\(i = 1, 2, \ldots, 20\)&lt;/span&gt; be the location of the &lt;span class="math inline"&gt;\(j\)&lt;/span&gt;-th knot. The spline model we will use is given by&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[E(Y\ |\ X) = \sum_{j = 1}^{20} \beta_j \cdot B_{j, k; \mathbf{x}^*}(X)\]&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;(If one applies a link function to the conditional expectation of the left hand side, this becomes a &lt;em&gt;generalized&lt;/em&gt; additive model.) For spline regression, &lt;span class="math inline"&gt;\(B_{j, k; \mathbf{x}^*}(\cdot)\)&lt;/span&gt; is a &lt;span class="math inline"&gt;\(k\)&lt;/span&gt;-th-degree polynomial in &lt;span class="math inline"&gt;\(x\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(x^*\)&lt;/span&gt;. There are many possible choices for these functions. We will use &lt;code&gt;scipy&lt;/code&gt;’s cubic &lt;a href="https://en.wikipedia.org/wiki/B-spline"&gt;B-spline&lt;/a&gt; &lt;a href="https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.BSpline.html"&gt;implementation&lt;/a&gt;. For more information splines, consult Simon Wood’s excellent book &lt;a href="https://www.taylorfrancis.com/books/mono/10.1201/9781315370279/generalized-additive-models-simon-wood"&gt;&lt;em&gt;Generalized Additive Models&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb16"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb16-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb16-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;basis &lt;span class="op"&gt;=&lt;/span&gt; sp.interpolate.BSpline(knots, np.eye(N_KNOT), &lt;span class="dv"&gt;3&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We see that &lt;code&gt;basis&lt;/code&gt; is a callable function function that will give the design matrix for spline regression at a given set of points.&lt;/p&gt;
&lt;div class="sourceCode" id="cb17"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb17-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb17-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="bu"&gt;hasattr&lt;/span&gt;(basis, &lt;span class="st"&gt;'__call__'&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;True&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We build this design matrix at the (standardized) value of &lt;code&gt;range&lt;/code&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb19"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb19-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb19-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;dmat &lt;span class="op"&gt;=&lt;/span&gt; shared(basis(std_df[&lt;span class="st"&gt;"range"&lt;/span&gt;]))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With &lt;code&gt;dmat&lt;/code&gt; in hand, we are ready to build our model with &lt;code&gt;pymc3&lt;/code&gt;. We follow the model specified in &lt;a href="http://www.miladkh.com/"&gt;Milad Kharratzadeh’s&lt;/a&gt; excellent short paper &lt;a href="https://github.com/milkha/Splines_in_Stan/blob/master/splines_in_stan.pdf"&gt;&lt;em&gt;Splines in Stan&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The model for the conditional mean is given above,&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[\mu\ |\ X = \sum_{j = 1}^{20} \beta_j \cdot B_{j, k; \mathbf{x}^*}(X).\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We put a Gaussian random walk prior (GRW) on these coefficients &lt;span class="math inline"&gt;\(\beta_j\)&lt;/span&gt;, under the intuition that the coefficients for adjacent knots should be similar. We parameterize our GRW as follows:&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \mu_{\beta}
        &amp;amp; \sim N(0, 2.5^2) \\
    \Delta_{\beta, j}
        &amp;amp; \sim N(0, 1) \\
    \sigma_{\beta}
        &amp;amp; \sim \mathrm{Half}-N(2.5^2) \\
    \beta_j
        &amp;amp; = \mu_{\beta} + \sigma_{\beta} \cdot \sum_{i = 1}^j \Delta_{\beta, i}.
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb20"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb20-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb20-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# the scale necessary to make a halfnormal distribution&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb20-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# have unit variance&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb20-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;HALFNORMAL_SCALE &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="fl"&gt;1.&lt;/span&gt; &lt;span class="op"&gt;/&lt;/span&gt; np.sqrt(&lt;span class="fl"&gt;1.&lt;/span&gt; &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="fl"&gt;2.&lt;/span&gt; &lt;span class="op"&gt;/&lt;/span&gt; np.pi)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb21"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb21-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb21-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;coords &lt;span class="op"&gt;=&lt;/span&gt; {&lt;span class="st"&gt;"knot"&lt;/span&gt;: np.arange(N_KNOT)}&lt;/span&gt;
&lt;span id="cb21-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb21-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb21-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb21-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model(coords&lt;span class="op"&gt;=&lt;/span&gt;coords) &lt;span class="im"&gt;as&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb21-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb21-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ_β &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"μ_β"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb21-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb21-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    Δ_β &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"Δ_β"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;1.&lt;/span&gt;, dims&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"knot"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb21-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb21-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ_β &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"σ_β"&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; HALFNORMAL_SCALE)&lt;/span&gt;
&lt;span id="cb21-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb21-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;span class="st"&gt;"β"&lt;/span&gt;, μ_β &lt;span class="op"&gt;+&lt;/span&gt; σ_β &lt;span class="op"&gt;*&lt;/span&gt; Δ_β.cumsum(),&lt;/span&gt;
&lt;span id="cb21-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb21-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         dims&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"knot"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb21-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb21-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; at.dot(dmat, β)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Our observational model here is normal, with unknown variance &lt;span class="math inline"&gt;\(\sigma \sim \mathrm{Half-}N(2.5^2)\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb22"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb22-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb22-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb22-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb22-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"σ"&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; HALFNORMAL_SCALE)&lt;/span&gt;
&lt;span id="cb22-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb22-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"obs"&lt;/span&gt;, μ, σ, observed&lt;span class="op"&gt;=&lt;/span&gt;std_df[&lt;span class="st"&gt;"logratio"&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now sample from the posterior distribution of this model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb23"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb23-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb23-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SEED &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;123456789&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb23-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;CORES &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb23-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb23-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb23-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SAMPLE_KWARGS &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb23-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb23-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'cores'&lt;/span&gt;: CORES,&lt;/span&gt;
&lt;span id="cb23-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb23-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'random_seed'&lt;/span&gt;: [SEED &lt;span class="op"&gt;+&lt;/span&gt; i &lt;span class="cf"&gt;for&lt;/span&gt; i &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;range&lt;/span&gt;(CORES)],&lt;/span&gt;
&lt;span id="cb23-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb23-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'return_inferencedata'&lt;/span&gt;: &lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb23-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb23-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'target_accept'&lt;/span&gt;: &lt;span class="fl"&gt;0.95&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb23-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb24"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb24-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb24-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb24-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb24-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [μ_β, Δ_β, σ_β, σ]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="6000" class max="6000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [6000/6000 02:21&amp;lt;00:00 Sampling 3 chains, 0 divergences]&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Sampling 3 chains for 1_000 tune and 1_000 draw iterations (3_000 + 3_000 draws total) took 142 seconds.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;None of the standard sampling diagnostics show cause for concern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb27"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb27-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb27-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_energy(trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/splines_hetero_files/splines_hetero_40_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb28"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb28-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb28-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.rhat(trace).&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;svg style="position: absolute; width: 0; height: 0; overflow: hidden"&gt;
&lt;defs&gt; &lt;symbol id="icon-database" viewbox="0 0 32 32"&gt; &lt;path d="M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z"&gt;&lt;/path&gt; &lt;path d="M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;path d="M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;symbol id="icon-file-text2" viewbox="0 0 32 32"&gt; &lt;path d="M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z"&gt;&lt;/path&gt; &lt;path d="M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;/defs&gt;
&lt;/svg&gt;
&lt;style&gt;/* CSS stylesheet for displaying xarray objects in jupyterlab.
 *
 */

:root {
  --xr-font-color0: var(--jp-content-font-color0, rgba(0, 0, 0, 1));
  --xr-font-color2: var(--jp-content-font-color2, rgba(0, 0, 0, 0.54));
  --xr-font-color3: var(--jp-content-font-color3, rgba(0, 0, 0, 0.38));
  --xr-border-color: var(--jp-border-color2, #e0e0e0);
  --xr-disabled-color: var(--jp-layout-color3, #bdbdbd);
  --xr-background-color: var(--jp-layout-color0, white);
  --xr-background-color-row-even: var(--jp-layout-color1, white);
  --xr-background-color-row-odd: var(--jp-layout-color2, #eeeeee);
}

html[theme=dark],
body.vscode-dark {
  --xr-font-color0: rgba(255, 255, 255, 1);
  --xr-font-color2: rgba(255, 255, 255, 0.54);
  --xr-font-color3: rgba(255, 255, 255, 0.38);
  --xr-border-color: #1F1F1F;
  --xr-disabled-color: #515151;
  --xr-background-color: #111111;
  --xr-background-color-row-even: #111111;
  --xr-background-color-row-odd: #313131;
}

.xr-wrap {
  display: block;
  min-width: 300px;
  max-width: 700px;
}

.xr-text-repr-fallback {
  /* fallback to plain text repr when CSS is not injected (untrusted notebook) */
  display: none;
}

.xr-header {
  padding-top: 6px;
  padding-bottom: 6px;
  margin-bottom: 4px;
  border-bottom: solid 1px var(--xr-border-color);
}

.xr-header &gt; div,
.xr-header &gt; ul {
  display: inline;
  margin-top: 0;
  margin-bottom: 0;
}

.xr-obj-type,
.xr-array-name {
  margin-left: 2px;
  margin-right: 10px;
}

.xr-obj-type {
  color: var(--xr-font-color2);
}

.xr-sections {
  padding-left: 0 !important;
  display: grid;
  grid-template-columns: 150px auto auto 1fr 20px 20px;
}

.xr-section-item {
  display: contents;
}

.xr-section-item input {
  display: none;
}

.xr-section-item input + label {
  color: var(--xr-disabled-color);
}

.xr-section-item input:enabled + label {
  cursor: pointer;
  color: var(--xr-font-color2);
}

.xr-section-item input:enabled + label:hover {
  color: var(--xr-font-color0);
}

.xr-section-summary {
  grid-column: 1;
  color: var(--xr-font-color2);
  font-weight: 500;
}

.xr-section-summary &gt; span {
  display: inline-block;
  padding-left: 0.5em;
}

.xr-section-summary-in:disabled + label {
  color: var(--xr-font-color2);
}

.xr-section-summary-in + label:before {
  display: inline-block;
  content: '►';
  font-size: 11px;
  width: 15px;
  text-align: center;
}

.xr-section-summary-in:disabled + label:before {
  color: var(--xr-disabled-color);
}

.xr-section-summary-in:checked + label:before {
  content: '▼';
}

.xr-section-summary-in:checked + label &gt; span {
  display: none;
}

.xr-section-summary,
.xr-section-inline-details {
  padding-top: 4px;
  padding-bottom: 4px;
}

.xr-section-inline-details {
  grid-column: 2 / -1;
}

.xr-section-details {
  display: none;
  grid-column: 1 / -1;
  margin-bottom: 5px;
}

.xr-section-summary-in:checked ~ .xr-section-details {
  display: contents;
}

.xr-array-wrap {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 20px auto;
}

.xr-array-wrap &gt; label {
  grid-column: 1;
  vertical-align: top;
}

.xr-preview {
  color: var(--xr-font-color3);
}

.xr-array-preview,
.xr-array-data {
  padding: 0 5px !important;
  grid-column: 2;
}

.xr-array-data,
.xr-array-in:checked ~ .xr-array-preview {
  display: none;
}

.xr-array-in:checked ~ .xr-array-data,
.xr-array-preview {
  display: inline-block;
}

.xr-dim-list {
  display: inline-block !important;
  list-style: none;
  padding: 0 !important;
  margin: 0;
}

.xr-dim-list li {
  display: inline-block;
  padding: 0;
  margin: 0;
}

.xr-dim-list:before {
  content: '(';
}

.xr-dim-list:after {
  content: ')';
}

.xr-dim-list li:not(:last-child):after {
  content: ',';
  padding-right: 5px;
}

.xr-has-index {
  font-weight: bold;
}

.xr-var-list,
.xr-var-item {
  display: contents;
}

.xr-var-item &gt; div,
.xr-var-item label,
.xr-var-item &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-even);
  margin-bottom: 0;
}

.xr-var-item &gt; .xr-var-name:hover span {
  padding-right: 5px;
}

.xr-var-list &gt; li:nth-child(odd) &gt; div,
.xr-var-list &gt; li:nth-child(odd) &gt; label,
.xr-var-list &gt; li:nth-child(odd) &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-odd);
}

.xr-var-name {
  grid-column: 1;
}

.xr-var-dims {
  grid-column: 2;
}

.xr-var-dtype {
  grid-column: 3;
  text-align: right;
  color: var(--xr-font-color2);
}

.xr-var-preview {
  grid-column: 4;
}

.xr-var-name,
.xr-var-dims,
.xr-var-dtype,
.xr-preview,
.xr-attrs dt {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 10px;
}

.xr-var-name:hover,
.xr-var-dims:hover,
.xr-var-dtype:hover,
.xr-attrs dt:hover {
  overflow: visible;
  width: auto;
  z-index: 1;
}

.xr-var-attrs,
.xr-var-data {
  display: none;
  background-color: var(--xr-background-color) !important;
  padding-bottom: 5px !important;
}

.xr-var-attrs-in:checked ~ .xr-var-attrs,
.xr-var-data-in:checked ~ .xr-var-data {
  display: block;
}

.xr-var-data &gt; table {
  float: right;
}

.xr-var-name span,
.xr-var-data,
.xr-attrs {
  padding-left: 25px !important;
}

.xr-attrs,
.xr-var-attrs,
.xr-var-data {
  grid-column: 1 / -1;
}

dl.xr-attrs {
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 125px auto;
}

.xr-attrs dt,
.xr-attrs dd {
  padding: 0;
  margin: 0;
  float: left;
  padding-right: 10px;
  width: auto;
}

.xr-attrs dt {
  font-weight: normal;
  grid-column: 1;
}

.xr-attrs dt:hover span {
  display: inline-block;
  background: var(--xr-background-color);
  padding-right: 10px;
}

.xr-attrs dd {
  grid-column: 2;
  white-space: pre-wrap;
  word-break: break-all;
}

.xr-icon-database,
.xr-icon-file-text2 {
  display: inline-block;
  vertical-align: middle;
  width: 1em;
  height: 1.5em !important;
  stroke-width: 0;
  stroke: currentColor;
  fill: currentColor;
}
&lt;/style&gt;
&lt;pre class="xr-text-repr-fallback"&gt;&amp;lt;xarray.Dataset&amp;gt;
Dimensions:  ()
Data variables:
    μ_β      float64 1.002
    Δ_β      float64 1.003
    σ_β      float64 1.003
    σ        float64 1.001
    β        float64 1.002&lt;/pre&gt;
&lt;div class="xr-wrap" hidden=""&gt;
&lt;div class="xr-header"&gt;
&lt;div class="xr-obj-type"&gt;
xarray.Dataset
&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="xr-sections"&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-6be9e327-8217-444b-82ac-8d72e31b9762" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-6be9e327-8217-444b-82ac-8d72e31b9762" class="xr-section-summary" title="Expand/collapse section"&gt;Dimensions:&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-262c20ca-f234-455e-a412-57ae50add49d" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-262c20ca-f234-455e-a412-57ae50add49d" class="xr-section-summary" title="Expand/collapse section"&gt;Coordinates: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-4159528f-614b-4383-9914-6f8a2ee6919b" class="xr-section-summary-in" type="checkbox" checked&gt;&lt;label for="section-4159528f-614b-4383-9914-6f8a2ee6919b" class="xr-section-summary"&gt;Data variables: &lt;span&gt;(5)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;μ_β&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.002
&lt;/div&gt;
&lt;input id="attrs-e3ef8664-98c0-491b-9e90-f9df14021341" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-e3ef8664-98c0-491b-9e90-f9df14021341" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-3cc66f89-032b-4da6-90dc-c9f43e377ae6" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-3cc66f89-032b-4da6-90dc-c9f43e377ae6" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00177301)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;Δ_β&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.003
&lt;/div&gt;
&lt;input id="attrs-f7d29b36-94b4-49ae-8a0a-604226555c27" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-f7d29b36-94b4-49ae-8a0a-604226555c27" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-788b1891-2d2f-470c-831c-6e0f03a8efb6" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-788b1891-2d2f-470c-831c-6e0f03a8efb6" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00304857)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;σ_β&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.003
&lt;/div&gt;
&lt;input id="attrs-44f8d525-edee-4f7b-911c-81dfb07460b6" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-44f8d525-edee-4f7b-911c-81dfb07460b6" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-f79ac85a-eba8-4c81-a547-6d99db461896" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-f79ac85a-eba8-4c81-a547-6d99db461896" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00278469)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;σ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.001
&lt;/div&gt;
&lt;input id="attrs-e981d8e5-65ab-4f10-b947-5976f10b9c2e" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-e981d8e5-65ab-4f10-b947-5976f10b9c2e" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-902e30d3-d247-469e-99db-87992ac032a3" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-902e30d3-d247-469e-99db-87992ac032a3" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00087722)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;β&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.002
&lt;/div&gt;
&lt;input id="attrs-e31c6ee9-83ae-44b9-a2a2-ae7915a5da0e" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-e31c6ee9-83ae-44b9-a2a2-ae7915a5da0e" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-6b553585-f795-42a2-9667-242dc6c723e9" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-6b553585-f795-42a2-9667-242dc6c723e9" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00209198)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-879965fa-b95c-4639-8d79-138f8d4b19dd" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-879965fa-b95c-4639-8d79-138f8d4b19dd" class="xr-section-summary" title="Expand/collapse section"&gt;Attributes: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To visualize our predictions, we sample from the posterior predictive distribution along a grid of reasonable values for &lt;code&gt;range&lt;/code&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb29"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb29-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb29-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_range &lt;span class="op"&gt;=&lt;/span&gt; np.linspace(&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="fl"&gt;1.75&lt;/span&gt;, &lt;span class="fl"&gt;1.75&lt;/span&gt;, &lt;span class="dv"&gt;100&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb29-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb29-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;dmat.set_value(basis(pp_range))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb30"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb30-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb30-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb30-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb30-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    pp_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample_posterior_predictive(trace)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="3000" class max="3000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [3000/3000 00:00&amp;lt;00:00]&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;We now plot the posterior predictions.&lt;/p&gt;
&lt;div class="sourceCode" id="cb31"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb31-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, (std_ax, joint_ax) &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(&lt;/span&gt;
&lt;span id="cb31-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    nrows&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb31-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    gridspec_kw&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;'height_ratios'&lt;/span&gt;: [&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;4&lt;/span&gt;]}&lt;/span&gt;
&lt;span id="cb31-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb31-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb31-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;low, high &lt;span class="op"&gt;=&lt;/span&gt; np.percentile(pp_trace[&lt;span class="st"&gt;"obs"&lt;/span&gt;], [&lt;span class="fl"&gt;2.5&lt;/span&gt;, &lt;span class="fl"&gt;97.5&lt;/span&gt;], axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;joint_ax.fill_between(pp_range, low, high,&lt;/span&gt;
&lt;span id="cb31-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.25&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb31-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"95&lt;/span&gt;&lt;span class="sc"&gt;% c&lt;/span&gt;&lt;span class="st"&gt;redible interval"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb31-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"range"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"logratio"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;std_df,&lt;/span&gt;
&lt;span id="cb31-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;joint_ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb31-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(std_df.groupby(std_df[&lt;span class="st"&gt;"range"&lt;/span&gt;].&lt;span class="bu"&gt;round&lt;/span&gt;(&lt;span class="dv"&gt;1&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb31-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       [&lt;span class="st"&gt;"logratio"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb31-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .std()&lt;/span&gt;
&lt;span id="cb31-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .rolling(&lt;span class="dv"&gt;5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .mean()&lt;/span&gt;
&lt;span id="cb31-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .plot(ax&lt;span class="op"&gt;=&lt;/span&gt;std_ax, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Actual"&lt;/span&gt;))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb31-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_ax.plot(pp_range, pp_trace[&lt;span class="st"&gt;"obs"&lt;/span&gt;].std(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb31-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Posterior predictive"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb31-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;joint_ax.plot(pp_range, pp_trace[&lt;span class="st"&gt;"obs"&lt;/span&gt;].mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb31-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Posterior expected value"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-26"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb31-27"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_ax.set_ylabel(&lt;span class="st"&gt;"Standard&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;deviation&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;(binned)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-28"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb31-29"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'upper left'&lt;/span&gt;, bbox_to_anchor&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;1.65&lt;/span&gt;))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-30"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;joint_ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'lower left'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-31"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb31-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/splines_hetero_files/splines_hetero_46_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Visually, we appear to have captured the relationship between &lt;code&gt;range&lt;/code&gt; and the expected value of &lt;code&gt;logratio&lt;/code&gt; reasonably well. The credible interval and the standard deviation above are a bit odd though. We have built a homoskedastic (same-variance) observational model, so the credible interval has roughly the same width, even though the data show a small variance for small values of range, and variance increases as &lt;code&gt;range&lt;/code&gt; does.&lt;/p&gt;
&lt;h3 id="accounting-for-heteroskedasticity"&gt;Accounting for heteroskedasticity&lt;/h3&gt;
&lt;p&gt;In order to remedy this issue, we will build a heteroskedastic model that allows the variance of &lt;code&gt;logratio&lt;/code&gt; to vary with &lt;code&gt;ratio&lt;/code&gt;. In fact, we will use a spline to model the changing variance as well.&lt;/p&gt;
&lt;p&gt;Let &lt;span class="math inline"&gt;\(\gamma_j\)&lt;/span&gt; come from a GRW similar to &lt;span class="math inline"&gt;\(\beta_j\)&lt;/span&gt;. We define&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \eta_{\sigma}\ |\ X
        &amp;amp; = \sum_{j = 1}^{20} \gamma_j \cdot B_{j, k; \mathbf{x}^*}(X) \\
    \sigma\ |\ X
        &amp;amp; = 0.05 + \exp(\eta_{\sigma}).
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Note that the &lt;span class="math inline"&gt;\(0.05\)&lt;/span&gt; factor in the definition of &lt;span class="math inline"&gt;\(\sigma\ |\ X\)&lt;/span&gt; sets a lower bound on the variance, which is necessary for computational stability.&lt;/p&gt;
&lt;p&gt;The model is a straightforward adaptation of the homoskedastic one.&lt;/p&gt;
&lt;div class="sourceCode" id="cb32"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb32-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb32-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;dmat.set_value(basis(std_df[&lt;span class="st"&gt;"range"&lt;/span&gt;]))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb33"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb33-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model(coords&lt;span class="op"&gt;=&lt;/span&gt;coords) &lt;span class="im"&gt;as&lt;/span&gt; var_model:&lt;/span&gt;
&lt;span id="cb33-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"β0"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb33-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    Δ_β &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"Δ_β"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;1.&lt;/span&gt;, dims&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"knot"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb33-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ_β &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"σ_β"&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; HALFNORMAL_SCALE)&lt;/span&gt;
&lt;span id="cb33-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;span class="st"&gt;"β"&lt;/span&gt;, β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; Δ_β.cumsum() &lt;span class="op"&gt;*&lt;/span&gt; σ_β,&lt;/span&gt;
&lt;span id="cb33-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         dims&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"knot"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb33-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; at.dot(dmat, β)&lt;/span&gt;
&lt;span id="cb33-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb33-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    γ&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"γ0"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb33-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    Δ_γ &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"Δ_γ"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;1.&lt;/span&gt;, dims&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"knot"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb33-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ_γ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"σ_γ"&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; HALFNORMAL_SCALE)&lt;/span&gt;
&lt;span id="cb33-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    γ &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;span class="st"&gt;"γ"&lt;/span&gt;, γ&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; Δ_γ.cumsum() &lt;span class="op"&gt;*&lt;/span&gt; σ_γ,&lt;/span&gt;
&lt;span id="cb33-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         dims&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"knot"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb33-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    η_σ &lt;span class="op"&gt;=&lt;/span&gt; at.dot(dmat, γ)&lt;/span&gt;
&lt;span id="cb33-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="fl"&gt;0.05&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; at.exp(η_σ)&lt;/span&gt;
&lt;span id="cb33-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb33-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb33-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"obs"&lt;/span&gt;, μ, σ, observed&lt;span class="op"&gt;=&lt;/span&gt;std_df[&lt;span class="st"&gt;"logratio"&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now sample from this model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb34"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb34-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb34-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; var_model:&lt;/span&gt;
&lt;span id="cb34-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb34-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    var_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [β0, Δ_β, σ_β, γ0, Δ_γ, σ_γ]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="6000" class max="6000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [6000/6000 04:42&amp;lt;00:00 Sampling 3 chains, 0 divergences]&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Sampling 3 chains for 1_000 tune and 1_000 draw iterations (3_000 + 3_000 draws total) took 282 seconds.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again the sampling diagnostics show no cause for concern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb37"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb37-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb37-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_energy(var_trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/splines_hetero_files/splines_hetero_54_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb38"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb38-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb38-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.rhat(var_trace).&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;svg style="position: absolute; width: 0; height: 0; overflow: hidden"&gt;
&lt;defs&gt; &lt;symbol id="icon-database" viewbox="0 0 32 32"&gt; &lt;path d="M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z"&gt;&lt;/path&gt; &lt;path d="M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;path d="M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;symbol id="icon-file-text2" viewbox="0 0 32 32"&gt; &lt;path d="M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z"&gt;&lt;/path&gt; &lt;path d="M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;/defs&gt;
&lt;/svg&gt;
&lt;style&gt;/* CSS stylesheet for displaying xarray objects in jupyterlab.
 *
 */

:root {
  --xr-font-color0: var(--jp-content-font-color0, rgba(0, 0, 0, 1));
  --xr-font-color2: var(--jp-content-font-color2, rgba(0, 0, 0, 0.54));
  --xr-font-color3: var(--jp-content-font-color3, rgba(0, 0, 0, 0.38));
  --xr-border-color: var(--jp-border-color2, #e0e0e0);
  --xr-disabled-color: var(--jp-layout-color3, #bdbdbd);
  --xr-background-color: var(--jp-layout-color0, white);
  --xr-background-color-row-even: var(--jp-layout-color1, white);
  --xr-background-color-row-odd: var(--jp-layout-color2, #eeeeee);
}

html[theme=dark],
body.vscode-dark {
  --xr-font-color0: rgba(255, 255, 255, 1);
  --xr-font-color2: rgba(255, 255, 255, 0.54);
  --xr-font-color3: rgba(255, 255, 255, 0.38);
  --xr-border-color: #1F1F1F;
  --xr-disabled-color: #515151;
  --xr-background-color: #111111;
  --xr-background-color-row-even: #111111;
  --xr-background-color-row-odd: #313131;
}

.xr-wrap {
  display: block;
  min-width: 300px;
  max-width: 700px;
}

.xr-text-repr-fallback {
  /* fallback to plain text repr when CSS is not injected (untrusted notebook) */
  display: none;
}

.xr-header {
  padding-top: 6px;
  padding-bottom: 6px;
  margin-bottom: 4px;
  border-bottom: solid 1px var(--xr-border-color);
}

.xr-header &gt; div,
.xr-header &gt; ul {
  display: inline;
  margin-top: 0;
  margin-bottom: 0;
}

.xr-obj-type,
.xr-array-name {
  margin-left: 2px;
  margin-right: 10px;
}

.xr-obj-type {
  color: var(--xr-font-color2);
}

.xr-sections {
  padding-left: 0 !important;
  display: grid;
  grid-template-columns: 150px auto auto 1fr 20px 20px;
}

.xr-section-item {
  display: contents;
}

.xr-section-item input {
  display: none;
}

.xr-section-item input + label {
  color: var(--xr-disabled-color);
}

.xr-section-item input:enabled + label {
  cursor: pointer;
  color: var(--xr-font-color2);
}

.xr-section-item input:enabled + label:hover {
  color: var(--xr-font-color0);
}

.xr-section-summary {
  grid-column: 1;
  color: var(--xr-font-color2);
  font-weight: 500;
}

.xr-section-summary &gt; span {
  display: inline-block;
  padding-left: 0.5em;
}

.xr-section-summary-in:disabled + label {
  color: var(--xr-font-color2);
}

.xr-section-summary-in + label:before {
  display: inline-block;
  content: '►';
  font-size: 11px;
  width: 15px;
  text-align: center;
}

.xr-section-summary-in:disabled + label:before {
  color: var(--xr-disabled-color);
}

.xr-section-summary-in:checked + label:before {
  content: '▼';
}

.xr-section-summary-in:checked + label &gt; span {
  display: none;
}

.xr-section-summary,
.xr-section-inline-details {
  padding-top: 4px;
  padding-bottom: 4px;
}

.xr-section-inline-details {
  grid-column: 2 / -1;
}

.xr-section-details {
  display: none;
  grid-column: 1 / -1;
  margin-bottom: 5px;
}

.xr-section-summary-in:checked ~ .xr-section-details {
  display: contents;
}

.xr-array-wrap {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 20px auto;
}

.xr-array-wrap &gt; label {
  grid-column: 1;
  vertical-align: top;
}

.xr-preview {
  color: var(--xr-font-color3);
}

.xr-array-preview,
.xr-array-data {
  padding: 0 5px !important;
  grid-column: 2;
}

.xr-array-data,
.xr-array-in:checked ~ .xr-array-preview {
  display: none;
}

.xr-array-in:checked ~ .xr-array-data,
.xr-array-preview {
  display: inline-block;
}

.xr-dim-list {
  display: inline-block !important;
  list-style: none;
  padding: 0 !important;
  margin: 0;
}

.xr-dim-list li {
  display: inline-block;
  padding: 0;
  margin: 0;
}

.xr-dim-list:before {
  content: '(';
}

.xr-dim-list:after {
  content: ')';
}

.xr-dim-list li:not(:last-child):after {
  content: ',';
  padding-right: 5px;
}

.xr-has-index {
  font-weight: bold;
}

.xr-var-list,
.xr-var-item {
  display: contents;
}

.xr-var-item &gt; div,
.xr-var-item label,
.xr-var-item &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-even);
  margin-bottom: 0;
}

.xr-var-item &gt; .xr-var-name:hover span {
  padding-right: 5px;
}

.xr-var-list &gt; li:nth-child(odd) &gt; div,
.xr-var-list &gt; li:nth-child(odd) &gt; label,
.xr-var-list &gt; li:nth-child(odd) &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-odd);
}

.xr-var-name {
  grid-column: 1;
}

.xr-var-dims {
  grid-column: 2;
}

.xr-var-dtype {
  grid-column: 3;
  text-align: right;
  color: var(--xr-font-color2);
}

.xr-var-preview {
  grid-column: 4;
}

.xr-var-name,
.xr-var-dims,
.xr-var-dtype,
.xr-preview,
.xr-attrs dt {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 10px;
}

.xr-var-name:hover,
.xr-var-dims:hover,
.xr-var-dtype:hover,
.xr-attrs dt:hover {
  overflow: visible;
  width: auto;
  z-index: 1;
}

.xr-var-attrs,
.xr-var-data {
  display: none;
  background-color: var(--xr-background-color) !important;
  padding-bottom: 5px !important;
}

.xr-var-attrs-in:checked ~ .xr-var-attrs,
.xr-var-data-in:checked ~ .xr-var-data {
  display: block;
}

.xr-var-data &gt; table {
  float: right;
}

.xr-var-name span,
.xr-var-data,
.xr-attrs {
  padding-left: 25px !important;
}

.xr-attrs,
.xr-var-attrs,
.xr-var-data {
  grid-column: 1 / -1;
}

dl.xr-attrs {
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 125px auto;
}

.xr-attrs dt,
.xr-attrs dd {
  padding: 0;
  margin: 0;
  float: left;
  padding-right: 10px;
  width: auto;
}

.xr-attrs dt {
  font-weight: normal;
  grid-column: 1;
}

.xr-attrs dt:hover span {
  display: inline-block;
  background: var(--xr-background-color);
  padding-right: 10px;
}

.xr-attrs dd {
  grid-column: 2;
  white-space: pre-wrap;
  word-break: break-all;
}

.xr-icon-database,
.xr-icon-file-text2 {
  display: inline-block;
  vertical-align: middle;
  width: 1em;
  height: 1.5em !important;
  stroke-width: 0;
  stroke: currentColor;
  fill: currentColor;
}
&lt;/style&gt;
&lt;pre class="xr-text-repr-fallback"&gt;&amp;lt;xarray.Dataset&amp;gt;
Dimensions:  ()
Data variables:
    β0       float64 0.9998
    Δ_β      float64 1.006
    σ_β      float64 1.0
    γ0       float64 1.001
    Δ_γ      float64 1.005
    σ_γ      float64 1.0
    β        float64 1.002
    γ        float64 1.002&lt;/pre&gt;
&lt;div class="xr-wrap" hidden=""&gt;
&lt;div class="xr-header"&gt;
&lt;div class="xr-obj-type"&gt;
xarray.Dataset
&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="xr-sections"&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-7362aa37-9f8a-4802-b82c-c036e0ce48e8" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-7362aa37-9f8a-4802-b82c-c036e0ce48e8" class="xr-section-summary" title="Expand/collapse section"&gt;Dimensions:&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-0c5a2fdc-6a32-4688-af4c-eb27e082d3d5" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-0c5a2fdc-6a32-4688-af4c-eb27e082d3d5" class="xr-section-summary" title="Expand/collapse section"&gt;Coordinates: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-b29bc7b8-3e4e-4279-aac8-20d38dd7d09c" class="xr-section-summary-in" type="checkbox" checked&gt;&lt;label for="section-b29bc7b8-3e4e-4279-aac8-20d38dd7d09c" class="xr-section-summary"&gt;Data variables: &lt;span&gt;(8)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;β0&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
0.9998
&lt;/div&gt;
&lt;input id="attrs-1f5170ce-ccfc-4311-8246-d9e627ab323e" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-1f5170ce-ccfc-4311-8246-d9e627ab323e" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-cd3e8eda-7d32-4aad-83e5-9d277c2f3e56" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-cd3e8eda-7d32-4aad-83e5-9d277c2f3e56" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(0.99984598)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;Δ_β&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.006
&lt;/div&gt;
&lt;input id="attrs-089a661f-4ba0-464e-97a8-dc623d98dca7" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-089a661f-4ba0-464e-97a8-dc623d98dca7" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-9e4f120d-d01c-4a49-b8fb-3ae5672f9b45" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-9e4f120d-d01c-4a49-b8fb-3ae5672f9b45" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00613202)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;σ_β&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.0
&lt;/div&gt;
&lt;input id="attrs-551b992b-dfb9-4dc0-9da0-480350993952" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-551b992b-dfb9-4dc0-9da0-480350993952" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-4149d6bf-ce6e-4073-bcdd-806b4ccd5069" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-4149d6bf-ce6e-4073-bcdd-806b4ccd5069" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00047073)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;γ0&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.001
&lt;/div&gt;
&lt;input id="attrs-12f3c607-8ac1-4f55-ac6e-407119acf580" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-12f3c607-8ac1-4f55-ac6e-407119acf580" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-38f8b3df-a0d6-45cf-ba57-2bca9b92d994" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-38f8b3df-a0d6-45cf-ba57-2bca9b92d994" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.0010354)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;Δ_γ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.005
&lt;/div&gt;
&lt;input id="attrs-790917a7-b6d6-4286-9eb9-f0e8100d6d30" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-790917a7-b6d6-4286-9eb9-f0e8100d6d30" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-f01e1c18-b63b-40ad-825c-bfcf0e39f3a3" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-f01e1c18-b63b-40ad-825c-bfcf0e39f3a3" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00481044)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;σ_γ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.0
&lt;/div&gt;
&lt;input id="attrs-d4e97dad-29e0-4a7a-baf7-9f4eeb46dc58" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-d4e97dad-29e0-4a7a-baf7-9f4eeb46dc58" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-1afcb5f6-1ba2-481e-b828-aae93a973229" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-1afcb5f6-1ba2-481e-b828-aae93a973229" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00035778)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;β&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.002
&lt;/div&gt;
&lt;input id="attrs-4c219615-905a-408d-9278-74f6bcce7310" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-4c219615-905a-408d-9278-74f6bcce7310" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-21ad6f14-44b1-40af-9a70-a205599bf077" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-21ad6f14-44b1-40af-9a70-a205599bf077" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00226144)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;γ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.002
&lt;/div&gt;
&lt;input id="attrs-8c961902-eca0-4928-8bd5-1f83664db8a4" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-8c961902-eca0-4928-8bd5-1f83664db8a4" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-26417bc1-f4bb-47f5-b133-2661c4174d78" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-26417bc1-f4bb-47f5-b133-2661c4174d78" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00190525)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-ec411289-4373-47ec-93b8-5f529dd60452" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-ec411289-4373-47ec-93b8-5f529dd60452" class="xr-section-summary" title="Expand/collapse section"&gt;Attributes: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We do see that the values of &lt;span class="math inline"&gt;\(\gamma_j\)&lt;/span&gt; that correspond to small values of &lt;code&gt;range&lt;/code&gt; have small coefficients, and the coefficients grow as &lt;code&gt;range&lt;/code&gt; gets larger.&lt;/p&gt;
&lt;div class="sourceCode" id="cb39"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb39-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb39-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax, &lt;span class="op"&gt;=&lt;/span&gt; az.plot_forest(var_trace, var_names&lt;span class="op"&gt;=&lt;/span&gt;[&lt;span class="st"&gt;"γ"&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb39-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb39-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb39-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb39-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="vs"&gt;r"$\gamma_j$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb39-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb39-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb39-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb39-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yticklabels(np.arange(N_KNOT)[::&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb39-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb39-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"$j$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/splines_hetero_files/splines_hetero_57_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Again we sample from the posterior predictive distribution of this model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb40"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb40-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb40-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;dmat.set_value(basis(pp_range))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb41"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb41-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb41-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; var_model:&lt;/span&gt;
&lt;span id="cb41-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb41-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    pp_var_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample_posterior_predictive(var_trace)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="3000" class max="3000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [3000/3000 00:00&amp;lt;00:00]&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;We plot these predictions in order to compare them to those of the homoskedastic model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb42"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb42-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, (std_ax, joint_ax) &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(&lt;/span&gt;
&lt;span id="cb42-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    nrows&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb42-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    gridspec_kw&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;'height_ratios'&lt;/span&gt;: [&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;4&lt;/span&gt;]}&lt;/span&gt;
&lt;span id="cb42-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb42-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;low, high &lt;span class="op"&gt;=&lt;/span&gt; np.percentile(pp_var_trace[&lt;span class="st"&gt;"obs"&lt;/span&gt;], [&lt;span class="fl"&gt;2.5&lt;/span&gt;, &lt;span class="fl"&gt;97.5&lt;/span&gt;], axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb42-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;joint_ax.fill_between(pp_range, low, high,&lt;/span&gt;
&lt;span id="cb42-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.25&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb42-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"95&lt;/span&gt;&lt;span class="sc"&gt;% c&lt;/span&gt;&lt;span class="st"&gt;redible interval"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"range"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"logratio"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;std_df,&lt;/span&gt;
&lt;span id="cb42-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;joint_ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(std_df.groupby(std_df[&lt;span class="st"&gt;"range"&lt;/span&gt;].&lt;span class="bu"&gt;round&lt;/span&gt;(&lt;span class="dv"&gt;1&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb42-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       [&lt;span class="st"&gt;"logratio"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb42-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .std()&lt;/span&gt;
&lt;span id="cb42-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .rolling(&lt;span class="dv"&gt;5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb42-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .mean()&lt;/span&gt;
&lt;span id="cb42-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .plot(ax&lt;span class="op"&gt;=&lt;/span&gt;std_ax, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Actual"&lt;/span&gt;))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_ax.plot(pp_range, pp_trace[&lt;span class="st"&gt;"obs"&lt;/span&gt;].std(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb42-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Posterior predictive&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;(homoskedastic)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_ax.plot(pp_range, pp_var_trace[&lt;span class="st"&gt;"obs"&lt;/span&gt;].std(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb42-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'r'&lt;/span&gt;, ls&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'--'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb42-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Posterior predictive&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;(heteroskedastic)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-26"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-27"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;joint_ax.plot(pp_range, pp_trace[&lt;span class="st"&gt;"obs"&lt;/span&gt;].mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb42-28"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Posterior predictive&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;(homoskedastic)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-29"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;joint_ax.plot(pp_range, pp_var_trace[&lt;span class="st"&gt;"obs"&lt;/span&gt;].mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb42-30"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'r'&lt;/span&gt;, ls&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'--'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb42-31"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Posterior predictive&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;(heteroskedastic)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-32"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-33"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_ax.set_ylabel(&lt;span class="st"&gt;"Standard&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;deviation&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;(binned)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-34"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-35"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'upper left'&lt;/span&gt;, ncol&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;3&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb42-36"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              bbox_to_anchor&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;1.6&lt;/span&gt;))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-37"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;joint_ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'lower left'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-38"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb42-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/splines_hetero_files/splines_hetero_62_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that the homo- and heteroskedastic models produce essentially the same estimate of the expected value of &lt;code&gt;logratio&lt;/code&gt;, but that the heteroskedastic model comes closer to capturing the true change in the variance.&lt;/p&gt;
&lt;p&gt;We now compare these two models using &lt;a href="https://arxiv.org/abs/1507.04544"&gt;Pareto-smoothed importance sampling leave-one-out cross-validation&lt;/a&gt; (PSIS-LOO).&lt;/p&gt;
&lt;div class="sourceCode" id="cb43"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb43-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb43-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;traces &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb43-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb43-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'Homoskedastic'&lt;/span&gt;: trace,&lt;/span&gt;
&lt;span id="cb43-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb43-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'Heteroskedastic'&lt;/span&gt;: var_trace&lt;/span&gt;
&lt;span id="cb43-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb43-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb44"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb44-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb44-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;comp_df &lt;span class="op"&gt;=&lt;/span&gt; az.compare(traces)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb45"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb45-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb45-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;comp_df.loc[:, :&lt;span class="st"&gt;"weight"&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
rank
&lt;/th&gt;
&lt;th&gt;
loo
&lt;/th&gt;
&lt;th&gt;
p_loo
&lt;/th&gt;
&lt;th&gt;
d_loo
&lt;/th&gt;
&lt;th&gt;
weight
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
Heteroskedastic
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
41.369658
&lt;/td&gt;
&lt;td&gt;
17.759399
&lt;/td&gt;
&lt;td&gt;
0.000000
&lt;/td&gt;
&lt;td&gt;
1.000000e+00
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Homoskedastic
&lt;/th&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
-41.703944
&lt;/td&gt;
&lt;td&gt;
14.188435
&lt;/td&gt;
&lt;td&gt;
83.073602
&lt;/td&gt;
&lt;td&gt;
8.058976e-11
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb46"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb46-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb46-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots()&lt;/span&gt;
&lt;span id="cb46-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb46-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb46-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-11-splines-hetero.html#cb46-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_compare(comp_df, plot_ic_diff&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/splines_hetero_files/splines_hetero_67_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Interestingly, the PSIS-LOO score for the heteroskedastic model is significantly higher than that of the homoskedastic model, even though these two models predict essentially the same conditional mean.&lt;/p&gt;
&lt;p&gt;This post is available as a Jupyter notebook &lt;a href="https://nbviewer.jupyter.org/gist/AustinRochford/2b7a0f79457dc6b593309db433ecbedd"&gt;here&lt;/a&gt;.&lt;/p&gt;</description><category>Bayesian Statistics</category><category>PyMC3</category><category>Python</category><category>Splines</category><guid>https://austinrochford.com/posts/2021-08-11-splines-hetero.html</guid><pubDate>Wed, 11 Aug 2021 04:00:00 GMT</pubDate></item><item><title>A Bayesian Alternative to Synthetic Control Comparative Case Studies in Python with PyMC3</title><link>https://austinrochford.com/posts/2021-08-08-basc-ccs.html</link><dc:creator>Austin Rochford</dc:creator><description>&lt;p&gt;Recently I had cause to be perusing &lt;a href="https://yiqingxu.org/research/"&gt;Yiqing Xu’s research&lt;/a&gt; and dove deep into the 2020 paper &lt;em&gt;A Bayesian Alternative to Synthetic Control for Comparative Case Studies&lt;/em&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; (BASC-CCS from now on). In an effort to better understand the method introduced in this paper, I decided to replicate (most of) the results form the simulation study described in Sections 4.1 and A.4.1 in Python using PyMC3.&lt;/p&gt;
&lt;p&gt;BASC-CCS uses &lt;a href="https://en.wikipedia.org/wiki/Cross-sectional_data"&gt;time series cross sectional data&lt;/a&gt; (TSCS) to infer causal effects from observational data where direct control of the treatment mechanism is not possible. As such it falls under the umbrella of &lt;a href="https://en.wikipedia.org/wiki/Causal_inference"&gt;causal inference methods&lt;/a&gt;. More specifically, it uses the Bayesian approach that treats causal inference from observational data as a problem of imputing missing (control) data for treated units.&lt;/p&gt;
&lt;h2 id="generate-the-data"&gt;Generate the Data&lt;/h2&gt;
&lt;p&gt;We begin by generating the data to be modeled. First we make the necessary Python imports and do some light housekeeping.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb1-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;matplotlib inline&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb2-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; warnings &lt;span class="im"&gt;import&lt;/span&gt; filterwarnings&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb3-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; aesara &lt;span class="im"&gt;import&lt;/span&gt; tensor &lt;span class="im"&gt;as&lt;/span&gt; at&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; arviz &lt;span class="im"&gt;as&lt;/span&gt; az&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; matplotlib &lt;span class="im"&gt;as&lt;/span&gt; mpl&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib &lt;span class="im"&gt;import&lt;/span&gt; pyplot &lt;span class="im"&gt;as&lt;/span&gt; plt&lt;/span&gt;
&lt;span id="cb3-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb3-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib.lines &lt;span class="im"&gt;import&lt;/span&gt; Line2D&lt;/span&gt;
&lt;span id="cb3-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb3-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; numpy &lt;span class="im"&gt;as&lt;/span&gt; np&lt;/span&gt;
&lt;span id="cb3-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb3-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pymc3 &lt;span class="im"&gt;as&lt;/span&gt; pm&lt;/span&gt;
&lt;span id="cb3-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb3-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; scipy &lt;span class="im"&gt;as&lt;/span&gt; sp&lt;/span&gt;
&lt;span id="cb3-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb3-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; seaborn &lt;span class="im"&gt;as&lt;/span&gt; sns&lt;/span&gt;
&lt;span id="cb3-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb3-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; xarray &lt;span class="im"&gt;as&lt;/span&gt; xr&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;You are running the v4 development version of PyMC3 which currently still lacks key features. You probably want to use the stable v3 instead which you can either install via conda or find on the v3 GitHub branch: https://github.com/pymc-devs/pymc3/tree/v3&lt;/code&gt;&lt;/pre&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb5-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;filterwarnings(&lt;span class="st"&gt;'ignore'&lt;/span&gt;, category&lt;span class="op"&gt;=&lt;/span&gt;pm.ImputationWarning, module&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'pymc3'&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb6-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;mpl.rcParams[&lt;span class="st"&gt;'figure.figsize'&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb6-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb6-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.&lt;span class="bu"&gt;set&lt;/span&gt;(color_codes&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;BASC-CCS is designed for TSCS where a number of units are observed over a period of time. Following the BASC-CCS paper, we simulate data from &lt;span class="math inline"&gt;\(N = 50\)&lt;/span&gt; units over &lt;span class="math inline"&gt;\(T = 30\)&lt;/span&gt; time periods.&lt;/p&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb7-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb7-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;N &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;50&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb7-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;T &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;30&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb7-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb7-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb7-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;t &lt;span class="op"&gt;=&lt;/span&gt; np.arange(T)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this simulation 10% of the units will be treated starting at time &lt;span class="math inline"&gt;\(T_{\mathrm{treat}} = 21\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb8-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;T_treat &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;21&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb8-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;P_treat &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="fl"&gt;0.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Which units are treated will be determined by a linear combination of two unobserved latent factors, drawn from a standard normal distribution for each unit, &lt;span class="math inline"&gt;\(\Gamma_{i, 1}, \Gamma_{i, 2} \sim N(0, 1)\)&lt;/span&gt; (note that we use capital letters for simulated quantities and the corresponding lowercase letters for the corresponding inferred parameters).&lt;/p&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb9-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SEED &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;12345&lt;/span&gt; &lt;span class="co"&gt;# for reproducibility&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb9-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb9-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb9-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;rng &lt;span class="op"&gt;=&lt;/span&gt; np.random.default_rng(SEED)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb10"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb10-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb10-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Γ &lt;span class="op"&gt;=&lt;/span&gt; rng.normal(size&lt;span class="op"&gt;=&lt;/span&gt;(N, &lt;span class="dv"&gt;2&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Treatment is determined according to the variable&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[\mathrm{tr}_i = 0.7 \cdot \Gamma_{i, 1} + 0.3 \cdot \Gamma_{i, 2} + \varepsilon^{\Gamma}_i,\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;where &lt;span class="math inline"&gt;\(\varepsilon^{\Gamma}_i \sim N(0, 0.25).\)&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb11"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb11-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb11-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;tr &lt;span class="op"&gt;=&lt;/span&gt; Γ.dot([&lt;span class="fl"&gt;0.7&lt;/span&gt;, &lt;span class="fl"&gt;0.3&lt;/span&gt;]) &lt;span class="op"&gt;+&lt;/span&gt; rng.normal(&lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;0.5&lt;/span&gt;, size&lt;span class="op"&gt;=&lt;/span&gt;N)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The five units with the largest values of &lt;span class="math inline"&gt;\(tr_i\)&lt;/span&gt; are treated.&lt;/p&gt;
&lt;div class="sourceCode" id="cb12"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb12-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb12-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;treat_crit &lt;span class="op"&gt;=&lt;/span&gt; np.percentile(tr, &lt;span class="dv"&gt;100&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; (&lt;span class="fl"&gt;1.&lt;/span&gt; &lt;span class="op"&gt;-&lt;/span&gt; P_treat))&lt;/span&gt;
&lt;span id="cb12-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb12-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;treated &lt;span class="op"&gt;=&lt;/span&gt; tr &lt;span class="op"&gt;&amp;gt;&lt;/span&gt; treat_crit&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb13"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb13-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb13-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_treated &lt;span class="op"&gt;=&lt;/span&gt; treated.&lt;span class="bu"&gt;sum&lt;/span&gt;()&lt;/span&gt;
&lt;span id="cb13-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb13-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb13-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_treated&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;5&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following plot shows the relationship between the latent values &lt;span class="math inline"&gt;\(\Gamma_i\)&lt;/span&gt; and which units are treated.&lt;/p&gt;
&lt;div class="sourceCode" id="cb15"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb15-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb15-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;CMAP &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="st"&gt;'winter'&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb16"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb16-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;8&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb16-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_aspect(&lt;span class="st"&gt;'equal'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb16-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb16-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;norm &lt;span class="op"&gt;=&lt;/span&gt; plt.Normalize(tr.&lt;span class="bu"&gt;min&lt;/span&gt;(), tr.&lt;span class="bu"&gt;max&lt;/span&gt;())&lt;/span&gt;
&lt;span id="cb16-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;Γ[&lt;span class="op"&gt;~&lt;/span&gt;treated, &lt;span class="dv"&gt;0&lt;/span&gt;], y&lt;span class="op"&gt;=&lt;/span&gt;Γ[&lt;span class="op"&gt;~&lt;/span&gt;treated, &lt;span class="dv"&gt;1&lt;/span&gt;], hue&lt;span class="op"&gt;=&lt;/span&gt;tr[&lt;span class="op"&gt;~&lt;/span&gt;treated],&lt;/span&gt;
&lt;span id="cb16-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                hue_norm&lt;span class="op"&gt;=&lt;/span&gt;norm, palette&lt;span class="op"&gt;=&lt;/span&gt;CMAP,&lt;/span&gt;
&lt;span id="cb16-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Untreated"&lt;/span&gt;, legend&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb16-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;Γ[treated, &lt;span class="dv"&gt;0&lt;/span&gt;], y&lt;span class="op"&gt;=&lt;/span&gt;Γ[treated, &lt;span class="dv"&gt;1&lt;/span&gt;], hue&lt;span class="op"&gt;=&lt;/span&gt;tr[treated],&lt;/span&gt;
&lt;span id="cb16-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                s&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;100&lt;/span&gt;, marker&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'s'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb16-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                hue_norm&lt;span class="op"&gt;=&lt;/span&gt;norm, palette&lt;span class="op"&gt;=&lt;/span&gt;CMAP,&lt;/span&gt;
&lt;span id="cb16-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Treated"&lt;/span&gt;, legend&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb16-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb16-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Γ_mult &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="fl"&gt;1.05&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Γ_min, Γ_max &lt;span class="op"&gt;=&lt;/span&gt; Γ_mult &lt;span class="op"&gt;*&lt;/span&gt; Γ.&lt;span class="bu"&gt;min&lt;/span&gt;(), Γ_mult &lt;span class="op"&gt;*&lt;/span&gt; Γ.&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;
&lt;span id="cb16-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_Γ &lt;span class="op"&gt;=&lt;/span&gt; np.linspace(Γ_min, Γ_max, &lt;span class="dv"&gt;100&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb16-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb16-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot(plot_Γ, (treat_crit &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="fl"&gt;0.7&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; plot_Γ) &lt;span class="op"&gt;/&lt;/span&gt; &lt;span class="fl"&gt;0.3&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb16-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, ls&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'--'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Treatment threshold&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;(noiseless)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb16-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sm &lt;span class="op"&gt;=&lt;/span&gt; plt.cm.ScalarMappable(norm&lt;span class="op"&gt;=&lt;/span&gt;norm, cmap&lt;span class="op"&gt;=&lt;/span&gt;CMAP)&lt;/span&gt;
&lt;span id="cb16-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;cbar &lt;span class="op"&gt;=&lt;/span&gt; fig.colorbar(sm)&lt;/span&gt;
&lt;span id="cb16-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb16-26"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlim(Γ_min, Γ_max)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-27"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="vs"&gt;r"$\Gamma_{i, 1}$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-28"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb16-29"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylim(Γ_min, Γ_max)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-30"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="vs"&gt;r"$\Gamma_{i, 2}$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-31"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb16-32"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;cbar.set_label(&lt;span class="vs"&gt;r"$\mathrm&lt;/span&gt;&lt;span class="sc"&gt;{tr}&lt;/span&gt;&lt;span class="vs"&gt;_i$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-33"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb16-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'upper left'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/basc-ccs_files/basc-ccs_22_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The inclusion of the noise term &lt;span class="math inline"&gt;\(\varepsilon^{\Gamma}_i\)&lt;/span&gt; causes some of the treated units to be below the treatment threshold line in this plot and some of the points above the treatment threshold line to not be treated.&lt;/p&gt;
&lt;p&gt;We now generate &lt;span class="math inline"&gt;\(K = 10\)&lt;/span&gt; covariates for each unit, one of which is a constant intercept and the rest of which follow a standard normal distribution.&lt;/p&gt;
&lt;div class="sourceCode" id="cb17"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb17-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb17-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;K &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;10&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb18"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb18-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb18-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;X &lt;span class="op"&gt;=&lt;/span&gt; np.empty((N, K))&lt;/span&gt;
&lt;span id="cb18-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb18-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;X[:, &lt;span class="dv"&gt;0&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="fl"&gt;1.&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb18-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;X[:, &lt;span class="dv"&gt;1&lt;/span&gt;:] &lt;span class="op"&gt;=&lt;/span&gt; rng.normal(size&lt;span class="op"&gt;=&lt;/span&gt;(N, K &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Following the paper, the first &lt;span class="math inline"&gt;\(K_* = 4\)&lt;/span&gt; covariates influence the outcome, and the rest are uncorrelated with it. The true regression coefficients, &lt;span class="math inline"&gt;\(B_j\)&lt;/span&gt; are taken from the BASC-CCS paper.&lt;/p&gt;
&lt;div class="sourceCode" id="cb19"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb19-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb19-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;K_star &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb20"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb20-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb20-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;B &lt;span class="op"&gt;=&lt;/span&gt; np.zeros(K)&lt;/span&gt;
&lt;span id="cb20-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb20-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;B[:K_star] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="fl"&gt;3.&lt;/span&gt;, &lt;span class="fl"&gt;6.&lt;/span&gt;, &lt;span class="fl"&gt;4.&lt;/span&gt;, &lt;span class="fl"&gt;2.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The influence of each of the first &lt;span class="math inline"&gt;\(K_*\)&lt;/span&gt; covariates varies by unit, according to &lt;span class="math inline"&gt;\(A_{i, j} \sim N\left(0, \left(\frac{B_j}{2}\right)^2\right)\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb21"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb21-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb21-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;A &lt;span class="op"&gt;=&lt;/span&gt; np.zeros((N, K))&lt;/span&gt;
&lt;span id="cb21-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb21-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;A[:, :K_star] &lt;span class="op"&gt;=&lt;/span&gt; rng.normal(&lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;0.5&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; B[:K_star], size&lt;span class="op"&gt;=&lt;/span&gt;(N, K_star))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The influence of these first &lt;span class="math inline"&gt;\(K_*\)&lt;/span&gt; covariates also varies over time according to an &lt;span class="math inline"&gt;\(AR(1)\)&lt;/span&gt; process &lt;span class="math inline"&gt;\(\Xi_{j, t}\)&lt;/span&gt; with autocorrelation of &lt;span class="math inline"&gt;\(0.6\)&lt;/span&gt; and standard normal innovations.&lt;/p&gt;
&lt;div class="sourceCode" id="cb22"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb22-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb22-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; ar1(k, innov):&lt;/span&gt;
&lt;span id="cb22-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb22-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    t &lt;span class="op"&gt;=&lt;/span&gt; np.arange(innov.shape[&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb22-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb22-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    expon &lt;span class="op"&gt;=&lt;/span&gt; sp.linalg.toeplitz(t)&lt;/span&gt;
&lt;span id="cb22-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb22-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb22-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb22-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; np.dot(innov, np.triu(np.power(k, expon)))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb23"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb23-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb23-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;innov_Ξ &lt;span class="op"&gt;=&lt;/span&gt; rng.normal(size&lt;span class="op"&gt;=&lt;/span&gt;(K_star, T))&lt;/span&gt;
&lt;span id="cb23-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb23-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb23-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb23-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Ξ &lt;span class="op"&gt;=&lt;/span&gt; np.zeros((K, T))&lt;/span&gt;
&lt;span id="cb23-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb23-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Ξ[:K_star] &lt;span class="op"&gt;=&lt;/span&gt; ar1(&lt;span class="fl"&gt;0.6&lt;/span&gt;, innov_Ξ)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb24"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb24-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb24-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb24-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb24-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb24-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb24-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot(t, Ξ.T, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.75&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb24-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb24-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb24-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"$t$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb24-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="vs"&gt;r"$\Xi_{i, t}$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/basc-ccs_files/basc-ccs_34_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The horizontal lines at zero here correspond to the &lt;span class="math inline"&gt;\(K - K_*\)&lt;/span&gt; covariates that have no influence on the outcome and do not vary over time.&lt;/p&gt;
&lt;p&gt;The noise in outcomes is related to the latent parameters &lt;span class="math inline"&gt;\(\Gamma_i\)&lt;/span&gt; through factor loadings &lt;span class="math inline"&gt;\(F_t\)&lt;/span&gt;, which also follow an &lt;span class="math inline"&gt;\(AR(1)\)&lt;/span&gt; process with autocorrelation of &lt;span class="math inline"&gt;\(0.7\)&lt;/span&gt; and standard normal innovations.&lt;/p&gt;
&lt;div class="sourceCode" id="cb25"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb25-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb25-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;innov_F &lt;span class="op"&gt;=&lt;/span&gt; rng.normal(size&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;2&lt;/span&gt;, T))&lt;/span&gt;
&lt;span id="cb25-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb25-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb25-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb25-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;F &lt;span class="op"&gt;=&lt;/span&gt; ar1(&lt;span class="fl"&gt;0.7&lt;/span&gt;, innov_F)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb26"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb26-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb26-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb26-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb26-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb26-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb26-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot(t, F.T, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.75&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb26-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb26-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb26-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb26-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"$t$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb26-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb26-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="vs"&gt;r"$F_{i, t}$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/basc-ccs_files/basc-ccs_37_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Finally, we simulate the treament effects, which are&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\Delta_{i, t} =
    \begin{cases}
        t - T_{\mathrm{treat}} + \varepsilon^{\mathrm{treat}}_{i, t} &amp;amp; \mathrm{if}\ t &amp;gt; T_{\mathrm{treat}} \\
        0 &amp;amp; \mathrm{if}\ t \leq T_{\mathrm{treat}}
    \end{cases}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;where &lt;span class="math inline"&gt;\(\varepsilon^{\mathrm{treat}}_{i, t} \sim N(0, 0.25)\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb27"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb27-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb27-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Δ &lt;span class="op"&gt;=&lt;/span&gt; np.zeros((N, T))&lt;/span&gt;
&lt;span id="cb27-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb27-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Δ[:, T_treat:] &lt;span class="op"&gt;=&lt;/span&gt; t[T_treat:] &lt;span class="op"&gt;-&lt;/span&gt; T_treat &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb27-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb27-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    &lt;span class="op"&gt;+&lt;/span&gt; rng.normal(&lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;0.5&lt;/span&gt;, size&lt;span class="op"&gt;=&lt;/span&gt;(N, T &lt;span class="op"&gt;-&lt;/span&gt; T_treat))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The array &lt;code&gt;w&lt;/code&gt; indicates which units where treated at a given time, with&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
w_{i, t} =
    \begin{cases}
        1 &amp;amp; \mathrm{if\ unit}\ i\ \mathrm{is\ treated\ at\ time}\ t \\
        0 &amp;amp; \mathrm{otherwise}
    \end{cases}.
\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb28"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb28-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb28-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;w &lt;span class="op"&gt;=&lt;/span&gt; np.zeros((N, T))&lt;/span&gt;
&lt;span id="cb28-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb28-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;w[treated, T_treat:] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We plot the treatment effects that our model will attempt to recover.&lt;/p&gt;
&lt;div class="sourceCode" id="cb29"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb29-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb29-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb29-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb29-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb29-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot(t, (Δ &lt;span class="op"&gt;*&lt;/span&gt; w)[&lt;span class="op"&gt;~&lt;/span&gt;treated][&lt;span class="dv"&gt;0&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb29-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb29-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Untreated"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb29-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot(t, (Δ &lt;span class="op"&gt;*&lt;/span&gt; w)[treated][&lt;span class="dv"&gt;0&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb29-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb29-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'r'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.75&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb29-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb29-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Treated"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb29-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot(t, (Δ &lt;span class="op"&gt;*&lt;/span&gt; w)[treated][&lt;span class="dv"&gt;1&lt;/span&gt;:].T,&lt;/span&gt;
&lt;span id="cb29-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb29-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'r'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.75&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb29-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb29-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"$t$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb29-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="vs"&gt;r"$\Delta_{i, t} \cdot w_{i, t}$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb29-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'upper left'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/basc-ccs_files/basc-ccs_43_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We combine each of these components to generate the data to be modeled.&lt;/p&gt;
&lt;div class="sourceCode" id="cb30"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb30-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb30-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;Θ &lt;span class="op"&gt;=&lt;/span&gt; (B &lt;span class="op"&gt;+&lt;/span&gt; A)[..., np.newaxis] &lt;span class="op"&gt;+&lt;/span&gt; Ξ[np.newaxis]&lt;/span&gt;
&lt;span id="cb30-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb30-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;XΘ &lt;span class="op"&gt;=&lt;/span&gt; (X[..., np.newaxis] &lt;span class="op"&gt;*&lt;/span&gt; Θ).&lt;span class="bu"&gt;sum&lt;/span&gt;(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We combine the reatment effects, the effects of the covariates, the effects of the latent factors, and standard normal noise to get the observed outcomes, &lt;span class="math inline"&gt;\(y_{i, t}\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb31"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb31-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb31-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;y &lt;span class="op"&gt;=&lt;/span&gt; Δ &lt;span class="op"&gt;*&lt;/span&gt; w &lt;span class="op"&gt;+&lt;/span&gt; XΘ &lt;span class="op"&gt;+&lt;/span&gt; Γ.dot(F) &lt;span class="op"&gt;+&lt;/span&gt; rng.normal(size&lt;span class="op"&gt;=&lt;/span&gt;(N, T))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb32"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb32-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb32-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb32-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb32-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb32-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb32-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.axvline(T_treat, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, ls&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'--'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb32-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb32-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"$T_{\mathrm&lt;/span&gt;&lt;span class="sc"&gt;{treat}&lt;/span&gt;&lt;span class="st"&gt;}$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb32-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb32-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb32-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot(t, y[&lt;span class="op"&gt;~&lt;/span&gt;treated].T, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb32-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot([], [], c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb32-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb32-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Untreated"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb32-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb32-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb32-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot(t, y[treated].T, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'r'&lt;/span&gt;, lw&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;3&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.75&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb32-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot([], [], c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'r'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.75&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb32-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb32-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Treated"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb32-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb32-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb32-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"$t$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb32-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"$y_{i, t}$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb32-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"upper left"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/basc-ccs_files/basc-ccs_48_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that the treated units have outcomes that generally trend up after &lt;span class="math inline"&gt;\(T_{\mathrm{treat}}\)&lt;/span&gt;, but there is a lot of visual noise to interpret when comparing those to the untreated units. Thee BASC-CCS model w will build in the next section will help to quantify the difference and cut through this noise.&lt;/p&gt;
&lt;h2 id="modeling"&gt;Modeling&lt;/h2&gt;
&lt;h3 id="unidentified-latent-factors"&gt;Unidentified latent factors&lt;/h3&gt;
&lt;p&gt;We begin with a model that has &lt;a href="https://en.wikipedia.org/wiki/Identifiability#:~:text=In%20statistics%2C%20identifiability%20is%20a,number%20of%20observations%20from%20it."&gt;unidentified&lt;/a&gt; latent factors in order to determine which factors we should constrain to best identify our model. For more details about implementing factor analysis models in PyMC see my &lt;a href="https://austinrochford.com/posts/2021-07-05-factor-analysis-pymc3.html"&gt;previous post&lt;/a&gt; on the topic.&lt;/p&gt;
&lt;p&gt;Since we are using the Bayesian causal-inference-as-missing-data paradigm, we define the control observations as a &lt;a href="https://numpy.org/doc/stable/reference/maskedarray.html"&gt;masked array&lt;/a&gt;, with entries masked when &lt;span class="math inline"&gt;\(w_{i, t} = 1\)&lt;/span&gt;, indicating that the &lt;span class="math inline"&gt;\(i\)&lt;/span&gt;-th unit was treated at time &lt;span class="math inline"&gt;\(t\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb33"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb33-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb33-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;y_ctrl &lt;span class="op"&gt;=&lt;/span&gt; np.ma.array(y, mask&lt;span class="op"&gt;=&lt;/span&gt;w)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For simplicity our model will use two latent factors, even though in general we do not know the true number of latent factors. For a more rigorous discussion of how to choose the number of latent factors, see &lt;a href="https://probml.github.io/pml-book/"&gt;&lt;em&gt;Machine Learning, A Probabilistic Perspective&lt;/em&gt;&lt;/a&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;, §12.3.&lt;/p&gt;
&lt;div class="sourceCode" id="cb34"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb34-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb34-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;N_factor &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We define the coordinates for our parameters. (For more information on how to get PyMC3 to interact nicely with &lt;a href="http://xarray.pydata.org/en/stable/index.html"&gt;&lt;code&gt;xarray&lt;/code&gt;&lt;/a&gt; via coordinates, see Oriol Abril’s excellent &lt;a href="https://oriolabril.github.io/oriol_unraveled/python/arviz/pymc3/xarray/2020/09/22/pymc3-arviz.html"&gt;post&lt;/a&gt; on the subject.)&lt;/p&gt;
&lt;div class="sourceCode" id="cb35"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb35-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb35-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;coords &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb35-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb35-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"unit"&lt;/span&gt;: np.arange(N),                        &lt;span class="co"&gt;# units&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb35-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb35-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"fact"&lt;/span&gt;: np.arange(N_factor),                 &lt;span class="co"&gt;# latent factors&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb35-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb35-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"feat"&lt;/span&gt;: np.arange(K),                        &lt;span class="co"&gt;# features&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb35-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb35-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"time"&lt;/span&gt;: t,                                   &lt;span class="co"&gt;# time&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb35-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb35-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"time_block"&lt;/span&gt;: np.arange(T &lt;span class="op"&gt;-&lt;/span&gt; (N_factor &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;))  &lt;span class="co"&gt;# block of time for identifying factors&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb35-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb35-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We put centered normal priors on our shared regression coefficients, &lt;span class="math inline"&gt;\(\beta_j\)&lt;/span&gt;. This prior differs from the one in the paper, which uses a &lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html"&gt;sparse prior&lt;/a&gt; for these coefficients. Fortunately since we are using a modular probabilistic programming library, this prior can be changed relatively easily.&lt;/p&gt;
&lt;div class="sourceCode" id="cb36"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb36-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb36-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model(coords&lt;span class="op"&gt;=&lt;/span&gt;coords) &lt;span class="im"&gt;as&lt;/span&gt; ref_model:&lt;/span&gt;
&lt;span id="cb36-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb36-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"β"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt;, dims&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"feat"&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We put &lt;a href="https://twiecki.io/blog/2017/02/08/bayesian-hierchical-non-centered/"&gt;hierarchical normally distributed priors&lt;/a&gt; with mean zero (for identifiability) on the per-unit random effects &lt;span class="math inline"&gt;\(\alpha_{i, j}\)&lt;/span&gt; and the per-time random effects &lt;span class="math inline"&gt;\(\xi_{j, t}\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb37"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb37-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb37-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# the scale necessary to make a halfnormal distribution&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb37-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb37-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# have unit variance&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb37-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb37-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;HALFNORMAL_SCALE &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="fl"&gt;1.&lt;/span&gt; &lt;span class="op"&gt;/&lt;/span&gt; np.sqrt(&lt;span class="fl"&gt;1.&lt;/span&gt; &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="fl"&gt;2.&lt;/span&gt; &lt;span class="op"&gt;/&lt;/span&gt; np.pi)&lt;/span&gt;
&lt;span id="cb37-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb37-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb37-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb37-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; noncentered_normal(name, dims, μ&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;,):&lt;/span&gt;
&lt;span id="cb37-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb37-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; μ &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb37-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb37-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        μ &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="ss"&gt;f"μ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb37-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb37-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb37-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb37-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    Δ &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="ss"&gt;f"Δ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;1.&lt;/span&gt;, dims&lt;span class="op"&gt;=&lt;/span&gt;dims)&lt;/span&gt;
&lt;span id="cb37-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb37-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="ss"&gt;f"σ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; HALFNORMAL_SCALE)&lt;/span&gt;
&lt;span id="cb37-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb37-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb37-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb37-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; pm.Deterministic(name, μ &lt;span class="op"&gt;+&lt;/span&gt; Δ &lt;span class="op"&gt;*&lt;/span&gt; σ)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb38"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb38-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb38-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; ref_model:&lt;/span&gt;
&lt;span id="cb38-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb38-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    α &lt;span class="op"&gt;=&lt;/span&gt; noncentered_normal(&lt;span class="st"&gt;"α"&lt;/span&gt;, (&lt;span class="st"&gt;"unit"&lt;/span&gt;, &lt;span class="st"&gt;"feat"&lt;/span&gt;), μ&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb38-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb38-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ξ &lt;span class="op"&gt;=&lt;/span&gt; noncentered_normal(&lt;span class="st"&gt;"ξ"&lt;/span&gt;, (&lt;span class="st"&gt;"feat"&lt;/span&gt;, &lt;span class="st"&gt;"time"&lt;/span&gt;), μ&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that here we do not use the fact that the true values of &lt;span class="math inline"&gt;\(\Xi_{j, t}\)&lt;/span&gt; form an AR(1) process.&lt;/p&gt;
&lt;p&gt;We combine &lt;span class="math inline"&gt;\(\beta_j\)&lt;/span&gt;, &lt;span class="math inline"&gt;\(\alpha_{i, j}\)&lt;/span&gt;, and &lt;span class="math inline"&gt;\(\xi_{j, t}\)&lt;/span&gt; to form the full coefficient cube, &lt;span class="math inline"&gt;\(\theta_{i, j, t}\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb39"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb39-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb39-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;θ &lt;span class="op"&gt;=&lt;/span&gt; β[np.newaxis, :, np.newaxis] &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb39-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb39-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;+&lt;/span&gt; α[..., np.newaxis] &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb39-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb39-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;+&lt;/span&gt; ξ[np.newaxis, ...]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We build latent factor component of the model as in the previous post, knowing that this model specificiation is only identified up to reflections of &lt;code&gt;f_unid&lt;/code&gt; and &lt;code&gt;γ_unid&lt;/code&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb40"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb40-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb40-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; ref_model:&lt;/span&gt;
&lt;span id="cb40-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb40-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    f_pos_row &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"f_pos_row"&lt;/span&gt;, HALFNORMAL_SCALE,&lt;/span&gt;
&lt;span id="cb40-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb40-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                              dims&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"fact"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb40-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb40-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    f_block_unid &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"f_block_unid"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;1.&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb40-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb40-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                             dims&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="st"&gt;"time_block"&lt;/span&gt;, &lt;span class="st"&gt;"fact"&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb40-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb40-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    f_unid &lt;span class="op"&gt;=&lt;/span&gt; at.concatenate((&lt;/span&gt;
&lt;span id="cb40-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb40-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        at.eye(N_factor),&lt;/span&gt;
&lt;span id="cb40-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb40-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        at.shape_padleft(f_pos_row),&lt;/span&gt;
&lt;span id="cb40-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb40-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        f_block_unid&lt;/span&gt;
&lt;span id="cb40-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb40-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ))&lt;/span&gt;
&lt;span id="cb40-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb40-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    γ_unid &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"γ_unid"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;1.&lt;/span&gt;, dims&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="st"&gt;"unit"&lt;/span&gt;, &lt;span class="st"&gt;"fact"&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, we specify our observational likelihood.&lt;/p&gt;
&lt;div class="sourceCode" id="cb41"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb41-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb41-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; ref_model:&lt;/span&gt;
&lt;span id="cb41-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb41-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ_ctrl &lt;span class="op"&gt;=&lt;/span&gt; (X[..., np.newaxis] &lt;span class="op"&gt;*&lt;/span&gt; θ).&lt;span class="bu"&gt;sum&lt;/span&gt;(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;) &lt;span class="op"&gt;+&lt;/span&gt; γ_unid.dot(f_unid.T)&lt;/span&gt;
&lt;span id="cb41-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb41-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb41-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb41-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"σ"&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; HALFNORMAL_SCALE)&lt;/span&gt;
&lt;span id="cb41-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb41-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs_ctrl &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"obs_ctrl"&lt;/span&gt;, μ_ctrl, σ, observed&lt;span class="op"&gt;=&lt;/span&gt;y_ctrl)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now draw 100 samples from this unidentified model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb42"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb42-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb42-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;CORES &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb42-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb42-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SAMPLE_KWARGS &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb42-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb42-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"cores"&lt;/span&gt;: CORES,&lt;/span&gt;
&lt;span id="cb42-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb42-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"random_seed"&lt;/span&gt;: [SEED &lt;span class="op"&gt;+&lt;/span&gt; i &lt;span class="cf"&gt;for&lt;/span&gt; i &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;range&lt;/span&gt;(CORES)],&lt;/span&gt;
&lt;span id="cb42-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb42-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"return_inferencedata"&lt;/span&gt;: &lt;span class="va"&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb42-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb43"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb43-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb43-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; ref_model:&lt;/span&gt;
&lt;span id="cb43-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb43-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ref_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(tune&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;100&lt;/span&gt;, draws&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;100&lt;/span&gt;, &lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Only 100 samples in chain.
Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [β, Δ_α, σ_α, Δ_ξ, σ_ξ, f_pos_row, f_block_unid, γ_unid, σ, obs_ctrl_missing]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="600" class max="600" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [600/600 02:14&amp;lt;00:00 Sampling 3 chains, 18 divergences]&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Sampling 3 chains for 100 tune and 100 draw iterations (300 + 300 draws total) took 136 seconds.
There were 18 divergences after tuning. Increase `target_accept` or reparameterize.
The acceptance probability does not match the target. It is 1.0, but should be close to 0.8. Try to increase the number of tuning steps.
The rhat statistic is larger than 1.4 for some parameters. The sampler did not converge.
The number of effective samples is smaller than 10% for some parameters.&lt;/code&gt;&lt;/pre&gt;
&lt;div class="sourceCode" id="cb46"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb46-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb46-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.rhat(ref_trace).&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;svg style="position: absolute; width: 0; height: 0; overflow: hidden"&gt;
&lt;defs&gt; &lt;symbol id="icon-database" viewbox="0 0 32 32"&gt; &lt;path d="M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z"&gt;&lt;/path&gt; &lt;path d="M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;path d="M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;symbol id="icon-file-text2" viewbox="0 0 32 32"&gt; &lt;path d="M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z"&gt;&lt;/path&gt; &lt;path d="M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;/defs&gt;
&lt;/svg&gt;
&lt;style&gt;/* CSS stylesheet for displaying xarray objects in jupyterlab.
 *
 */

:root {
  --xr-font-color0: var(--jp-content-font-color0, rgba(0, 0, 0, 1));
  --xr-font-color2: var(--jp-content-font-color2, rgba(0, 0, 0, 0.54));
  --xr-font-color3: var(--jp-content-font-color3, rgba(0, 0, 0, 0.38));
  --xr-border-color: var(--jp-border-color2, #e0e0e0);
  --xr-disabled-color: var(--jp-layout-color3, #bdbdbd);
  --xr-background-color: var(--jp-layout-color0, white);
  --xr-background-color-row-even: var(--jp-layout-color1, white);
  --xr-background-color-row-odd: var(--jp-layout-color2, #eeeeee);
}

html[theme=dark],
body.vscode-dark {
  --xr-font-color0: rgba(255, 255, 255, 1);
  --xr-font-color2: rgba(255, 255, 255, 0.54);
  --xr-font-color3: rgba(255, 255, 255, 0.38);
  --xr-border-color: #1F1F1F;
  --xr-disabled-color: #515151;
  --xr-background-color: #111111;
  --xr-background-color-row-even: #111111;
  --xr-background-color-row-odd: #313131;
}

.xr-wrap {
  display: block;
  min-width: 300px;
  max-width: 700px;
}

.xr-text-repr-fallback {
  /* fallback to plain text repr when CSS is not injected (untrusted notebook) */
  display: none;
}

.xr-header {
  padding-top: 6px;
  padding-bottom: 6px;
  margin-bottom: 4px;
  border-bottom: solid 1px var(--xr-border-color);
}

.xr-header &gt; div,
.xr-header &gt; ul {
  display: inline;
  margin-top: 0;
  margin-bottom: 0;
}

.xr-obj-type,
.xr-array-name {
  margin-left: 2px;
  margin-right: 10px;
}

.xr-obj-type {
  color: var(--xr-font-color2);
}

.xr-sections {
  padding-left: 0 !important;
  display: grid;
  grid-template-columns: 150px auto auto 1fr 20px 20px;
}

.xr-section-item {
  display: contents;
}

.xr-section-item input {
  display: none;
}

.xr-section-item input + label {
  color: var(--xr-disabled-color);
}

.xr-section-item input:enabled + label {
  cursor: pointer;
  color: var(--xr-font-color2);
}

.xr-section-item input:enabled + label:hover {
  color: var(--xr-font-color0);
}

.xr-section-summary {
  grid-column: 1;
  color: var(--xr-font-color2);
  font-weight: 500;
}

.xr-section-summary &gt; span {
  display: inline-block;
  padding-left: 0.5em;
}

.xr-section-summary-in:disabled + label {
  color: var(--xr-font-color2);
}

.xr-section-summary-in + label:before {
  display: inline-block;
  content: '►';
  font-size: 11px;
  width: 15px;
  text-align: center;
}

.xr-section-summary-in:disabled + label:before {
  color: var(--xr-disabled-color);
}

.xr-section-summary-in:checked + label:before {
  content: '▼';
}

.xr-section-summary-in:checked + label &gt; span {
  display: none;
}

.xr-section-summary,
.xr-section-inline-details {
  padding-top: 4px;
  padding-bottom: 4px;
}

.xr-section-inline-details {
  grid-column: 2 / -1;
}

.xr-section-details {
  display: none;
  grid-column: 1 / -1;
  margin-bottom: 5px;
}

.xr-section-summary-in:checked ~ .xr-section-details {
  display: contents;
}

.xr-array-wrap {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 20px auto;
}

.xr-array-wrap &gt; label {
  grid-column: 1;
  vertical-align: top;
}

.xr-preview {
  color: var(--xr-font-color3);
}

.xr-array-preview,
.xr-array-data {
  padding: 0 5px !important;
  grid-column: 2;
}

.xr-array-data,
.xr-array-in:checked ~ .xr-array-preview {
  display: none;
}

.xr-array-in:checked ~ .xr-array-data,
.xr-array-preview {
  display: inline-block;
}

.xr-dim-list {
  display: inline-block !important;
  list-style: none;
  padding: 0 !important;
  margin: 0;
}

.xr-dim-list li {
  display: inline-block;
  padding: 0;
  margin: 0;
}

.xr-dim-list:before {
  content: '(';
}

.xr-dim-list:after {
  content: ')';
}

.xr-dim-list li:not(:last-child):after {
  content: ',';
  padding-right: 5px;
}

.xr-has-index {
  font-weight: bold;
}

.xr-var-list,
.xr-var-item {
  display: contents;
}

.xr-var-item &gt; div,
.xr-var-item label,
.xr-var-item &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-even);
  margin-bottom: 0;
}

.xr-var-item &gt; .xr-var-name:hover span {
  padding-right: 5px;
}

.xr-var-list &gt; li:nth-child(odd) &gt; div,
.xr-var-list &gt; li:nth-child(odd) &gt; label,
.xr-var-list &gt; li:nth-child(odd) &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-odd);
}

.xr-var-name {
  grid-column: 1;
}

.xr-var-dims {
  grid-column: 2;
}

.xr-var-dtype {
  grid-column: 3;
  text-align: right;
  color: var(--xr-font-color2);
}

.xr-var-preview {
  grid-column: 4;
}

.xr-var-name,
.xr-var-dims,
.xr-var-dtype,
.xr-preview,
.xr-attrs dt {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 10px;
}

.xr-var-name:hover,
.xr-var-dims:hover,
.xr-var-dtype:hover,
.xr-attrs dt:hover {
  overflow: visible;
  width: auto;
  z-index: 1;
}

.xr-var-attrs,
.xr-var-data {
  display: none;
  background-color: var(--xr-background-color) !important;
  padding-bottom: 5px !important;
}

.xr-var-attrs-in:checked ~ .xr-var-attrs,
.xr-var-data-in:checked ~ .xr-var-data {
  display: block;
}

.xr-var-data &gt; table {
  float: right;
}

.xr-var-name span,
.xr-var-data,
.xr-attrs {
  padding-left: 25px !important;
}

.xr-attrs,
.xr-var-attrs,
.xr-var-data {
  grid-column: 1 / -1;
}

dl.xr-attrs {
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 125px auto;
}

.xr-attrs dt,
.xr-attrs dd {
  padding: 0;
  margin: 0;
  float: left;
  padding-right: 10px;
  width: auto;
}

.xr-attrs dt {
  font-weight: normal;
  grid-column: 1;
}

.xr-attrs dt:hover span {
  display: inline-block;
  background: var(--xr-background-color);
  padding-right: 10px;
}

.xr-attrs dd {
  grid-column: 2;
  white-space: pre-wrap;
  word-break: break-all;
}

.xr-icon-database,
.xr-icon-file-text2 {
  display: inline-block;
  vertical-align: middle;
  width: 1em;
  height: 1.5em !important;
  stroke-width: 0;
  stroke: currentColor;
  fill: currentColor;
}
&lt;/style&gt;
&lt;pre class="xr-text-repr-fallback"&gt;&amp;lt;xarray.Dataset&amp;gt;
Dimensions:           ()
Data variables:
    β                 float64 1.813
    Δ_α               float64 1.885
    σ_α               float64 1.814
    Δ_ξ               float64 1.86
    σ_ξ               float64 1.805
    f_pos_row         float64 1.727
    f_block_unid      float64 1.818
    γ_unid            float64 1.808
    σ                 float64 1.832
    obs_ctrl_missing  float64 1.82
    α                 float64 1.85
    ξ                 float64 1.848&lt;/pre&gt;
&lt;div class="xr-wrap" hidden=""&gt;
&lt;div class="xr-header"&gt;
&lt;div class="xr-obj-type"&gt;
xarray.Dataset
&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="xr-sections"&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-893aabd1-b7b6-4733-91c9-282bb59cb3c1" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-893aabd1-b7b6-4733-91c9-282bb59cb3c1" class="xr-section-summary" title="Expand/collapse section"&gt;Dimensions:&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-4b556a2e-1ca2-436c-b931-8633810fc3f9" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-4b556a2e-1ca2-436c-b931-8633810fc3f9" class="xr-section-summary" title="Expand/collapse section"&gt;Coordinates: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-5681b80f-e688-460c-ab2a-cbf11c693f97" class="xr-section-summary-in" type="checkbox" checked&gt;&lt;label for="section-5681b80f-e688-460c-ab2a-cbf11c693f97" class="xr-section-summary"&gt;Data variables: &lt;span&gt;(12)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;β&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.813
&lt;/div&gt;
&lt;input id="attrs-6d6ebe00-49bf-443c-a635-b2a085ae2a0c" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-6d6ebe00-49bf-443c-a635-b2a085ae2a0c" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-b7902a7e-8f84-490c-b48d-6b652ecb242f" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-b7902a7e-8f84-490c-b48d-6b652ecb242f" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.81270912)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;Δ_α&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.885
&lt;/div&gt;
&lt;input id="attrs-14d81b4e-c8a3-4084-8154-c90cd50d230a" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-14d81b4e-c8a3-4084-8154-c90cd50d230a" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-a238804e-9eba-4ccc-9f6c-54c0c7540b93" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-a238804e-9eba-4ccc-9f6c-54c0c7540b93" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.88526959)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;σ_α&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.814
&lt;/div&gt;
&lt;input id="attrs-195fd498-8c9c-4d5b-9b7e-450f7cd0a465" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-195fd498-8c9c-4d5b-9b7e-450f7cd0a465" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-074ae403-d66c-441b-9a07-36d9c5451b26" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-074ae403-d66c-441b-9a07-36d9c5451b26" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.81400238)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;Δ_ξ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.86
&lt;/div&gt;
&lt;input id="attrs-087a0100-8205-4d19-93f0-394e5e9aa7c7" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-087a0100-8205-4d19-93f0-394e5e9aa7c7" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-dbd78f5e-f6c2-4d04-bbcb-03a0ad406ca8" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-dbd78f5e-f6c2-4d04-bbcb-03a0ad406ca8" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.85974353)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;σ_ξ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.805
&lt;/div&gt;
&lt;input id="attrs-3f2853d8-a1ec-4b35-8849-2b13e039ecef" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-3f2853d8-a1ec-4b35-8849-2b13e039ecef" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-0b6449bf-95ee-4f49-b8cd-7b3ccd1b24fa" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-0b6449bf-95ee-4f49-b8cd-7b3ccd1b24fa" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.80451891)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;f_pos_row&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.727
&lt;/div&gt;
&lt;input id="attrs-461c5a4c-78e8-4a81-b1f7-8a8f1459af24" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-461c5a4c-78e8-4a81-b1f7-8a8f1459af24" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-eb90cc03-759c-4ae5-84a0-dd7679bc712c" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-eb90cc03-759c-4ae5-84a0-dd7679bc712c" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.72748944)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;f_block_unid&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.818
&lt;/div&gt;
&lt;input id="attrs-35db9239-4a34-43bc-9516-5d2abb077118" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-35db9239-4a34-43bc-9516-5d2abb077118" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-0ec0fec8-f669-456b-baaf-5a6ac8e2fc60" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-0ec0fec8-f669-456b-baaf-5a6ac8e2fc60" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.81831663)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;γ_unid&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.808
&lt;/div&gt;
&lt;input id="attrs-31481cfa-752c-4946-abe4-7210cc3eb712" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-31481cfa-752c-4946-abe4-7210cc3eb712" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-8085c1fb-d93f-4012-ba4c-3a90399dc14d" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-8085c1fb-d93f-4012-ba4c-3a90399dc14d" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.80812046)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;σ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.832
&lt;/div&gt;
&lt;input id="attrs-4805568a-632a-495b-a327-231e773fef7a" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-4805568a-632a-495b-a327-231e773fef7a" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-ad27b52a-2f3e-460b-a569-c8118c21ea56" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-ad27b52a-2f3e-460b-a569-c8118c21ea56" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.83187637)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;obs_ctrl_missing&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.82
&lt;/div&gt;
&lt;input id="attrs-4ce94dc7-3656-4125-b540-e5d22a7b559b" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-4ce94dc7-3656-4125-b540-e5d22a7b559b" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-019a7263-5579-4097-9a0d-46865971b755" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-019a7263-5579-4097-9a0d-46865971b755" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.81951939)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;α&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.85
&lt;/div&gt;
&lt;input id="attrs-05963eaf-361d-4844-9489-f9bfca046c01" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-05963eaf-361d-4844-9489-f9bfca046c01" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-94ce3608-1248-4c6d-adc6-26c77a635f78" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-94ce3608-1248-4c6d-adc6-26c77a635f78" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.84973862)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;ξ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.848
&lt;/div&gt;
&lt;input id="attrs-90ea0b58-91fe-48ff-be98-3d84f857cf5f" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-90ea0b58-91fe-48ff-be98-3d84f857cf5f" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-81fb896b-5ccc-4b87-a983-76ab95199ef4" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-81fb896b-5ccc-4b87-a983-76ab95199ef4" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.84825114)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-a3ba7cb2-32d9-41a2-be53-1065b4780eeb" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-a3ba7cb2-32d9-41a2-be53-1065b4780eeb" class="xr-section-summary" title="Expand/collapse section"&gt;Attributes: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As expected, the &lt;span class="math inline"&gt;\(\hat{R}\)&lt;/span&gt; parameters are quite high, indiciating that the chains have not converged well. This behavior is expected, since we know that this model is reflection-invariant and therefore has a multimodal posterior.&lt;/p&gt;
&lt;p&gt;As in the previous post on identification in factor analysis, we choose a row of &lt;code&gt;f_block_unid&lt;/code&gt; that we constrain to have all positive entries and change the signs of the entries &lt;code&gt;f_block_unid&lt;/code&gt; and &lt;code&gt;γ_unid&lt;/code&gt; so that they have the same relationship with the signs of this row. We choose the row that has the chain whose latent factors have the largest posterior expected distance from the origin.&lt;/p&gt;
&lt;div class="sourceCode" id="cb47"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb47-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb47-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;block_mean &lt;span class="op"&gt;=&lt;/span&gt; (ref_trace.posterior[&lt;span class="st"&gt;"f_block_unid"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb47-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb47-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                       .mean(dim&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"draw"&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb47-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb47-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;block_mean_norm &lt;span class="op"&gt;=&lt;/span&gt; np.square(block_mean).&lt;span class="bu"&gt;sum&lt;/span&gt;(dim&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"fact"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb47-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb47-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sign_row &lt;span class="op"&gt;=&lt;/span&gt; (block_mean_norm.&lt;span class="bu"&gt;max&lt;/span&gt;(dim&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"chain"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb47-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb47-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                           .argmax()&lt;/span&gt;
&lt;span id="cb47-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb47-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                           .item())&lt;/span&gt;
&lt;span id="cb47-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb47-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sign_chain &lt;span class="op"&gt;=&lt;/span&gt; (block_mean_norm.sel({&lt;span class="st"&gt;"time_block"&lt;/span&gt;: sign_row})&lt;/span&gt;
&lt;span id="cb47-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb47-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                             .argmax()&lt;/span&gt;
&lt;span id="cb47-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb47-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                             .item())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb48"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb48-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb48-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;target_sign &lt;span class="op"&gt;=&lt;/span&gt; (np.sign(block_mean.sel({&lt;span class="st"&gt;"chain"&lt;/span&gt;: sign_chain,&lt;/span&gt;
&lt;span id="cb48-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb48-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                       &lt;span class="st"&gt;"time_block"&lt;/span&gt;: sign_row}))&lt;/span&gt;
&lt;span id="cb48-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb48-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 .data)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can now specify the identified model, which is largely the same as the previous model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb49"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb49-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb49-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model(coords&lt;span class="op"&gt;=&lt;/span&gt;coords) &lt;span class="im"&gt;as&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb49-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb49-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"β"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt;, dims&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"feat"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb49-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb49-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    α &lt;span class="op"&gt;=&lt;/span&gt; noncentered_normal(&lt;span class="st"&gt;"α"&lt;/span&gt;, (&lt;span class="st"&gt;"unit"&lt;/span&gt;, &lt;span class="st"&gt;"feat"&lt;/span&gt;), μ&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb49-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb49-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ξ &lt;span class="op"&gt;=&lt;/span&gt; noncentered_normal(&lt;span class="st"&gt;"ξ"&lt;/span&gt;, (&lt;span class="st"&gt;"feat"&lt;/span&gt;, &lt;span class="st"&gt;"time"&lt;/span&gt;), μ&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb49-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb49-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    θ &lt;span class="op"&gt;=&lt;/span&gt; β[np.newaxis, :, np.newaxis] &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb49-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb49-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;+&lt;/span&gt; α[..., np.newaxis] &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb49-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb49-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;+&lt;/span&gt; ξ[np.newaxis, ...]&lt;/span&gt;
&lt;span id="cb49-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb49-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb49-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb49-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    f_pos_row &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"f_pos_row"&lt;/span&gt;, HALFNORMAL_SCALE,&lt;/span&gt;
&lt;span id="cb49-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb49-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                              dims&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"fact"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb49-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb49-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    f_block_unid &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"f_block_unid"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;1.&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb49-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb49-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                             dims&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="st"&gt;"time_block"&lt;/span&gt;, &lt;span class="st"&gt;"fact"&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb49-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb49-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb49-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb49-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    γ_unid &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"γ_unid"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;1.&lt;/span&gt;, dims&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="st"&gt;"unit"&lt;/span&gt;, &lt;span class="st"&gt;"fact"&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now enforce the sign constraints that will break the reflectional invariance of the previous model and specify the observational likelihood.&lt;/p&gt;
&lt;div class="sourceCode" id="cb50"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb50-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb50-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    unid_sign &lt;span class="op"&gt;=&lt;/span&gt; at.sgn(f_block_unid[sign_row])&lt;/span&gt;
&lt;span id="cb50-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb50-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    f_block &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;/span&gt;
&lt;span id="cb50-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;"f_block"&lt;/span&gt;, target_sign &lt;span class="op"&gt;*&lt;/span&gt; unid_sign &lt;span class="op"&gt;*&lt;/span&gt; f_block_unid,&lt;/span&gt;
&lt;span id="cb50-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        dims&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="st"&gt;"time_block"&lt;/span&gt;, &lt;span class="st"&gt;"fact"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb50-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb50-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    f &lt;span class="op"&gt;=&lt;/span&gt; at.concatenate((&lt;/span&gt;
&lt;span id="cb50-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        at.eye(N_factor),&lt;/span&gt;
&lt;span id="cb50-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        at.shape_padleft(f_pos_row),&lt;/span&gt;
&lt;span id="cb50-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        f_block&lt;/span&gt;
&lt;span id="cb50-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ))&lt;/span&gt;
&lt;span id="cb50-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb50-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    γ &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;/span&gt;
&lt;span id="cb50-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;"γ"&lt;/span&gt;, target_sign &lt;span class="op"&gt;*&lt;/span&gt; unid_sign &lt;span class="op"&gt;*&lt;/span&gt; γ_unid,&lt;/span&gt;
&lt;span id="cb50-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        dims&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="st"&gt;"unit"&lt;/span&gt;, &lt;span class="st"&gt;"fact"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb50-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb50-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb50-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ_ctrl &lt;span class="op"&gt;=&lt;/span&gt; (X[..., np.newaxis] &lt;span class="op"&gt;*&lt;/span&gt; θ).&lt;span class="bu"&gt;sum&lt;/span&gt;(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;) &lt;span class="op"&gt;+&lt;/span&gt; γ.dot(f.T)&lt;/span&gt;
&lt;span id="cb50-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb50-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"σ"&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; HALFNORMAL_SCALE)&lt;/span&gt;
&lt;span id="cb50-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb50-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs_ctrl &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"obs_ctrl"&lt;/span&gt;, μ_ctrl, σ, observed&lt;span class="op"&gt;=&lt;/span&gt;y_ctrl)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now sample from this identified model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb51"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb51-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb51-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb51-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb51-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [β, Δ_α, σ_α, Δ_ξ, σ_ξ, f_pos_row, f_block_unid, γ_unid, σ, obs_ctrl_missing]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="6000" class max="6000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [6000/6000 13:54&amp;lt;00:00 Sampling 3 chains, 0 divergences]&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Sampling 3 chains for 1_000 tune and 1_000 draw iterations (3_000 + 3_000 draws total) took 835 seconds.
The rhat statistic is larger than 1.4 for some parameters. The sampler did not converge.
The estimated number of effective samples is smaller than 200 for some parameters.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For the moment we ignore the convergence warnings, because we expect the &lt;span class="math inline"&gt;\(\hat{R}\)&lt;/span&gt; values for &lt;code&gt;f_block_unid&lt;/code&gt; and &lt;code&gt;γ_unid&lt;/code&gt; to be high.&lt;/p&gt;
&lt;p&gt;The energy plot shows no cause for concern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb54"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb54-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb54-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_energy(trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/basc-ccs_files/basc-ccs_82_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Ignoring the variables we know are not identified, all of our &lt;span class="math inline"&gt;\(\hat{R}\)&lt;/span&gt; statistics are reasonable as well.&lt;/p&gt;
&lt;div class="sourceCode" id="cb55"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb55-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb55-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;rhat_var_names &lt;span class="op"&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb55-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb55-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    var_name &lt;span class="cf"&gt;for&lt;/span&gt; var_name &lt;span class="kw"&gt;in&lt;/span&gt; trace.posterior.data_vars&lt;/span&gt;
&lt;span id="cb55-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb55-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;if&lt;/span&gt; &lt;span class="kw"&gt;not&lt;/span&gt; var_name.endswith(&lt;span class="st"&gt;"_unid"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb55-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb55-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb56"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb56-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb56-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.rhat(trace, var_names&lt;span class="op"&gt;=&lt;/span&gt;rhat_var_names).&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;svg style="position: absolute; width: 0; height: 0; overflow: hidden"&gt;
&lt;defs&gt; &lt;symbol id="icon-database" viewbox="0 0 32 32"&gt; &lt;path d="M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z"&gt;&lt;/path&gt; &lt;path d="M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;path d="M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;symbol id="icon-file-text2" viewbox="0 0 32 32"&gt; &lt;path d="M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z"&gt;&lt;/path&gt; &lt;path d="M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;/defs&gt;
&lt;/svg&gt;
&lt;style&gt;/* CSS stylesheet for displaying xarray objects in jupyterlab.
 *
 */

:root {
  --xr-font-color0: var(--jp-content-font-color0, rgba(0, 0, 0, 1));
  --xr-font-color2: var(--jp-content-font-color2, rgba(0, 0, 0, 0.54));
  --xr-font-color3: var(--jp-content-font-color3, rgba(0, 0, 0, 0.38));
  --xr-border-color: var(--jp-border-color2, #e0e0e0);
  --xr-disabled-color: var(--jp-layout-color3, #bdbdbd);
  --xr-background-color: var(--jp-layout-color0, white);
  --xr-background-color-row-even: var(--jp-layout-color1, white);
  --xr-background-color-row-odd: var(--jp-layout-color2, #eeeeee);
}

html[theme=dark],
body.vscode-dark {
  --xr-font-color0: rgba(255, 255, 255, 1);
  --xr-font-color2: rgba(255, 255, 255, 0.54);
  --xr-font-color3: rgba(255, 255, 255, 0.38);
  --xr-border-color: #1F1F1F;
  --xr-disabled-color: #515151;
  --xr-background-color: #111111;
  --xr-background-color-row-even: #111111;
  --xr-background-color-row-odd: #313131;
}

.xr-wrap {
  display: block;
  min-width: 300px;
  max-width: 700px;
}

.xr-text-repr-fallback {
  /* fallback to plain text repr when CSS is not injected (untrusted notebook) */
  display: none;
}

.xr-header {
  padding-top: 6px;
  padding-bottom: 6px;
  margin-bottom: 4px;
  border-bottom: solid 1px var(--xr-border-color);
}

.xr-header &gt; div,
.xr-header &gt; ul {
  display: inline;
  margin-top: 0;
  margin-bottom: 0;
}

.xr-obj-type,
.xr-array-name {
  margin-left: 2px;
  margin-right: 10px;
}

.xr-obj-type {
  color: var(--xr-font-color2);
}

.xr-sections {
  padding-left: 0 !important;
  display: grid;
  grid-template-columns: 150px auto auto 1fr 20px 20px;
}

.xr-section-item {
  display: contents;
}

.xr-section-item input {
  display: none;
}

.xr-section-item input + label {
  color: var(--xr-disabled-color);
}

.xr-section-item input:enabled + label {
  cursor: pointer;
  color: var(--xr-font-color2);
}

.xr-section-item input:enabled + label:hover {
  color: var(--xr-font-color0);
}

.xr-section-summary {
  grid-column: 1;
  color: var(--xr-font-color2);
  font-weight: 500;
}

.xr-section-summary &gt; span {
  display: inline-block;
  padding-left: 0.5em;
}

.xr-section-summary-in:disabled + label {
  color: var(--xr-font-color2);
}

.xr-section-summary-in + label:before {
  display: inline-block;
  content: '►';
  font-size: 11px;
  width: 15px;
  text-align: center;
}

.xr-section-summary-in:disabled + label:before {
  color: var(--xr-disabled-color);
}

.xr-section-summary-in:checked + label:before {
  content: '▼';
}

.xr-section-summary-in:checked + label &gt; span {
  display: none;
}

.xr-section-summary,
.xr-section-inline-details {
  padding-top: 4px;
  padding-bottom: 4px;
}

.xr-section-inline-details {
  grid-column: 2 / -1;
}

.xr-section-details {
  display: none;
  grid-column: 1 / -1;
  margin-bottom: 5px;
}

.xr-section-summary-in:checked ~ .xr-section-details {
  display: contents;
}

.xr-array-wrap {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 20px auto;
}

.xr-array-wrap &gt; label {
  grid-column: 1;
  vertical-align: top;
}

.xr-preview {
  color: var(--xr-font-color3);
}

.xr-array-preview,
.xr-array-data {
  padding: 0 5px !important;
  grid-column: 2;
}

.xr-array-data,
.xr-array-in:checked ~ .xr-array-preview {
  display: none;
}

.xr-array-in:checked ~ .xr-array-data,
.xr-array-preview {
  display: inline-block;
}

.xr-dim-list {
  display: inline-block !important;
  list-style: none;
  padding: 0 !important;
  margin: 0;
}

.xr-dim-list li {
  display: inline-block;
  padding: 0;
  margin: 0;
}

.xr-dim-list:before {
  content: '(';
}

.xr-dim-list:after {
  content: ')';
}

.xr-dim-list li:not(:last-child):after {
  content: ',';
  padding-right: 5px;
}

.xr-has-index {
  font-weight: bold;
}

.xr-var-list,
.xr-var-item {
  display: contents;
}

.xr-var-item &gt; div,
.xr-var-item label,
.xr-var-item &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-even);
  margin-bottom: 0;
}

.xr-var-item &gt; .xr-var-name:hover span {
  padding-right: 5px;
}

.xr-var-list &gt; li:nth-child(odd) &gt; div,
.xr-var-list &gt; li:nth-child(odd) &gt; label,
.xr-var-list &gt; li:nth-child(odd) &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-odd);
}

.xr-var-name {
  grid-column: 1;
}

.xr-var-dims {
  grid-column: 2;
}

.xr-var-dtype {
  grid-column: 3;
  text-align: right;
  color: var(--xr-font-color2);
}

.xr-var-preview {
  grid-column: 4;
}

.xr-var-name,
.xr-var-dims,
.xr-var-dtype,
.xr-preview,
.xr-attrs dt {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 10px;
}

.xr-var-name:hover,
.xr-var-dims:hover,
.xr-var-dtype:hover,
.xr-attrs dt:hover {
  overflow: visible;
  width: auto;
  z-index: 1;
}

.xr-var-attrs,
.xr-var-data {
  display: none;
  background-color: var(--xr-background-color) !important;
  padding-bottom: 5px !important;
}

.xr-var-attrs-in:checked ~ .xr-var-attrs,
.xr-var-data-in:checked ~ .xr-var-data {
  display: block;
}

.xr-var-data &gt; table {
  float: right;
}

.xr-var-name span,
.xr-var-data,
.xr-attrs {
  padding-left: 25px !important;
}

.xr-attrs,
.xr-var-attrs,
.xr-var-data {
  grid-column: 1 / -1;
}

dl.xr-attrs {
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 125px auto;
}

.xr-attrs dt,
.xr-attrs dd {
  padding: 0;
  margin: 0;
  float: left;
  padding-right: 10px;
  width: auto;
}

.xr-attrs dt {
  font-weight: normal;
  grid-column: 1;
}

.xr-attrs dt:hover span {
  display: inline-block;
  background: var(--xr-background-color);
  padding-right: 10px;
}

.xr-attrs dd {
  grid-column: 2;
  white-space: pre-wrap;
  word-break: break-all;
}

.xr-icon-database,
.xr-icon-file-text2 {
  display: inline-block;
  vertical-align: middle;
  width: 1em;
  height: 1.5em !important;
  stroke-width: 0;
  stroke: currentColor;
  fill: currentColor;
}
&lt;/style&gt;
&lt;pre class="xr-text-repr-fallback"&gt;&amp;lt;xarray.Dataset&amp;gt;
Dimensions:           ()
Data variables:
    β                 float64 1.004
    Δ_α               float64 1.007
    σ_α               float64 1.003
    Δ_ξ               float64 1.008
    σ_ξ               float64 1.0
    f_pos_row         float64 1.002
    σ                 float64 1.002
    obs_ctrl_missing  float64 1.004
    α                 float64 1.008
    ξ                 float64 1.008
    f_block           float64 1.008
    γ                 float64 1.008&lt;/pre&gt;
&lt;div class="xr-wrap" hidden=""&gt;
&lt;div class="xr-header"&gt;
&lt;div class="xr-obj-type"&gt;
xarray.Dataset
&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="xr-sections"&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-e868ecab-ab46-4e76-a98f-831c5cf2cd71" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-e868ecab-ab46-4e76-a98f-831c5cf2cd71" class="xr-section-summary" title="Expand/collapse section"&gt;Dimensions:&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-4ab2f128-0006-4117-842d-254234088f77" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-4ab2f128-0006-4117-842d-254234088f77" class="xr-section-summary" title="Expand/collapse section"&gt;Coordinates: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-0bd793ab-7da3-4760-bf0f-da019de57876" class="xr-section-summary-in" type="checkbox" checked&gt;&lt;label for="section-0bd793ab-7da3-4760-bf0f-da019de57876" class="xr-section-summary"&gt;Data variables: &lt;span&gt;(12)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;β&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.004
&lt;/div&gt;
&lt;input id="attrs-6e7ef1f5-eb43-448c-9a1f-ad5b81a34d91" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-6e7ef1f5-eb43-448c-9a1f-ad5b81a34d91" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-0ba991ac-27ad-4144-b8f7-f4833d12433a" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-0ba991ac-27ad-4144-b8f7-f4833d12433a" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00389839)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;Δ_α&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.007
&lt;/div&gt;
&lt;input id="attrs-aae261c1-c9b1-4b78-814b-f8da914c5da9" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-aae261c1-c9b1-4b78-814b-f8da914c5da9" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-1b1b9bed-c79b-4ed9-aa8a-2c7e75168d2a" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-1b1b9bed-c79b-4ed9-aa8a-2c7e75168d2a" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00650723)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;σ_α&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.003
&lt;/div&gt;
&lt;input id="attrs-9773e5fb-4b47-4af4-8f63-fe06d1cd9c73" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-9773e5fb-4b47-4af4-8f63-fe06d1cd9c73" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-ea53a995-6661-4f43-a045-718e964805e2" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-ea53a995-6661-4f43-a045-718e964805e2" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00252306)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;Δ_ξ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.008
&lt;/div&gt;
&lt;input id="attrs-c688aa01-9a10-4dc1-a609-ffae2e13a410" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-c688aa01-9a10-4dc1-a609-ffae2e13a410" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-bd5436f3-c0ea-43bb-a6f8-7268618e7669" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-bd5436f3-c0ea-43bb-a6f8-7268618e7669" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00802131)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;σ_ξ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.0
&lt;/div&gt;
&lt;input id="attrs-c9c1f02c-e799-4ce3-b3f4-43c7b01a97c3" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-c9c1f02c-e799-4ce3-b3f4-43c7b01a97c3" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-514a6c0a-a62e-4570-9e5a-ca360d5a4e53" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-514a6c0a-a62e-4570-9e5a-ca360d5a4e53" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00025354)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;f_pos_row&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.002
&lt;/div&gt;
&lt;input id="attrs-738f9bb1-e429-4f71-a4f6-b6498f534dba" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-738f9bb1-e429-4f71-a4f6-b6498f534dba" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-687b4df4-2860-497b-b822-cf16021375e9" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-687b4df4-2860-497b-b822-cf16021375e9" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00226488)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;σ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.002
&lt;/div&gt;
&lt;input id="attrs-ae4dafa7-0c54-4f76-a439-1cd72f7e769a" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-ae4dafa7-0c54-4f76-a439-1cd72f7e769a" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-4cafa54f-26f7-4b24-8583-d6acfdfad636" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-4cafa54f-26f7-4b24-8583-d6acfdfad636" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00224675)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;obs_ctrl_missing&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.004
&lt;/div&gt;
&lt;input id="attrs-ba2a3547-d323-470b-b356-0560808a2fd5" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-ba2a3547-d323-470b-b356-0560808a2fd5" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-d761dea0-cbbb-42bd-8cd5-5e233a9ec002" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-d761dea0-cbbb-42bd-8cd5-5e233a9ec002" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00359828)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;α&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.008
&lt;/div&gt;
&lt;input id="attrs-e8acbada-6dd8-48f6-86d5-d81ab8c0288e" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-e8acbada-6dd8-48f6-86d5-d81ab8c0288e" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-168184b4-e590-41b9-8bf8-09ce70703b46" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-168184b4-e590-41b9-8bf8-09ce70703b46" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00811494)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;ξ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.008
&lt;/div&gt;
&lt;input id="attrs-1c594262-ea32-4fac-a015-0a50b9ef2170" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-1c594262-ea32-4fac-a015-0a50b9ef2170" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-00cecafb-deaf-4b32-ac9c-68fd849bf458" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-00cecafb-deaf-4b32-ac9c-68fd849bf458" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00801751)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;f_block&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.008
&lt;/div&gt;
&lt;input id="attrs-3cbf5457-d609-4282-b5f6-b52ddc298a6a" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-3cbf5457-d609-4282-b5f6-b52ddc298a6a" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-8f0764b8-3a9a-452a-8eec-660c7b2a9443" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-8f0764b8-3a9a-452a-8eec-660c7b2a9443" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00819455)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;γ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.008
&lt;/div&gt;
&lt;input id="attrs-d3637a67-db84-4b64-b706-dda4099ffc67" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-d3637a67-db84-4b64-b706-dda4099ffc67" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-a5b3d3b1-e7dd-41e9-a066-b42db0e2a917" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-a5b3d3b1-e7dd-41e9-a066-b42db0e2a917" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00805011)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-3de1dac7-3cc2-46ee-8336-d342466c70aa" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-3de1dac7-3cc2-46ee-8336-d342466c70aa" class="xr-section-summary" title="Expand/collapse section"&gt;Attributes: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The model has recovered the true regression coefficients reasonably well.&lt;/p&gt;
&lt;div class="sourceCode" id="cb57"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb57-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb57-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax, &lt;span class="op"&gt;=&lt;/span&gt; az.plot_forest(trace, var_names&lt;span class="op"&gt;=&lt;/span&gt;[&lt;span class="st"&gt;"β"&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb57-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb57-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     combined&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, hdi_prob&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.95&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb57-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb57-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb57-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb57-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.scatter(B[::&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;], ax.get_yticks(),&lt;/span&gt;
&lt;span id="cb57-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb57-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, zorder&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;5&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Actual"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb57-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb57-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb57-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb57-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yticklabels([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb57-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb57-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="vs"&gt;r"$\beta_j$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb57-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb57-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb57-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb57-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'upper left'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/basc-ccs_files/basc-ccs_87_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We now turn to estimating the causal effect. First we build an array of the posterior imputed control outcomes for the treated units.&lt;/p&gt;
&lt;div class="sourceCode" id="cb58"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb58-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb58-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;post_treat_ctrl &lt;span class="op"&gt;=&lt;/span&gt; xr.DataArray(&lt;/span&gt;
&lt;span id="cb58-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb58-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    trace.posterior[&lt;span class="st"&gt;"obs_ctrl_missing"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb58-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb58-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          .data&lt;/span&gt;
&lt;span id="cb58-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb58-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          .reshape((CORES, &lt;span class="dv"&gt;1000&lt;/span&gt;, n_treated, T &lt;span class="op"&gt;-&lt;/span&gt; T_treat)),&lt;/span&gt;
&lt;span id="cb58-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb58-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    dims&lt;span class="op"&gt;=&lt;/span&gt;(&lt;/span&gt;
&lt;span id="cb58-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb58-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;"chain"&lt;/span&gt;, &lt;span class="st"&gt;"draw"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb58-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb58-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;"treat_unit"&lt;/span&gt;, &lt;span class="st"&gt;"treat_time"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb58-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb58-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb58-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb58-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb59"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb59-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb59-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;post_treat_ctrl.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;svg style="position: absolute; width: 0; height: 0; overflow: hidden"&gt;
&lt;defs&gt; &lt;symbol id="icon-database" viewbox="0 0 32 32"&gt; &lt;path d="M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z"&gt;&lt;/path&gt; &lt;path d="M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;path d="M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;symbol id="icon-file-text2" viewbox="0 0 32 32"&gt; &lt;path d="M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z"&gt;&lt;/path&gt; &lt;path d="M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;/defs&gt;
&lt;/svg&gt;
&lt;style&gt;/* CSS stylesheet for displaying xarray objects in jupyterlab.
 *
 */

:root {
  --xr-font-color0: var(--jp-content-font-color0, rgba(0, 0, 0, 1));
  --xr-font-color2: var(--jp-content-font-color2, rgba(0, 0, 0, 0.54));
  --xr-font-color3: var(--jp-content-font-color3, rgba(0, 0, 0, 0.38));
  --xr-border-color: var(--jp-border-color2, #e0e0e0);
  --xr-disabled-color: var(--jp-layout-color3, #bdbdbd);
  --xr-background-color: var(--jp-layout-color0, white);
  --xr-background-color-row-even: var(--jp-layout-color1, white);
  --xr-background-color-row-odd: var(--jp-layout-color2, #eeeeee);
}

html[theme=dark],
body.vscode-dark {
  --xr-font-color0: rgba(255, 255, 255, 1);
  --xr-font-color2: rgba(255, 255, 255, 0.54);
  --xr-font-color3: rgba(255, 255, 255, 0.38);
  --xr-border-color: #1F1F1F;
  --xr-disabled-color: #515151;
  --xr-background-color: #111111;
  --xr-background-color-row-even: #111111;
  --xr-background-color-row-odd: #313131;
}

.xr-wrap {
  display: block;
  min-width: 300px;
  max-width: 700px;
}

.xr-text-repr-fallback {
  /* fallback to plain text repr when CSS is not injected (untrusted notebook) */
  display: none;
}

.xr-header {
  padding-top: 6px;
  padding-bottom: 6px;
  margin-bottom: 4px;
  border-bottom: solid 1px var(--xr-border-color);
}

.xr-header &gt; div,
.xr-header &gt; ul {
  display: inline;
  margin-top: 0;
  margin-bottom: 0;
}

.xr-obj-type,
.xr-array-name {
  margin-left: 2px;
  margin-right: 10px;
}

.xr-obj-type {
  color: var(--xr-font-color2);
}

.xr-sections {
  padding-left: 0 !important;
  display: grid;
  grid-template-columns: 150px auto auto 1fr 20px 20px;
}

.xr-section-item {
  display: contents;
}

.xr-section-item input {
  display: none;
}

.xr-section-item input + label {
  color: var(--xr-disabled-color);
}

.xr-section-item input:enabled + label {
  cursor: pointer;
  color: var(--xr-font-color2);
}

.xr-section-item input:enabled + label:hover {
  color: var(--xr-font-color0);
}

.xr-section-summary {
  grid-column: 1;
  color: var(--xr-font-color2);
  font-weight: 500;
}

.xr-section-summary &gt; span {
  display: inline-block;
  padding-left: 0.5em;
}

.xr-section-summary-in:disabled + label {
  color: var(--xr-font-color2);
}

.xr-section-summary-in + label:before {
  display: inline-block;
  content: '►';
  font-size: 11px;
  width: 15px;
  text-align: center;
}

.xr-section-summary-in:disabled + label:before {
  color: var(--xr-disabled-color);
}

.xr-section-summary-in:checked + label:before {
  content: '▼';
}

.xr-section-summary-in:checked + label &gt; span {
  display: none;
}

.xr-section-summary,
.xr-section-inline-details {
  padding-top: 4px;
  padding-bottom: 4px;
}

.xr-section-inline-details {
  grid-column: 2 / -1;
}

.xr-section-details {
  display: none;
  grid-column: 1 / -1;
  margin-bottom: 5px;
}

.xr-section-summary-in:checked ~ .xr-section-details {
  display: contents;
}

.xr-array-wrap {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 20px auto;
}

.xr-array-wrap &gt; label {
  grid-column: 1;
  vertical-align: top;
}

.xr-preview {
  color: var(--xr-font-color3);
}

.xr-array-preview,
.xr-array-data {
  padding: 0 5px !important;
  grid-column: 2;
}

.xr-array-data,
.xr-array-in:checked ~ .xr-array-preview {
  display: none;
}

.xr-array-in:checked ~ .xr-array-data,
.xr-array-preview {
  display: inline-block;
}

.xr-dim-list {
  display: inline-block !important;
  list-style: none;
  padding: 0 !important;
  margin: 0;
}

.xr-dim-list li {
  display: inline-block;
  padding: 0;
  margin: 0;
}

.xr-dim-list:before {
  content: '(';
}

.xr-dim-list:after {
  content: ')';
}

.xr-dim-list li:not(:last-child):after {
  content: ',';
  padding-right: 5px;
}

.xr-has-index {
  font-weight: bold;
}

.xr-var-list,
.xr-var-item {
  display: contents;
}

.xr-var-item &gt; div,
.xr-var-item label,
.xr-var-item &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-even);
  margin-bottom: 0;
}

.xr-var-item &gt; .xr-var-name:hover span {
  padding-right: 5px;
}

.xr-var-list &gt; li:nth-child(odd) &gt; div,
.xr-var-list &gt; li:nth-child(odd) &gt; label,
.xr-var-list &gt; li:nth-child(odd) &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-odd);
}

.xr-var-name {
  grid-column: 1;
}

.xr-var-dims {
  grid-column: 2;
}

.xr-var-dtype {
  grid-column: 3;
  text-align: right;
  color: var(--xr-font-color2);
}

.xr-var-preview {
  grid-column: 4;
}

.xr-var-name,
.xr-var-dims,
.xr-var-dtype,
.xr-preview,
.xr-attrs dt {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 10px;
}

.xr-var-name:hover,
.xr-var-dims:hover,
.xr-var-dtype:hover,
.xr-attrs dt:hover {
  overflow: visible;
  width: auto;
  z-index: 1;
}

.xr-var-attrs,
.xr-var-data {
  display: none;
  background-color: var(--xr-background-color) !important;
  padding-bottom: 5px !important;
}

.xr-var-attrs-in:checked ~ .xr-var-attrs,
.xr-var-data-in:checked ~ .xr-var-data {
  display: block;
}

.xr-var-data &gt; table {
  float: right;
}

.xr-var-name span,
.xr-var-data,
.xr-attrs {
  padding-left: 25px !important;
}

.xr-attrs,
.xr-var-attrs,
.xr-var-data {
  grid-column: 1 / -1;
}

dl.xr-attrs {
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 125px auto;
}

.xr-attrs dt,
.xr-attrs dd {
  padding: 0;
  margin: 0;
  float: left;
  padding-right: 10px;
  width: auto;
}

.xr-attrs dt {
  font-weight: normal;
  grid-column: 1;
}

.xr-attrs dt:hover span {
  display: inline-block;
  background: var(--xr-background-color);
  padding-right: 10px;
}

.xr-attrs dd {
  grid-column: 2;
  white-space: pre-wrap;
  word-break: break-all;
}

.xr-icon-database,
.xr-icon-file-text2 {
  display: inline-block;
  vertical-align: middle;
  width: 1em;
  height: 1.5em !important;
  stroke-width: 0;
  stroke: currentColor;
  fill: currentColor;
}
&lt;/style&gt;
&lt;pre class="xr-text-repr-fallback"&gt;&amp;lt;xarray.DataArray (chain: 3, draw: 5, treat_unit: 5, treat_time: 5)&amp;gt;
array([[[[ 1.25759892e+01,  1.30612264e+01,  1.57087369e+01,
           1.49536257e+01,  1.64677110e+01],
         [-4.12810485e-02,  6.26047750e+00,  7.79874263e+00,
           1.23859034e+01,  1.61490831e+01],
         [ 7.27955473e+00,  1.04034349e+01,  1.12521199e+01,
           1.11063292e+01,  1.13530200e+01],
         [-5.36650155e+00, -5.83322477e+00, -3.35144524e+00,
           3.44000735e+00,  1.88207349e+00],
         [-1.31260800e+01, -1.22691019e+01, -1.33695535e+01,
          -5.94977044e+00, -8.61557509e+00]],

        [[ 1.30278045e+01,  1.42052058e+01,  1.40630688e+01,
           1.47218969e+01,  1.93233792e+01],
         [ 2.45746861e+00,  3.67240422e+00,  6.87289651e+00,
           8.61550996e+00,  1.48857372e+01],
         [ 8.68996670e+00,  1.22336995e+01,  1.01608424e+01,
           9.78275733e+00,  1.42336802e+01],
         [-6.32208820e+00, -3.22852886e+00, -1.89722169e+00,
           3.30217994e-01,  3.78225547e+00],
         [-1.53244972e+01, -1.35265466e+01, -1.36205170e+01,
...
           1.35873648e+01,  1.50553915e+01],
         [ 3.01241871e+00,  5.42217922e+00,  6.50204080e+00,
           1.15586759e+01,  1.33643026e+01],
         [ 7.65560768e+00,  1.29871011e+01,  9.75434111e+00,
           1.09479191e+01,  1.26587440e+01],
         [-3.59855020e+00, -4.76761066e+00, -4.10285725e+00,
           2.14369279e+00,  3.28661610e-01],
         [-1.39193859e+01, -1.79066255e+01, -1.26329862e+01,
          -4.73557646e+00, -7.94774028e+00]],

        [[ 1.38132791e+01,  1.24831973e+01,  1.20970456e+01,
           1.37274249e+01,  1.51289416e+01],
         [ 3.95173624e+00,  5.69156061e+00,  6.21128104e+00,
           1.20260114e+01,  1.34918240e+01],
         [ 7.22084256e+00,  1.30855164e+01,  9.73445859e+00,
           1.10445040e+01,  1.27090074e+01],
         [-3.85094179e+00, -3.93828746e+00, -3.88376440e+00,
           1.53955903e+00,  8.58625045e-01],
         [-1.39993793e+01, -1.79798655e+01, -1.25980525e+01,
          -4.70834640e+00, -7.87338772e+00]]]])
Dimensions without coordinates: chain, draw, treat_unit, treat_time&lt;/pre&gt;
&lt;div class="xr-wrap" hidden=""&gt;
&lt;div class="xr-header"&gt;
&lt;div class="xr-obj-type"&gt;
xarray.DataArray
&lt;/div&gt;
&lt;div class="xr-array-name"&gt;

&lt;/div&gt;
&lt;ul class="xr-dim-list"&gt;
&lt;li&gt;
&lt;span&gt;chain&lt;/span&gt;: 3
&lt;/li&gt;
&lt;li&gt;
&lt;span&gt;draw&lt;/span&gt;: 5
&lt;/li&gt;
&lt;li&gt;
&lt;span&gt;treat_unit&lt;/span&gt;: 5
&lt;/li&gt;
&lt;li&gt;
&lt;span&gt;treat_time&lt;/span&gt;: 5
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;ul class="xr-sections"&gt;
&lt;li class="xr-section-item"&gt;
&lt;div class="xr-array-wrap"&gt;
&lt;input id="section-d7c9a0fd-edfc-4da3-90ab-fc328b4dec2d" class="xr-array-in" type="checkbox" checked&gt;&lt;label for="section-d7c9a0fd-edfc-4da3-90ab-fc328b4dec2d" title="Show/hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-array-preview xr-preview"&gt;
&lt;span&gt;12.58 13.06 15.71 14.95 16.47 … -14.0 -17.98 -12.6 -4.708 -7.873&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-array-data"&gt;
&lt;pre&gt;array([[[[ 1.25759892e+01,  1.30612264e+01,  1.57087369e+01,
           1.49536257e+01,  1.64677110e+01],
         [-4.12810485e-02,  6.26047750e+00,  7.79874263e+00,
           1.23859034e+01,  1.61490831e+01],
         [ 7.27955473e+00,  1.04034349e+01,  1.12521199e+01,
           1.11063292e+01,  1.13530200e+01],
         [-5.36650155e+00, -5.83322477e+00, -3.35144524e+00,
           3.44000735e+00,  1.88207349e+00],
         [-1.31260800e+01, -1.22691019e+01, -1.33695535e+01,
          -5.94977044e+00, -8.61557509e+00]],

        [[ 1.30278045e+01,  1.42052058e+01,  1.40630688e+01,
           1.47218969e+01,  1.93233792e+01],
         [ 2.45746861e+00,  3.67240422e+00,  6.87289651e+00,
           8.61550996e+00,  1.48857372e+01],
         [ 8.68996670e+00,  1.22336995e+01,  1.01608424e+01,
           9.78275733e+00,  1.42336802e+01],
         [-6.32208820e+00, -3.22852886e+00, -1.89722169e+00,
           3.30217994e-01,  3.78225547e+00],
         [-1.53244972e+01, -1.35265466e+01, -1.36205170e+01,
...
           1.35873648e+01,  1.50553915e+01],
         [ 3.01241871e+00,  5.42217922e+00,  6.50204080e+00,
           1.15586759e+01,  1.33643026e+01],
         [ 7.65560768e+00,  1.29871011e+01,  9.75434111e+00,
           1.09479191e+01,  1.26587440e+01],
         [-3.59855020e+00, -4.76761066e+00, -4.10285725e+00,
           2.14369279e+00,  3.28661610e-01],
         [-1.39193859e+01, -1.79066255e+01, -1.26329862e+01,
          -4.73557646e+00, -7.94774028e+00]],

        [[ 1.38132791e+01,  1.24831973e+01,  1.20970456e+01,
           1.37274249e+01,  1.51289416e+01],
         [ 3.95173624e+00,  5.69156061e+00,  6.21128104e+00,
           1.20260114e+01,  1.34918240e+01],
         [ 7.22084256e+00,  1.30855164e+01,  9.73445859e+00,
           1.10445040e+01,  1.27090074e+01],
         [-3.85094179e+00, -3.93828746e+00, -3.88376440e+00,
           1.53955903e+00,  8.58625045e-01],
         [-1.39993793e+01, -1.79798655e+01, -1.25980525e+01,
          -4.70834640e+00, -7.87338772e+00]]]])&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-921babcf-a899-4c07-ac3a-e3a0aab640ba" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-921babcf-a899-4c07-ac3a-e3a0aab640ba" class="xr-section-summary" title="Expand/collapse section"&gt;Coordinates: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-7a1bc9f5-7da1-4979-ab63-380b8469bae6" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-7a1bc9f5-7da1-4979-ab63-380b8469bae6" class="xr-section-summary" title="Expand/collapse section"&gt;Attributes: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We plot these against the observed treated values to visualize the treatment effect.&lt;/p&gt;
&lt;div class="sourceCode" id="cb60"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb60-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb60-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb60-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;treated_c &lt;span class="op"&gt;=&lt;/span&gt; [&lt;span class="ss"&gt;f"C&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;i&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt; &lt;span class="cf"&gt;for&lt;/span&gt; i &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;range&lt;/span&gt;(n_treated)]&lt;/span&gt;
&lt;span id="cb60-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb60-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot(post_treat_ctrl.mean(dim&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="st"&gt;"chain"&lt;/span&gt;, &lt;span class="st"&gt;"draw"&lt;/span&gt;)).T,&lt;/span&gt;
&lt;span id="cb60-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ls&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'--'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_prop_cycle(&lt;span class="va"&gt;None&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot(y[treated, T_treat:].T)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb60-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="vs"&gt;r"$t - T_{\mathrm&lt;/span&gt;&lt;span class="sc"&gt;{treated}&lt;/span&gt;&lt;span class="vs"&gt;}$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"y_{i, t}"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb60-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;handles &lt;span class="op"&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb60-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    Line2D([&lt;span class="dv"&gt;0&lt;/span&gt;], [&lt;span class="dv"&gt;0&lt;/span&gt;], c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb60-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Treated (observed)"&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb60-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    Line2D([&lt;span class="dv"&gt;0&lt;/span&gt;], [&lt;span class="dv"&gt;0&lt;/span&gt;], c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, ls&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'--'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb60-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Control (posterior expected value)"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb60-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;
&lt;span id="cb60-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'upper left'&lt;/span&gt;, handles&lt;span class="op"&gt;=&lt;/span&gt;handles)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb60-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb60-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Treated units"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/basc-ccs_files/basc-ccs_92_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Here we see that the posterior estimates of the treatment effect are quite close to the actual effect.&lt;/p&gt;
&lt;div class="sourceCode" id="cb61"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb61-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb61-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb61-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;low, high &lt;span class="op"&gt;=&lt;/span&gt; (&lt;/span&gt;
&lt;span id="cb61-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (y[treated, T_treat:] &lt;span class="op"&gt;-&lt;/span&gt; post_treat_ctrl)&lt;/span&gt;
&lt;span id="cb61-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .quantile([&lt;span class="fl"&gt;0.025&lt;/span&gt;, &lt;span class="fl"&gt;0.975&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb61-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                  dim&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="st"&gt;"chain"&lt;/span&gt;, &lt;span class="st"&gt;"draw"&lt;/span&gt;, &lt;span class="st"&gt;"treat_unit"&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb61-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb61-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.fill_between(np.arange(T &lt;span class="op"&gt;-&lt;/span&gt; T_treat), low, high,&lt;/span&gt;
&lt;span id="cb61-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.25&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb61-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"95&lt;/span&gt;&lt;span class="sc"&gt;% c&lt;/span&gt;&lt;span class="st"&gt;redible interval"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb61-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot([&lt;span class="dv"&gt;0&lt;/span&gt;, T &lt;span class="op"&gt;-&lt;/span&gt; T_treat &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;], [&lt;span class="dv"&gt;0&lt;/span&gt;, T &lt;span class="op"&gt;-&lt;/span&gt; T_treat &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;], &lt;/span&gt;
&lt;span id="cb61-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Actual"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb61-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot(&lt;/span&gt;
&lt;span id="cb61-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    y[treated, T_treat:].T &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb61-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="op"&gt;-&lt;/span&gt; post_treat_ctrl.mean(dim&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="st"&gt;"chain"&lt;/span&gt;, &lt;span class="st"&gt;"draw"&lt;/span&gt;)).T,&lt;/span&gt;
&lt;span id="cb61-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb61-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb61-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb61-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;handles, _ &lt;span class="op"&gt;=&lt;/span&gt; ax.get_legend_handles_labels()&lt;/span&gt;
&lt;span id="cb61-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;handles.insert(&lt;/span&gt;
&lt;span id="cb61-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dv"&gt;1&lt;/span&gt;, Line2D([&lt;span class="dv"&gt;0&lt;/span&gt;], [&lt;span class="dv"&gt;0&lt;/span&gt;],c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Posterior expected"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb61-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb61-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'upper left'&lt;/span&gt;, handles&lt;span class="op"&gt;=&lt;/span&gt;handles)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb61-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb61-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="vs"&gt;r"$t - T_{\mathrm&lt;/span&gt;&lt;span class="sc"&gt;{treated}&lt;/span&gt;&lt;span class="vs"&gt;}$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb61-26"&gt;&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#cb61-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Treatment effect"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/basc-ccs_files/basc-ccs_94_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;This post is available as a Jupyter notebook &lt;a href="https://nbviewer.jupyter.org/gist/AustinRochford/932fa17bbd2d9b40c6efacdd4fcafa5a"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;section class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn1" role="doc-endnote"&gt;&lt;p&gt;Pang, Xun, Licheng Liu, and Yiqing Xu. “A Bayesian alternative to synthetic control for comparative case studies.” &lt;a href="https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3649226#"&gt;&lt;em&gt;Available at SSRN&lt;/em&gt;&lt;/a&gt; (2020).&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#fnref1" class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn2" role="doc-endnote"&gt;&lt;p&gt;Murphy, Kevin P. &lt;em&gt;Machine learning: a probabilistic perspective.&lt;/em&gt; MIT press, 2012.&lt;a href="https://austinrochford.com/posts/2021-08-08-basc-ccs.html#fnref2" class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description><category>Bayesian Statistics</category><category>Causal Inference</category><category>PyMC3</category><category>Python</category><guid>https://austinrochford.com/posts/2021-08-08-basc-ccs.html</guid><pubDate>Sun, 08 Aug 2021 04:00:00 GMT</pubDate></item><item><title>Modeling Shark Attacks in Python with PyMC3</title><link>https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html</link><dc:creator>Austin Rochford</dc:creator><description>&lt;p&gt;On a recent visit to &lt;a href="https://www.capemay.com/"&gt;Cape May, New Jersey&lt;/a&gt; I bought and read &lt;a href="https://www.amazon.com/dp/B085N5K6BQ"&gt;&lt;em&gt;Shark Attacks of the Jersey Shore: A History&lt;/em&gt;&lt;/a&gt;, which is an interesting account of verified shark attacks in New Jersey since the nineteenth century.&lt;/p&gt;
&lt;center&gt;
&lt;img src="https://img.thriftbooks.com/api/images/i/l/B0471B8D82576AC3D1ADE7F48D84273FE9A59A19.jpg"&gt;
&lt;/center&gt;
&lt;p&gt;While I was reading the book, I grew curious about modeling the frequency of shark attacks and went on the hunt for relevant data. There have not been many recent shark attacks in New Jersey, so I broadened my search and found the &lt;a href="http://www.sharkattackfile.net/"&gt;Global Shark Attack File&lt;/a&gt; (GSAF). The GSAF provides a fairly detailed &lt;a href="http://www.sharkattackfile.net/incidentlog.htm"&gt;incident log&lt;/a&gt; which appears to be updated every few days. This post presents an analysis of the GSAF data in Python using PyMC3. (It is worth mentioning that I am not a shark biologist, and I am sure specialists have produced much more useful and accurate models of shark attacks. Still, this seems like a fun small project as long as we don’t take the results too seriously.)&lt;/p&gt;
&lt;p&gt;First we make some Python imports and do a bit of housekeeping.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb1-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;matplotlib inline&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb2-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; functools &lt;span class="im"&gt;import&lt;/span&gt; &lt;span class="bu"&gt;reduce&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; warnings &lt;span class="im"&gt;import&lt;/span&gt; filterwarnings&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb3-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; aesara &lt;span class="im"&gt;import&lt;/span&gt; tensor &lt;span class="im"&gt;as&lt;/span&gt; at&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; arviz &lt;span class="im"&gt;as&lt;/span&gt; az&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib &lt;span class="im"&gt;import&lt;/span&gt; pyplot &lt;span class="im"&gt;as&lt;/span&gt; plt&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; numpy &lt;span class="im"&gt;as&lt;/span&gt; np&lt;/span&gt;
&lt;span id="cb3-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb3-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pandas &lt;span class="im"&gt;as&lt;/span&gt; pd&lt;/span&gt;
&lt;span id="cb3-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb3-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pymc3 &lt;span class="im"&gt;as&lt;/span&gt; pm&lt;/span&gt;
&lt;span id="cb3-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb3-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; seaborn &lt;span class="im"&gt;as&lt;/span&gt; sns&lt;/span&gt;
&lt;span id="cb3-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb3-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; us&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;You are running the v4 development version of PyMC3 which currently still lacks key features. You probably want to use the stable v3 instead which you can either install via conda or find on the v3 GitHub branch: https://github.com/pymc-devs/pymc3/tree/v3&lt;/code&gt;&lt;/pre&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb5-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;filterwarnings(&lt;span class="st"&gt;'ignore'&lt;/span&gt;, category&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="pp"&gt;UserWarning&lt;/span&gt;, module&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'aesara'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb5-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb5-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;filterwarnings(&lt;span class="st"&gt;'ignore'&lt;/span&gt;, category&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="pp"&gt;UserWarning&lt;/span&gt;, module&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'arviz'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb5-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb5-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;filterwarnings(&lt;span class="st"&gt;'ignore'&lt;/span&gt;, category&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="pp"&gt;UserWarning&lt;/span&gt;, module&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'pandas'&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb6-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plt.rcParams[&lt;span class="st"&gt;'figure.figsize'&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb6-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.&lt;span class="bu"&gt;set&lt;/span&gt;(color_codes&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="load-and-transform-the-data"&gt;Load and Transform the Data&lt;/h2&gt;
&lt;p&gt;We begin by downloading the data from the GSAF and loading the relevant columns into a Pandas data frame.&lt;/p&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb7-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb7-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%%&lt;/span&gt;bash&lt;/span&gt;
&lt;span id="cb7-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb7-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;DATA_URL&lt;span class="op"&gt;=&lt;/span&gt;http:&lt;span class="op"&gt;//&lt;/span&gt;www.sharkattackfile.net&lt;span class="op"&gt;/&lt;/span&gt;spreadsheets&lt;span class="op"&gt;/&lt;/span&gt;GSAF5.xls&lt;/span&gt;
&lt;span id="cb7-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb7-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;DATA_DEST&lt;span class="op"&gt;=&lt;/span&gt;.&lt;span class="op"&gt;/&lt;/span&gt;data&lt;span class="op"&gt;/&lt;/span&gt;GSAF5.xls&lt;/span&gt;
&lt;span id="cb7-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb7-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb7-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb7-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;if&lt;/span&gt; [[ &lt;span class="op"&gt;!&lt;/span&gt; &lt;span class="op"&gt;-&lt;/span&gt;e $DATA_DEST ]]&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb7-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;then&lt;/span&gt;
&lt;span id="cb7-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb7-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wget &lt;span class="op"&gt;-&lt;/span&gt;q &lt;span class="op"&gt;-&lt;/span&gt;O $DATA_DEST $DATA_URL&lt;/span&gt;
&lt;span id="cb7-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb7-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fi&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb8-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;full_df &lt;span class="op"&gt;=&lt;/span&gt; pd.read_excel(&lt;span class="st"&gt;'./data/GSAF5.xls'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb8-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        usecols&lt;span class="op"&gt;=&lt;/span&gt;[&lt;/span&gt;
&lt;span id="cb8-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb8-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                           &lt;span class="st"&gt;"Case Number"&lt;/span&gt;, &lt;span class="st"&gt;"Date"&lt;/span&gt;, &lt;span class="st"&gt;"Type"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb8-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                           &lt;span class="st"&gt;"Country"&lt;/span&gt;, &lt;span class="st"&gt;"Area"&lt;/span&gt;, &lt;span class="st"&gt;"Location"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb8-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                           &lt;span class="st"&gt;"Fatal (Y/N)"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb8-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        ],&lt;/span&gt;
&lt;span id="cb8-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb8-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        index_col&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Case Number"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb8-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb8-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;full_df[&lt;span class="st"&gt;"Date"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; full_df[&lt;span class="st"&gt;"Date"&lt;/span&gt;].&lt;span class="bu"&gt;apply&lt;/span&gt;(pd.to_datetime, errors&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'coerce'&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb9-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;full_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Date
&lt;/th&gt;
&lt;th&gt;
Type
&lt;/th&gt;
&lt;th&gt;
Country
&lt;/th&gt;
&lt;th&gt;
Area
&lt;/th&gt;
&lt;th&gt;
Location
&lt;/th&gt;
&lt;th&gt;
Fatal (Y/N)
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Case Number
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
2021.06.14.b
&lt;/th&gt;
&lt;td&gt;
2021-06-14
&lt;/td&gt;
&lt;td&gt;
Unprovoked
&lt;/td&gt;
&lt;td&gt;
USA
&lt;/td&gt;
&lt;td&gt;
Florida
&lt;/td&gt;
&lt;td&gt;
New Smyrna Beach, Volusia County
&lt;/td&gt;
&lt;td&gt;
N
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2021.06.14.a
&lt;/th&gt;
&lt;td&gt;
2021-06-14
&lt;/td&gt;
&lt;td&gt;
Unprovoked
&lt;/td&gt;
&lt;td&gt;
USA
&lt;/td&gt;
&lt;td&gt;
Florida
&lt;/td&gt;
&lt;td&gt;
New Smyrna Beach, Volusia County
&lt;/td&gt;
&lt;td&gt;
N
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2021.06.12
&lt;/th&gt;
&lt;td&gt;
2021-06-12
&lt;/td&gt;
&lt;td&gt;
Provoked
&lt;/td&gt;
&lt;td&gt;
ENGLAND
&lt;/td&gt;
&lt;td&gt;
West Sussex
&lt;/td&gt;
&lt;td&gt;
Littlehampton
&lt;/td&gt;
&lt;td&gt;
N
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2021.06.11
&lt;/th&gt;
&lt;td&gt;
2021-06-11
&lt;/td&gt;
&lt;td&gt;
Unprovoked
&lt;/td&gt;
&lt;td&gt;
AUSTRALIA
&lt;/td&gt;
&lt;td&gt;
Western Australia
&lt;/td&gt;
&lt;td&gt;
Five Fingers Reef
&lt;/td&gt;
&lt;td&gt;
N
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2021.05.23
&lt;/th&gt;
&lt;td&gt;
2021-05-23
&lt;/td&gt;
&lt;td&gt;
Unprovoked
&lt;/td&gt;
&lt;td&gt;
USA
&lt;/td&gt;
&lt;td&gt;
South Carolina
&lt;/td&gt;
&lt;td&gt;
Burkes Beach, Hilton Head, Beaufort County
&lt;/td&gt;
&lt;td&gt;
N
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb10"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb10-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb10-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;full_df.tail()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Date
&lt;/th&gt;
&lt;th&gt;
Type
&lt;/th&gt;
&lt;th&gt;
Country
&lt;/th&gt;
&lt;th&gt;
Area
&lt;/th&gt;
&lt;th&gt;
Location
&lt;/th&gt;
&lt;th&gt;
Fatal (Y/N)
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Case Number
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
NaN
&lt;/th&gt;
&lt;td&gt;
NaT
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
NaN
&lt;/th&gt;
&lt;td&gt;
NaT
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
NaN
&lt;/th&gt;
&lt;td&gt;
NaT
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
NaN
&lt;/th&gt;
&lt;td&gt;
NaT
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
xx
&lt;/th&gt;
&lt;td&gt;
NaT
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;We can already see by inspecting the data frame that there will be quite a bit of missing data to handle.&lt;/p&gt;
&lt;div class="sourceCode" id="cb11"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb11-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb11-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;full_df.index.isnull().mean()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;0.6595373706846449&lt;/code&gt;&lt;/pre&gt;
&lt;div class="sourceCode" id="cb13"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb13-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb13-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;full_df.isnull().mean()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Date           0.775621
Type           0.742880
Country        0.744391
Area           0.760587
Location       0.763726
Fatal (Y/N)    0.763842
dtype: float64&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We begin by filtering out rows with missing data in important columns.&lt;/p&gt;
&lt;div class="sourceCode" id="cb15"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb15-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb15-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;FILTERS &lt;span class="op"&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb15-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb15-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;~&lt;/span&gt;full_df.index.isnull(),&lt;/span&gt;
&lt;span id="cb15-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb15-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;~&lt;/span&gt;full_df[&lt;span class="st"&gt;"Date"&lt;/span&gt;].isnull(),&lt;/span&gt;
&lt;span id="cb15-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb15-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;~&lt;/span&gt;full_df[&lt;span class="st"&gt;"Type"&lt;/span&gt;].isnull()&lt;/span&gt;
&lt;span id="cb15-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb15-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb16"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb16-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb16-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(full_df[&lt;span class="bu"&gt;reduce&lt;/span&gt;(np.logical_and, FILTERS)]&lt;/span&gt;
&lt;span id="cb16-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb16-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .isnull()&lt;/span&gt;
&lt;span id="cb16-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb16-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .mean())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Date           0.000000
Type           0.000000
Country        0.004843
Area           0.052413
Location       0.061927
Fatal (Y/N)    0.079398
dtype: float64&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We see now that there is significantly less missing data, so we proceed to examine various aspects of the data.&lt;/p&gt;
&lt;div class="sourceCode" id="cb18"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb18-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb18-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; (full_df[&lt;span class="bu"&gt;reduce&lt;/span&gt;(np.logical_and, FILTERS)]&lt;/span&gt;
&lt;span id="cb18-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb18-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             [&lt;span class="st"&gt;"Type"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb18-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb18-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             .value_counts()&lt;/span&gt;
&lt;span id="cb18-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb18-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             .plot(kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'barh'&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb18-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb18-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb18-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb18-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb18-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Number of attacks"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb18-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb18-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb18-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.invert_yaxis()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb18-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Type of attack"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_19_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Unprovoked attacks are by far the most common. We will focus our analysis on this type of attack.&lt;/p&gt;
&lt;div class="sourceCode" id="cb19"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb19-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb19-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;FILTERS.append(full_df[&lt;span class="st"&gt;"Type"&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="st"&gt;"Unprovoked"&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb20"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb20-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb20-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; (full_df[&lt;span class="bu"&gt;reduce&lt;/span&gt;(np.logical_and, FILTERS)]&lt;/span&gt;
&lt;span id="cb20-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb20-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             [&lt;span class="st"&gt;"Country"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb20-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb20-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             .value_counts()&lt;/span&gt;
&lt;span id="cb20-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb20-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             .plot(kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'barh'&lt;/span&gt;, figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;30&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb20-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb20-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb20-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb20-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb20-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Number of unprovoked attacks"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb20-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb20-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb20-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.invert_yaxis()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb20-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Country"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_22_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;While the data contain information about attacks in many countries, we will focus on the United States. This focus is due partially to the fact that I was in New Jersey when considering this problem, and partially due to the fact that finding standardized data across countries can be more challenging than within different regions of a single country.&lt;/p&gt;
&lt;div class="sourceCode" id="cb21"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb21-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb21-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;FILTERS.append(full_df[&lt;span class="st"&gt;"Country"&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="st"&gt;"USA"&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb22"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb22-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb22-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; (full_df[&lt;span class="bu"&gt;reduce&lt;/span&gt;(np.logical_and, FILTERS)]&lt;/span&gt;
&lt;span id="cb22-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb22-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;[&lt;span class="st"&gt;"Area"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb22-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb22-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;.value_counts()&lt;/span&gt;
&lt;span id="cb22-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb22-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;.plot(kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'barh'&lt;/span&gt;, figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;12&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb22-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb22-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb22-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb22-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb22-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Number of unprovoked attacks"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb22-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb22-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb22-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.invert_yaxis()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb22-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Country"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_25_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that for unprovoked attacks in the United States, &lt;code&gt;Area&lt;/code&gt; roughly corresponds to state, with some territories included as well. Since most of the territories appear very rarely, we restrict our analysis to states so that it is easier to find information about them.&lt;/p&gt;
&lt;div class="sourceCode" id="cb23"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb23-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb23-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;FILTERS.append(&lt;/span&gt;
&lt;span id="cb23-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb23-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;full_df[&lt;span class="st"&gt;"Area"&lt;/span&gt;].isin([&lt;/span&gt;
&lt;span id="cb23-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb23-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;state.name &lt;span class="cf"&gt;for&lt;/span&gt; state &lt;span class="kw"&gt;in&lt;/span&gt; us.states.STATES&lt;/span&gt;
&lt;span id="cb23-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb23-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;])&lt;/span&gt;
&lt;span id="cb23-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb23-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally we look at how the number of shark attacks has changed over time.&lt;/p&gt;
&lt;div class="sourceCode" id="cb24"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb24-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb24-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; (full_df.assign(Year&lt;span class="op"&gt;=&lt;/span&gt;full_df[&lt;span class="st"&gt;"Date"&lt;/span&gt;].dt.year)&lt;/span&gt;
&lt;span id="cb24-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb24-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             [&lt;span class="bu"&gt;reduce&lt;/span&gt;(np.logical_and, FILTERS)]&lt;/span&gt;
&lt;span id="cb24-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb24-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             [&lt;span class="st"&gt;"Year"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb24-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb24-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             .value_counts()&lt;/span&gt;
&lt;span id="cb24-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb24-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             .sort_index()&lt;/span&gt;
&lt;span id="cb24-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb24-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             .plot())&lt;/span&gt;
&lt;span id="cb24-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb24-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb24-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb24-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Year"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb24-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Unprovoked shark attacks&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;in the United States"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_29_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that the number of shark attacks has increased over time. This phenomenon is likely partially due to population growth and partially due to improved reporting mechanisms for shark attacks. We willk keep a relatively modern focus an analysze shark attacks between 1960 and 2020.&lt;/p&gt;
&lt;div class="sourceCode" id="cb25"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb25-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb25-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;YEAR_RANGE &lt;span class="op"&gt;=&lt;/span&gt; (&lt;span class="dv"&gt;1960&lt;/span&gt;, &lt;span class="dv"&gt;2020&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb25-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb25-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb25-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb25-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;FILTERS.append(full_df[&lt;span class="st"&gt;"Date"&lt;/span&gt;].dt.year.between(&lt;span class="op"&gt;*&lt;/span&gt;YEAR_RANGE))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now that we have defined the set of attacks we will model, we produce another data frame including only these attacks and make some light transformations of the data.&lt;/p&gt;
&lt;div class="sourceCode" id="cb26"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb26-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb26-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df &lt;span class="op"&gt;=&lt;/span&gt; (full_df[&lt;span class="bu"&gt;reduce&lt;/span&gt;(np.logical_and, FILTERS)]&lt;/span&gt;
&lt;span id="cb26-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb26-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             .copy()&lt;/span&gt;
&lt;span id="cb26-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb26-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             .rename(columns&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;"Area"&lt;/span&gt;: &lt;span class="st"&gt;"State"&lt;/span&gt;}))&lt;/span&gt;
&lt;span id="cb26-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb26-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df[&lt;span class="st"&gt;"Year"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; df[&lt;span class="st"&gt;"Date"&lt;/span&gt;].dt.year&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb27"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb27-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb27-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Date
&lt;/th&gt;
&lt;th&gt;
Type
&lt;/th&gt;
&lt;th&gt;
Country
&lt;/th&gt;
&lt;th&gt;
State
&lt;/th&gt;
&lt;th&gt;
Location
&lt;/th&gt;
&lt;th&gt;
Fatal (Y/N)
&lt;/th&gt;
&lt;th&gt;
Year
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Case Number
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
2020.12.30
&lt;/th&gt;
&lt;td&gt;
2020-12-30
&lt;/td&gt;
&lt;td&gt;
Unprovoked
&lt;/td&gt;
&lt;td&gt;
USA
&lt;/td&gt;
&lt;td&gt;
California
&lt;/td&gt;
&lt;td&gt;
Coronado, San Diego County
&lt;/td&gt;
&lt;td&gt;
N
&lt;/td&gt;
&lt;td&gt;
2020
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2020.12.08
&lt;/th&gt;
&lt;td&gt;
2020-12-08
&lt;/td&gt;
&lt;td&gt;
Unprovoked
&lt;/td&gt;
&lt;td&gt;
USA
&lt;/td&gt;
&lt;td&gt;
Hawaii
&lt;/td&gt;
&lt;td&gt;
Honolua Bay
&lt;/td&gt;
&lt;td&gt;
Y
&lt;/td&gt;
&lt;td&gt;
2020
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2020.12.06.b
&lt;/th&gt;
&lt;td&gt;
2020-12-06
&lt;/td&gt;
&lt;td&gt;
Unprovoked
&lt;/td&gt;
&lt;td&gt;
USA
&lt;/td&gt;
&lt;td&gt;
Oregon
&lt;/td&gt;
&lt;td&gt;
Seaside Cove, Clatsop County
&lt;/td&gt;
&lt;td&gt;
N
&lt;/td&gt;
&lt;td&gt;
2020
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2020.11.26
&lt;/th&gt;
&lt;td&gt;
2020-11-26
&lt;/td&gt;
&lt;td&gt;
Unprovoked
&lt;/td&gt;
&lt;td&gt;
USA
&lt;/td&gt;
&lt;td&gt;
Hawaii
&lt;/td&gt;
&lt;td&gt;
Maui
&lt;/td&gt;
&lt;td&gt;
N
&lt;/td&gt;
&lt;td&gt;
2020
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2020.10.31
&lt;/th&gt;
&lt;td&gt;
2020-10-31
&lt;/td&gt;
&lt;td&gt;
Unprovoked
&lt;/td&gt;
&lt;td&gt;
USA
&lt;/td&gt;
&lt;td&gt;
Florida
&lt;/td&gt;
&lt;td&gt;
Ormond Beach
&lt;/td&gt;
&lt;td&gt;
N
&lt;/td&gt;
&lt;td&gt;
2020
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb28"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb28-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb28-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df.tail()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Date
&lt;/th&gt;
&lt;th&gt;
Type
&lt;/th&gt;
&lt;th&gt;
Country
&lt;/th&gt;
&lt;th&gt;
State
&lt;/th&gt;
&lt;th&gt;
Location
&lt;/th&gt;
&lt;th&gt;
Fatal (Y/N)
&lt;/th&gt;
&lt;th&gt;
Year
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Case Number
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
1904.00.00.a
&lt;/th&gt;
&lt;td&gt;
1970-01-01 00:00:00.000001904
&lt;/td&gt;
&lt;td&gt;
Unprovoked
&lt;/td&gt;
&lt;td&gt;
USA
&lt;/td&gt;
&lt;td&gt;
Hawaii
&lt;/td&gt;
&lt;td&gt;
Off Diamond Head, Honolulu, O’ahu
&lt;/td&gt;
&lt;td&gt;
Y
&lt;/td&gt;
&lt;td&gt;
1970
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1896.00.00.b
&lt;/th&gt;
&lt;td&gt;
1970-01-01 00:00:00.000001896
&lt;/td&gt;
&lt;td&gt;
Unprovoked
&lt;/td&gt;
&lt;td&gt;
USA
&lt;/td&gt;
&lt;td&gt;
Florida
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
Y
&lt;/td&gt;
&lt;td&gt;
1970
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1883.00.00.a
&lt;/th&gt;
&lt;td&gt;
1970-01-01 00:00:00.000001883
&lt;/td&gt;
&lt;td&gt;
Unprovoked
&lt;/td&gt;
&lt;td&gt;
USA
&lt;/td&gt;
&lt;td&gt;
South Carolina
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
Y
&lt;/td&gt;
&lt;td&gt;
1970
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1882.00.00.b
&lt;/th&gt;
&lt;td&gt;
1970-01-01 00:00:00.000001882
&lt;/td&gt;
&lt;td&gt;
Unprovoked
&lt;/td&gt;
&lt;td&gt;
USA
&lt;/td&gt;
&lt;td&gt;
Florida
&lt;/td&gt;
&lt;td&gt;
In the bay near the naval yard at Pensacola, E…
&lt;/td&gt;
&lt;td&gt;
N
&lt;/td&gt;
&lt;td&gt;
1970
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1852.00.00
&lt;/th&gt;
&lt;td&gt;
1970-01-01 00:00:00.000001852
&lt;/td&gt;
&lt;td&gt;
Unprovoked
&lt;/td&gt;
&lt;td&gt;
USA
&lt;/td&gt;
&lt;td&gt;
South Carolina
&lt;/td&gt;
&lt;td&gt;
Mount Pleasant, Charleston County
&lt;/td&gt;
&lt;td&gt;
Y
&lt;/td&gt;
&lt;td&gt;
1970
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb29"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb29-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb29-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df.shape&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;(1514, 7)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After applying these filters, just over 1,500 attacks remain. This analysis will focus on the number of shark attacks in a state in a given year. Subsequent posts may analyze other aspects of this data. First we count the number of attacks in a given state in a given year. (We will shorten the phrase “unprovoked shark attacks in the United States between 1960 and 2020” to “attacks” for the remainder of the post.)&lt;/p&gt;
&lt;div class="sourceCode" id="cb31"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb31-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb31-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;attacks_nz &lt;span class="op"&gt;=&lt;/span&gt; (df.groupby([&lt;span class="st"&gt;"State"&lt;/span&gt;, &lt;span class="st"&gt;"Year"&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb31-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb31-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .size()&lt;/span&gt;
&lt;span id="cb31-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb31-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .rename(&lt;span class="st"&gt;"Attacks"&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb32"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb32-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb32-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;attacks_nz.describe()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;count    333.000000
mean       4.546547
std        6.527174
min        1.000000
25%        1.000000
50%        2.000000
75%        5.000000
max       38.000000
Name: Attacks, dtype: float64&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The series &lt;code&gt;attacks_nz&lt;/code&gt; includes a row only when there was at least one attack in that state in that year. We also want to include zero entries for state/year combinations that saw now attacks, which we do now by reindexing &lt;code&gt;attacks_nz&lt;/code&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb34"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb34-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb34-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;attacks_index &lt;span class="op"&gt;=&lt;/span&gt; (pd.MultiIndex.from_product((&lt;/span&gt;
&lt;span id="cb34-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb34-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        attacks_nz.index&lt;/span&gt;
&lt;span id="cb34-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb34-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                  .get_level_values(&lt;span class="st"&gt;"State"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb34-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb34-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                  .unique(),&lt;/span&gt;
&lt;span id="cb34-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb34-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        YEAR_RANGE[&lt;span class="dv"&gt;0&lt;/span&gt;] &lt;span class="op"&gt;+&lt;/span&gt; np.arange(attacks_nz.index&lt;/span&gt;
&lt;span id="cb34-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb34-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                            .get_level_values(&lt;span class="st"&gt;"Year"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb34-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb34-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                            .values&lt;/span&gt;
&lt;span id="cb34-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb34-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                            .ptp())))&lt;/span&gt;
&lt;span id="cb34-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb34-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   .rename(&lt;span class="st"&gt;"Year"&lt;/span&gt;, level&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb34-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb34-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;attacks_df &lt;span class="op"&gt;=&lt;/span&gt; (attacks_nz.reindex(attacks_index, fill_value&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb34-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb34-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        .astype(np.int64)&lt;/span&gt;
&lt;span id="cb34-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb34-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        .to_frame())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb35"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb35-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb35-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;attacks_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Attacks
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
State
&lt;/th&gt;
&lt;th&gt;
Year
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th rowspan="5" valign="top"&gt;
Alabama
&lt;/th&gt;
&lt;th&gt;
1960
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1961
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1962
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1963
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1964
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb36"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb36-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb36-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;attacks_df.tail()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Attacks
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
State
&lt;/th&gt;
&lt;th&gt;
Year
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th rowspan="5" valign="top"&gt;
Washington
&lt;/th&gt;
&lt;th&gt;
2015
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2016
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2017
&lt;/th&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2018
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2019
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h2 id="modeling"&gt;Modeling&lt;/h2&gt;
&lt;p&gt;We now turn to modeling the data.&lt;/p&gt;
&lt;div class="sourceCode" id="cb37"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb37-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb37-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; attacks_df[&lt;span class="st"&gt;"Attacks"&lt;/span&gt;].hist(bins&lt;span class="op"&gt;=&lt;/span&gt;attacks_df[&lt;span class="st"&gt;"Attacks"&lt;/span&gt;].&lt;span class="bu"&gt;max&lt;/span&gt;() &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb37-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb37-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb37-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb37-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Number of attacks"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb37-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb37-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb37-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb37-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb37-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb37-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Number of state-years"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_46_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that the vast majority of state-years have no shark attacks, and that when there is at least one attack, there are rarely very many. We see that the &lt;a href="https://en.wikipedia.org/wiki/Index_of_dispersion"&gt;index of dispersion&lt;/a&gt; is significantly larger than one, so the data shows overdispersion.&lt;/p&gt;
&lt;div class="sourceCode" id="cb38"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb38-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb38-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;attacks_df.var() &lt;span class="op"&gt;/&lt;/span&gt; attacks_df.mean()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Attacks    12.729978
dtype: float64&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="negative-binomial"&gt;Negative Binomial&lt;/h3&gt;
&lt;p&gt;Due to this overdispersion, we begin with a &lt;a href="https://en.wikipedia.org/wiki/Negative_binomial_distribution"&gt;Negative Binomial&lt;/a&gt; model.&lt;/p&gt;
&lt;p&gt;Let &lt;span class="math inline"&gt;\(y_{i, t}\)&lt;/span&gt; represent the number of attacks in the &lt;span class="math inline"&gt;\(i\)&lt;/span&gt;-th state in year &lt;span class="math inline"&gt;\(t\)&lt;/span&gt;. We use the priors&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[ 
\begin{align*}
    \mu
        &amp;amp; \sim \operatorname{Lognormal}(0, 2.5^2) \\
    \alpha
        &amp;amp; \sim \operatorname{Half}-N(2.5^2).
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb40"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb40-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb40-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; nb_model:&lt;/span&gt;
&lt;span id="cb40-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb40-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; pm.Lognormal(&lt;span class="st"&gt;"μ"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb40-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb40-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    α &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"α"&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now let &lt;span class="math inline"&gt;\(y_{i, t} \sim NB(\mu, \alpha)\)&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb41"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb41-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb41-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;y &lt;span class="op"&gt;=&lt;/span&gt; attacks_df[&lt;span class="st"&gt;"Attacks"&lt;/span&gt;].values&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb42"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb42-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb42-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; nb_model:&lt;/span&gt;
&lt;span id="cb42-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb42-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs &lt;span class="op"&gt;=&lt;/span&gt; pm.NegativeBinomial(&lt;span class="st"&gt;"obs"&lt;/span&gt;, μ, α, observed&lt;span class="op"&gt;=&lt;/span&gt;y)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We use &lt;a href="https://docs.pymc.io/"&gt;&lt;code&gt;pymc3&lt;/code&gt;&lt;/a&gt; to sample from the posterior distribution of this model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb43"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb43-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb43-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;CHAINS &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb43-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb43-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SEED &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;12345&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb43-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb43-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb43-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb43-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SAMPLE_KWARGS &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb43-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb43-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'cores'&lt;/span&gt;: CHAINS,&lt;/span&gt;
&lt;span id="cb43-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb43-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'random_seed'&lt;/span&gt;: [SEED &lt;span class="op"&gt;+&lt;/span&gt; i &lt;span class="cf"&gt;for&lt;/span&gt; i &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;range&lt;/span&gt;(CHAINS)],&lt;/span&gt;
&lt;span id="cb43-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb43-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'return_inferencedata'&lt;/span&gt;: &lt;span class="va"&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb43-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb43-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb44"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb44-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb44-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; nb_model:&lt;/span&gt;
&lt;span id="cb44-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb44-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    nb_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [μ, α]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="6000" class max="6000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [6000/6000 00:15&amp;lt;00:00 Sampling 3 chains, 0 divergences]&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Sampling 3 chains for 1_000 tune and 1_000 draw iterations (3_000 + 3_000 draws total) took 20 seconds.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The standard sampling diagnostics (energy plots, BFMI, and &lt;span class="math inline"&gt;\(\hat{R}\)&lt;/span&gt;) show no cause for concern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb47"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb47-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; make_diagnostic_plots(trace, axes&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, min_mult&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.995&lt;/span&gt;, max_mult&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;1.005&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb47-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; axes &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb47-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb47-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                 sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb47-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                 figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;16&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb47-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb47-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    az.plot_energy(trace, ax&lt;span class="op"&gt;=&lt;/span&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb47-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb47-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb47-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    rhat &lt;span class="op"&gt;=&lt;/span&gt; az.rhat(trace).&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;
&lt;span id="cb47-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    axes[&lt;span class="dv"&gt;1&lt;/span&gt;].barh(np.arange(&lt;span class="bu"&gt;len&lt;/span&gt;(rhat.variables)), rhat.to_array(),&lt;/span&gt;
&lt;span id="cb47-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 tick_label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="bu"&gt;list&lt;/span&gt;(rhat.variables.keys()))&lt;/span&gt;
&lt;span id="cb47-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    axes[&lt;span class="dv"&gt;1&lt;/span&gt;].axvline(&lt;span class="dv"&gt;1&lt;/span&gt;, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, ls&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'--'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb47-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb47-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_xlim(&lt;/span&gt;
&lt;span id="cb47-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        min_mult &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="bu"&gt;min&lt;/span&gt;(rhat.&lt;span class="bu"&gt;min&lt;/span&gt;().to_array().&lt;span class="bu"&gt;min&lt;/span&gt;(), &lt;span class="dv"&gt;1&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb47-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        max_mult &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="bu"&gt;max&lt;/span&gt;(rhat.&lt;span class="bu"&gt;max&lt;/span&gt;().to_array().&lt;span class="bu"&gt;max&lt;/span&gt;(), &lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb47-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb47-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_xlabel(&lt;span class="vs"&gt;r"$\hat&lt;/span&gt;&lt;span class="sc"&gt;{R}&lt;/span&gt;&lt;span class="vs"&gt;$"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb47-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb47-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_ylabel(&lt;span class="st"&gt;"Variable"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb47-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb47-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb47-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; fig, axes&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb48"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb48-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb48-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_diagnostic_plots(nb_trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_59_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Examining the posterior distribution for &lt;span class="math inline"&gt;\(\mu\)&lt;/span&gt; shows that the model will predicts more than one shark attack per year on average.&lt;/p&gt;
&lt;div class="sourceCode" id="cb49"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb49-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb49-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_posterior(nb_trace, var_names&lt;span class="op"&gt;=&lt;/span&gt;[&lt;span class="st"&gt;"μ"&lt;/span&gt;])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_61_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;This prediction of about one shark attack per state per year captures nationwide average well enough, but is clearly not very useful at the state level. We see specifically how bad it is by examining the posterior predictions of the model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb50"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb50-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb50-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; nb_model:&lt;/span&gt;
&lt;span id="cb50-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb50-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    nb_pp_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample_posterior_predictive(nb_trace)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="3000" class max="3000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [3000/3000 00:05&amp;lt;00:00]&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;First we produce a long data frame where each row represents a single posterior predictive sample from the distribution of the number of attacks in a given state-year. This data frame will be the basis for all of our posterior predictive plots.&lt;/p&gt;
&lt;div class="sourceCode" id="cb51"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb51-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb51-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; make_pp_full_df(pp_obs):&lt;/span&gt;
&lt;span id="cb51-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb51-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; (pd.DataFrame(&lt;/span&gt;
&lt;span id="cb51-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb51-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                {i: samples &lt;span class="cf"&gt;for&lt;/span&gt; i, samples &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;enumerate&lt;/span&gt;(pp_obs)},&lt;/span&gt;
&lt;span id="cb51-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb51-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                index&lt;span class="op"&gt;=&lt;/span&gt;attacks_df.index&lt;/span&gt;
&lt;span id="cb51-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb51-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              )&lt;/span&gt;
&lt;span id="cb51-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb51-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .reset_index()&lt;/span&gt;
&lt;span id="cb51-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb51-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .melt(id_vars&lt;span class="op"&gt;=&lt;/span&gt;[&lt;span class="st"&gt;"State"&lt;/span&gt;, &lt;span class="st"&gt;"Year"&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb51-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb51-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    var_name&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Sample"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb51-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb51-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .set_index([&lt;span class="st"&gt;"State"&lt;/span&gt;, &lt;span class="st"&gt;"Year"&lt;/span&gt;, &lt;span class="st"&gt;"Sample"&lt;/span&gt;]))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb52"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb52-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb52-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;nb_pp_full_df &lt;span class="op"&gt;=&lt;/span&gt; make_pp_full_df(nb_pp_trace[&lt;span class="st"&gt;"obs"&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb53"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb53-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb53-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;nb_pp_full_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
value
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
State
&lt;/th&gt;
&lt;th&gt;
Year
&lt;/th&gt;
&lt;th&gt;
Sample
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th rowspan="5" valign="top"&gt;
Alabama
&lt;/th&gt;
&lt;th&gt;
1960
&lt;/th&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1961
&lt;/th&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1962
&lt;/th&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1963
&lt;/th&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1964
&lt;/th&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb54"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb54-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb54-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ALPHA &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="fl"&gt;0.05&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb55"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb55-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb55-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; summarize_pp_df(pp_full_df, level&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;ALPHA):&lt;/span&gt;
&lt;span id="cb55-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb55-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; level &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb55-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb55-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        level &lt;span class="op"&gt;=&lt;/span&gt; [&lt;span class="st"&gt;"State"&lt;/span&gt;, &lt;span class="st"&gt;"Year"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb55-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb55-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb55-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb55-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; (pp_full_df.groupby(level&lt;span class="op"&gt;=&lt;/span&gt;level)&lt;/span&gt;
&lt;span id="cb55-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb55-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      [&lt;span class="st"&gt;"value"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb55-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb55-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      .agg(&lt;/span&gt;
&lt;span id="cb55-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb55-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                          mean&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'mean'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb55-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb55-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                          &lt;span class="bu"&gt;sum&lt;/span&gt;&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'sum'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb55-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb55-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                          low&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="kw"&gt;lambda&lt;/span&gt; s: s.quantile(alpha &lt;span class="op"&gt;/&lt;/span&gt; &lt;span class="fl"&gt;2.&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb55-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb55-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                          high&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="kw"&gt;lambda&lt;/span&gt; s: s.quantile(&lt;span class="fl"&gt;1.&lt;/span&gt; &lt;span class="op"&gt;-&lt;/span&gt; alpha &lt;span class="op"&gt;/&lt;/span&gt; &lt;span class="fl"&gt;2.&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb55-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb55-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      )&lt;/span&gt;
&lt;span id="cb55-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb55-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      .assign(attacks&lt;span class="op"&gt;=&lt;/span&gt;attacks_df[&lt;span class="st"&gt;"Attacks"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb55-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb55-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                .groupby(level&lt;span class="op"&gt;=&lt;/span&gt;level)&lt;/span&gt;
&lt;span id="cb55-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb55-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                .&lt;span class="bu"&gt;sum&lt;/span&gt;()))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb56"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb56-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb56-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;nb_pp_df &lt;span class="op"&gt;=&lt;/span&gt; summarize_pp_df(nb_pp_full_df)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb57"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb57-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb57-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;nb_pp_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
mean
&lt;/th&gt;
&lt;th&gt;
sum
&lt;/th&gt;
&lt;th&gt;
low
&lt;/th&gt;
&lt;th&gt;
high
&lt;/th&gt;
&lt;th&gt;
attacks
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
State
&lt;/th&gt;
&lt;th&gt;
Year
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th rowspan="5" valign="top"&gt;
Alabama
&lt;/th&gt;
&lt;th&gt;
1960
&lt;/th&gt;
&lt;td&gt;
1.231000
&lt;/td&gt;
&lt;td&gt;
3693
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
12.000
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1961
&lt;/th&gt;
&lt;td&gt;
1.212667
&lt;/td&gt;
&lt;td&gt;
3638
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
12.000
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1962
&lt;/th&gt;
&lt;td&gt;
1.206000
&lt;/td&gt;
&lt;td&gt;
3618
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
11.025
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1963
&lt;/th&gt;
&lt;td&gt;
1.232000
&lt;/td&gt;
&lt;td&gt;
3696
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
12.000
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1964
&lt;/th&gt;
&lt;td&gt;
1.177667
&lt;/td&gt;
&lt;td&gt;
3533
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
11.000
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;The data frame &lt;code&gt;nb_pp_df&lt;/code&gt; contains the posterior predictive mean and posterior predictive quantiles for each state-year combination. We now plot the predictions and actual data, broken down by state.&lt;/p&gt;
&lt;div class="sourceCode" id="cb58"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb58-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; plot_pp_over_time(data&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"mean"&lt;/span&gt;, &lt;span class="op"&gt;*&lt;/span&gt;args, &lt;span class="op"&gt;**&lt;/span&gt;kwargs):&lt;/span&gt;
&lt;span id="cb58-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    pp_df &lt;span class="op"&gt;=&lt;/span&gt; data&lt;/span&gt;
&lt;span id="cb58-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb58-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax &lt;span class="op"&gt;=&lt;/span&gt; plt.gca()&lt;/span&gt;
&lt;span id="cb58-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (pp_df.plot(&lt;span class="st"&gt;"Year"&lt;/span&gt;, y,&lt;/span&gt;
&lt;span id="cb58-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Posterior expected value"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb58-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                ax&lt;span class="op"&gt;=&lt;/span&gt;ax))&lt;/span&gt;
&lt;span id="cb58-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    (pp_df.reset_index()&lt;/span&gt;
&lt;span id="cb58-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          .plot(&lt;span class="st"&gt;"Year"&lt;/span&gt;, &lt;span class="st"&gt;"attacks"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb58-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'scatter'&lt;/span&gt;, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, zorder&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;5&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb58-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Actual"&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;ax))&lt;/span&gt;
&lt;span id="cb58-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb58-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.fill_between(pp_df[&lt;span class="st"&gt;"Year"&lt;/span&gt;], pp_df[&lt;span class="st"&gt;"low"&lt;/span&gt;], pp_df[&lt;span class="st"&gt;"high"&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb58-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb58-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"95% posterior credible interval"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb58-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb58-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_ylabel(&lt;span class="st"&gt;"Number of shark attacks"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb58-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb58-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb58-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; ax&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb59"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb59-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb59-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid &lt;span class="op"&gt;=&lt;/span&gt; sns.FacetGrid(nb_pp_df.reset_index(), col&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"State"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb59-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb59-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     col_wrap&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, aspect&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;1.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb59-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb59-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid.map_dataframe(plot_pp_over_time)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb59-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb59-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb59-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb59-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid.axes[&lt;span class="dv"&gt;0&lt;/span&gt;].legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"upper left"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb59-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb59-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid.set_titles(&lt;span class="st"&gt;"&lt;/span&gt;&lt;span class="sc"&gt;{col_name}&lt;/span&gt;&lt;span class="st"&gt;"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb59-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb59-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid.fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_74_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that the predictions for each state are indeed the same (ignoring some slight Monte Carlo variation), and therefore vastly overpredict shark attacks for most states while massively underpredicting shark attacks for some states.&lt;/p&gt;
&lt;p&gt;The plot below which does not include a time axis further reinforces this point.&lt;/p&gt;
&lt;div class="sourceCode" id="cb60"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb60-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;nb_pp_state_df &lt;span class="op"&gt;=&lt;/span&gt; summarize_pp_df(nb_pp_full_df, level&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"State"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb60-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; (nb_pp_state_df.reset_index()&lt;/span&gt;
&lt;span id="cb60-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    .plot.scatter(&lt;span class="st"&gt;"mean"&lt;/span&gt;, &lt;span class="st"&gt;"State"&lt;/span&gt;, color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb60-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                  xerr&lt;span class="op"&gt;=&lt;/span&gt;nb_pp_state_df[[&lt;span class="st"&gt;"low"&lt;/span&gt;, &lt;span class="st"&gt;"high"&lt;/span&gt;]]&lt;/span&gt;
&lt;span id="cb60-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                     .sub(nb_pp_state_df[&lt;span class="st"&gt;"mean"&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb60-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                          axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb60-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                     .&lt;span class="bu"&gt;abs&lt;/span&gt;()&lt;/span&gt;
&lt;span id="cb60-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                     .values.T,&lt;/span&gt;
&lt;span id="cb60-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                  zorder&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;5&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb60-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                  label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Posterior predictive mean"&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb60-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(attacks_df.reset_index()&lt;/span&gt;
&lt;span id="cb60-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           .plot.scatter(&lt;span class="st"&gt;"Attacks"&lt;/span&gt;, &lt;span class="st"&gt;"State"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb60-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb60-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Actual"&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;ax))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb60-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Number of shark Attacks"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb60-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb60-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.invert_yaxis()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_76_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The predictions from this model are particularly bad for states like California, Florida, Hawaii, and the Carolinas, where years with many shark attacks are relatively more common than they are for other states.&lt;/p&gt;
&lt;h3 id="negative-binomial-regression"&gt;Negative Binomial Regression&lt;/h3&gt;
&lt;p&gt;California, Florida, and to a lesser extent the Carolinas are similar in that they have relatively large populations. All of these states are similar in that their population is relatively concentrated on the coast.&lt;/p&gt;
&lt;p&gt;The table below shows that overdispersion is still quite prevalent when we condition on state, so will use &lt;a href="https://en.wikipedia.org/wiki/Poisson_regression#Overdispersion_and_zero_inflation"&gt;negative binomial regression&lt;/a&gt; to account for the effect of state-level factors on the number of attacks.&lt;/p&gt;
&lt;div class="sourceCode" id="cb61"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb61-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb61-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(attacks_df.groupby(level&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"State"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb61-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb61-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           .var()&lt;/span&gt;
&lt;span id="cb61-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb61-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           .div(attacks_df.groupby(&lt;span class="st"&gt;"State"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb61-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb61-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                          .mean()))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Attacks
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
State
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
Alabama
&lt;/th&gt;
&lt;td&gt;
1.090395
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
California
&lt;/th&gt;
&lt;td&gt;
1.408464
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Connecticut
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Delaware
&lt;/th&gt;
&lt;td&gt;
0.966102
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Florida
&lt;/th&gt;
&lt;td&gt;
8.373881
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Georgia
&lt;/th&gt;
&lt;td&gt;
1.090395
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Hawaii
&lt;/th&gt;
&lt;td&gt;
3.457544
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Louisiana
&lt;/th&gt;
&lt;td&gt;
0.915254
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Maine
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Massachusetts
&lt;/th&gt;
&lt;td&gt;
1.254237
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Mississippi
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
New Jersey
&lt;/th&gt;
&lt;td&gt;
1.457627
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
New York
&lt;/th&gt;
&lt;td&gt;
2.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
North Carolina
&lt;/th&gt;
&lt;td&gt;
2.342930
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Oregon
&lt;/th&gt;
&lt;td&gt;
1.156634
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Rhode Island
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
South Carolina
&lt;/th&gt;
&lt;td&gt;
2.382694
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Texas
&lt;/th&gt;
&lt;td&gt;
1.917465
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Virginia
&lt;/th&gt;
&lt;td&gt;
0.881356
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Washington
&lt;/th&gt;
&lt;td&gt;
0.983051
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;First we load state-leve population and coastline data from Wikipedia.&lt;/p&gt;
&lt;div class="sourceCode" id="cb62"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb62-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb62-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;POP_URL &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="st"&gt;"https://en.wikipedia.org/wiki/List_of_U.S._states_and_territories_by_historical_population"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb62-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb62-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb62-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb62-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;population &lt;span class="op"&gt;=&lt;/span&gt; (pd.read_html(POP_URL)[&lt;span class="dv"&gt;3&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb62-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb62-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .iloc[:&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb62-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb62-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .melt(id_vars&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Name"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb62-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb62-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      var_name&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Year"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb62-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb62-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      value_name&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Population"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb62-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb62-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .rename(columns&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;"Name"&lt;/span&gt;: &lt;span class="st"&gt;"State"&lt;/span&gt;})&lt;/span&gt;
&lt;span id="cb62-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb62-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .fillna(&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb62-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb62-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .astype({&lt;/span&gt;
&lt;span id="cb62-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb62-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    &lt;span class="st"&gt;"Year"&lt;/span&gt;: np.int64,&lt;/span&gt;
&lt;span id="cb62-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb62-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    &lt;span class="st"&gt;"Population"&lt;/span&gt;: np.float64&lt;/span&gt;
&lt;span id="cb62-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb62-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                })&lt;/span&gt;
&lt;span id="cb62-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb62-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .set_index([&lt;span class="st"&gt;"State"&lt;/span&gt;, &lt;span class="st"&gt;"Year"&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb62-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb62-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .sort_index()&lt;/span&gt;
&lt;span id="cb62-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb62-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                [&lt;span class="st"&gt;"Population"&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb63"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb63-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb63-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;population.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;State    Year
Alabama  1960    3266740.0
         1970    3444165.0
         1980    3893888.0
         1990    4040587.0
         2000    4447100.0
Name: Population, dtype: float64&lt;/code&gt;&lt;/pre&gt;
&lt;div class="sourceCode" id="cb65"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb65-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb65-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;population.tail()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;State    Year
Wyoming  1980    469557.0
         1990    453588.0
         2000    493782.0
         2010    563626.0
         2020    576851.0
Name: Population, dtype: float64&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The series &lt;code&gt;population&lt;/code&gt; contains the population of each state according to the United States census conducted every ten years.&lt;/p&gt;
&lt;div class="sourceCode" id="cb67"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb67-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb67-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;COAST_URL &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="st"&gt;"https://en.wikipedia.org/wiki/List_of_U.S._states_and_territories_by_coastline"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb67-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb67-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb67-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;coast_df, _ &lt;span class="op"&gt;=&lt;/span&gt; pd.read_html(COAST_URL)&lt;/span&gt;
&lt;span id="cb67-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb67-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;coast_df &lt;span class="op"&gt;=&lt;/span&gt; (coast_df[[&lt;span class="st"&gt;"State or territory"&lt;/span&gt;, &lt;span class="st"&gt;"Method 1 (CRS)"&lt;/span&gt;, &lt;span class="st"&gt;"Coast/area ratio (ft/mi2)"&lt;/span&gt;]]&lt;/span&gt;
&lt;span id="cb67-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb67-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    .iloc[:&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb67-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb67-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;coast_df.columns &lt;span class="op"&gt;=&lt;/span&gt; coast_df.columns.droplevel(&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb67-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb67-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;coast_df &lt;span class="op"&gt;=&lt;/span&gt; coast_df.drop([&lt;span class="st"&gt;"Rank"&lt;/span&gt;, &lt;span class="st"&gt;"Method 2"&lt;/span&gt;], axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb67-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb67-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;coast_df &lt;span class="op"&gt;=&lt;/span&gt; (coast_df.rename(columns&lt;span class="op"&gt;=&lt;/span&gt;{&lt;/span&gt;
&lt;span id="cb67-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb67-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        &lt;span class="st"&gt;"State or territory"&lt;/span&gt;: &lt;span class="st"&gt;"State"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb67-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb67-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        &lt;span class="st"&gt;"Method 1"&lt;/span&gt;: &lt;span class="st"&gt;"Coastline to area"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb67-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    })&lt;/span&gt;
&lt;span id="cb67-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb67-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    .set_index(&lt;span class="st"&gt;"State"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb67-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb67-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    .sort_index())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb68"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb68-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb68-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;coast_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Coastline
&lt;/th&gt;
&lt;th&gt;
Coastline to area
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
State
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
Alabama
&lt;/th&gt;
&lt;td&gt;
53 mi (85 km)
&lt;/td&gt;
&lt;td&gt;
5.3
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Alaska
&lt;/th&gt;
&lt;td&gt;
6,640 mi (10,690 km)
&lt;/td&gt;
&lt;td&gt;
53
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
American Samoa
&lt;/th&gt;
&lt;td&gt;
–
&lt;/td&gt;
&lt;td&gt;
–
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
California
&lt;/th&gt;
&lt;td&gt;
840 mi (1,350 km)
&lt;/td&gt;
&lt;td&gt;
27
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Connecticut
&lt;/th&gt;
&lt;td&gt;
96 mi (154 km)
&lt;/td&gt;
&lt;td&gt;
91
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb69"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb69-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb69-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;coast_df[&lt;span class="st"&gt;"Coastline"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (&lt;/span&gt;
&lt;span id="cb69-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb69-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    coast_df[&lt;span class="st"&gt;"Coastline"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb69-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb69-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .&lt;span class="bu"&gt;str&lt;/span&gt;.split(expand&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb69-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb69-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .iloc[:, &lt;span class="dv"&gt;0&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb69-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb69-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .&lt;span class="bu"&gt;str&lt;/span&gt;.replace(&lt;span class="st"&gt;","&lt;/span&gt;, &lt;span class="st"&gt;""&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb69-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb69-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .&lt;span class="bu"&gt;str&lt;/span&gt;.replace(&lt;span class="st"&gt;"[–—]"&lt;/span&gt;, &lt;span class="st"&gt;"0"&lt;/span&gt;, regex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb69-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb69-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .astype(np.float64)&lt;/span&gt;
&lt;span id="cb69-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb69-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb69-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb69-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;coast_df[&lt;span class="st"&gt;"Coastline to area"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (&lt;/span&gt;
&lt;span id="cb69-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb69-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    coast_df[&lt;span class="st"&gt;"Coastline to area"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb69-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb69-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .astype(&lt;span class="bu"&gt;str&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb69-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb69-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .&lt;span class="bu"&gt;str&lt;/span&gt;.replace(&lt;span class="st"&gt;"[–—]"&lt;/span&gt;, &lt;span class="st"&gt;"-1"&lt;/span&gt;, regex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb69-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb69-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .astype(np.float64)&lt;/span&gt;
&lt;span id="cb69-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb69-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .replace(&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;, np.nan)&lt;/span&gt;
&lt;span id="cb69-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb69-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb70"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb70-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb70-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;coast_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Coastline
&lt;/th&gt;
&lt;th&gt;
Coastline to area
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
State
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
Alabama
&lt;/th&gt;
&lt;td&gt;
53.0
&lt;/td&gt;
&lt;td&gt;
5.3
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Alaska
&lt;/th&gt;
&lt;td&gt;
6640.0
&lt;/td&gt;
&lt;td&gt;
53.0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
American Samoa
&lt;/th&gt;
&lt;td&gt;
0.0
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
California
&lt;/th&gt;
&lt;td&gt;
840.0
&lt;/td&gt;
&lt;td&gt;
27.0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Connecticut
&lt;/th&gt;
&lt;td&gt;
96.0
&lt;/td&gt;
&lt;td&gt;
91.0
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb71"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb71-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb71-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;coast_df.tail()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Coastline
&lt;/th&gt;
&lt;th&gt;
Coastline to area
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
State
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
U.S. Minor Outlying Islands
&lt;/th&gt;
&lt;td&gt;
0.0
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
U.S. Virgin Islands
&lt;/th&gt;
&lt;td&gt;
0.0
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Virginia
&lt;/th&gt;
&lt;td&gt;
112.0
&lt;/td&gt;
&lt;td&gt;
14.0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Washington
&lt;/th&gt;
&lt;td&gt;
157.0
&lt;/td&gt;
&lt;td&gt;
12.0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Wisconsin
&lt;/th&gt;
&lt;td&gt;
0.0
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;The data frame &lt;code&gt;coast_df&lt;/code&gt; contains the length of a state’s coastline (in miles) as well as the ratio of its coastline to area (in square miles).&lt;/p&gt;
&lt;p&gt;We now combine &lt;code&gt;attacks&lt;/code&gt;, &lt;code&gt;population&lt;/code&gt;, and &lt;code&gt;coast_df&lt;/code&gt; into a single data frame.&lt;/p&gt;
&lt;div class="sourceCode" id="cb72"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb72-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb72-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;attacks_df &lt;span class="op"&gt;=&lt;/span&gt; (attacks_df.merge(coast_df,&lt;/span&gt;
&lt;span id="cb72-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb72-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               left_index&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, right_index&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb72-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb72-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        .merge(population, how&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'left'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb72-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb72-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               left_index&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, right_index&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb72-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb72-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        .fillna(method&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'ffill'&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb73"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb73-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb73-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;attacks_df[&lt;span class="st"&gt;"Population to coastline"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; attacks_df[&lt;span class="st"&gt;"Population"&lt;/span&gt;] &lt;span class="op"&gt;/&lt;/span&gt; attacks_df[&lt;span class="st"&gt;"Coastline"&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb74"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb74-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb74-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;attacks_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Attacks
&lt;/th&gt;
&lt;th&gt;
Coastline
&lt;/th&gt;
&lt;th&gt;
Coastline to area
&lt;/th&gt;
&lt;th&gt;
Population
&lt;/th&gt;
&lt;th&gt;
Population to coastline
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
State
&lt;/th&gt;
&lt;th&gt;
Year
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th rowspan="5" valign="top"&gt;
Alabama
&lt;/th&gt;
&lt;th&gt;
1960
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
53.0
&lt;/td&gt;
&lt;td&gt;
5.3
&lt;/td&gt;
&lt;td&gt;
3266740.0
&lt;/td&gt;
&lt;td&gt;
61636.603774
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1961
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
53.0
&lt;/td&gt;
&lt;td&gt;
5.3
&lt;/td&gt;
&lt;td&gt;
3266740.0
&lt;/td&gt;
&lt;td&gt;
61636.603774
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1962
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
53.0
&lt;/td&gt;
&lt;td&gt;
5.3
&lt;/td&gt;
&lt;td&gt;
3266740.0
&lt;/td&gt;
&lt;td&gt;
61636.603774
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1963
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
53.0
&lt;/td&gt;
&lt;td&gt;
5.3
&lt;/td&gt;
&lt;td&gt;
3266740.0
&lt;/td&gt;
&lt;td&gt;
61636.603774
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1964
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
53.0
&lt;/td&gt;
&lt;td&gt;
5.3
&lt;/td&gt;
&lt;td&gt;
3266740.0
&lt;/td&gt;
&lt;td&gt;
61636.603774
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb75"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb75-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb75-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;attacks_df.tail()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Attacks
&lt;/th&gt;
&lt;th&gt;
Coastline
&lt;/th&gt;
&lt;th&gt;
Coastline to area
&lt;/th&gt;
&lt;th&gt;
Population
&lt;/th&gt;
&lt;th&gt;
Population to coastline
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
State
&lt;/th&gt;
&lt;th&gt;
Year
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th rowspan="5" valign="top"&gt;
Washington
&lt;/th&gt;
&lt;th&gt;
2015
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
157.0
&lt;/td&gt;
&lt;td&gt;
12.0
&lt;/td&gt;
&lt;td&gt;
6724540.0
&lt;/td&gt;
&lt;td&gt;
42831.464968
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2016
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
157.0
&lt;/td&gt;
&lt;td&gt;
12.0
&lt;/td&gt;
&lt;td&gt;
6724540.0
&lt;/td&gt;
&lt;td&gt;
42831.464968
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2017
&lt;/th&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
157.0
&lt;/td&gt;
&lt;td&gt;
12.0
&lt;/td&gt;
&lt;td&gt;
6724540.0
&lt;/td&gt;
&lt;td&gt;
42831.464968
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2018
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
157.0
&lt;/td&gt;
&lt;td&gt;
12.0
&lt;/td&gt;
&lt;td&gt;
6724540.0
&lt;/td&gt;
&lt;td&gt;
42831.464968
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2019
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
157.0
&lt;/td&gt;
&lt;td&gt;
12.0
&lt;/td&gt;
&lt;td&gt;
6724540.0
&lt;/td&gt;
&lt;td&gt;
42831.464968
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;Here the population data is from the most recent United States census prior to the year in question (thanks to &lt;code&gt;fillna(method='ffill')&lt;/code&gt;. Below we plot the relationship between the four explanatory variables and the number of attacks.&lt;/p&gt;
&lt;div class="sourceCode" id="cb76"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb76-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb76-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, nrows&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb76-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb76-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;12&lt;/span&gt;, &lt;span class="dv"&gt;9&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb76-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb76-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb76-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb76-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;for&lt;/span&gt; col, ax &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;zip&lt;/span&gt;(attacks_df.columns[&lt;span class="dv"&gt;1&lt;/span&gt;:], axes.ravel()):&lt;/span&gt;
&lt;span id="cb76-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb76-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    attacks_df.plot.scatter(col, &lt;span class="st"&gt;"Attacks"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb76-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb76-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                            color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb76-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb76-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                            ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb76-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb76-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb76-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb76-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb76-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb76-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_yscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb76-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb76-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb76-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb76-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_97_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The top two and bottom two plots are very similar. We choose to use coastline length (in miles) and population as our predictors since those relationships seem to be a bit more linear on the log-log scale.&lt;/p&gt;
&lt;p&gt;We standardize the logarithms of coastline length and population before using them as predictors.&lt;/p&gt;
&lt;div class="sourceCode" id="cb77"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb77-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb77-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; standardize(x):&lt;/span&gt;
&lt;span id="cb77-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb77-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; (x &lt;span class="op"&gt;-&lt;/span&gt; x.mean()) &lt;span class="op"&gt;/&lt;/span&gt; x.std()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb78"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb78-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb78-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;log_coast &lt;span class="op"&gt;=&lt;/span&gt; np.log(attacks_df[&lt;span class="st"&gt;"Coastline"&lt;/span&gt;].values)&lt;/span&gt;
&lt;span id="cb78-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb78-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;x_coast &lt;span class="op"&gt;=&lt;/span&gt; at.constant(standardize(log_coast))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb79"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb79-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb79-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;log_pop &lt;span class="op"&gt;=&lt;/span&gt; np.log(attacks_df[&lt;span class="st"&gt;"Population"&lt;/span&gt;].values)&lt;/span&gt;
&lt;span id="cb79-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb79-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;x_pop &lt;span class="op"&gt;=&lt;/span&gt; at.constant(standardize(log_pop))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We use the priors &lt;span class="math inline"&gt;\(\beta_0, \beta_{\text{coast}}, \beta_{\text{pop}} \sim N(0, 2.5^2)\)&lt;/span&gt; on the regression coefficients and set&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[\eta_{i, t} = \beta_0 + \beta_{\text{coast}} \cdot x_{\text{coast}, i} + \beta_{\text{pop}} \cdot x_{\text{pop}, i, t}.\]&lt;/span&gt; The mean is then &lt;span class="math inline"&gt;\(\mu_{i, t} = \exp \eta_{i, t}.\)&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb80"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb80-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb80-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; nb_reg_model:&lt;/span&gt;
&lt;span id="cb80-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb80-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"β0"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb80-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb80-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_coast &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"β_coast"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb80-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb80-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_pop &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"β_pop"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb80-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb80-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    η &lt;span class="op"&gt;=&lt;/span&gt; β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; β_coast &lt;span class="op"&gt;*&lt;/span&gt; x_coast &lt;span class="op"&gt;+&lt;/span&gt; β_pop &lt;span class="op"&gt;*&lt;/span&gt; x_pop&lt;/span&gt;
&lt;span id="cb80-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb80-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; at.exp(η)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As in the previous model, &lt;span class="math inline"&gt;\(\alpha \sim \operatorname{Half}-N(2.5^2)\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(y_{i, t} \sim NB(\mu_{i, t}, \alpha)\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb81"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb81-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb81-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; nb_reg_model:&lt;/span&gt;
&lt;span id="cb81-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb81-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    α &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"α"&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb81-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb81-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs &lt;span class="op"&gt;=&lt;/span&gt; pm.NegativeBinomial(&lt;span class="st"&gt;"obs"&lt;/span&gt;, μ, α, observed&lt;span class="op"&gt;=&lt;/span&gt;y)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We again sample from the posterior distribution of the model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb82"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb82-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb82-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; nb_reg_model:&lt;/span&gt;
&lt;span id="cb82-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb82-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    nb_reg_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [β0, β_coast, β_pop, α]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="6000" class max="6000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [6000/6000 00:24&amp;lt;00:00 Sampling 3 chains, 0 divergences]&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Sampling 3 chains for 1_000 tune and 1_000 draw iterations (3_000 + 3_000 draws total) took 25 seconds.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As before, the standard sampling diagnostics show no cause for concern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb85"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb85-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb85-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_diagnostic_plots(nb_reg_trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_109_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;To see if the inclusion of these predictors has improved the model fit, we sample from and plot the posterior predictive distributions per state-year.&lt;/p&gt;
&lt;div class="sourceCode" id="cb86"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb86-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb86-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; nb_reg_model:&lt;/span&gt;
&lt;span id="cb86-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb86-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    nb_reg_pp_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample_posterior_predictive(nb_reg_trace)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="3000" class max="3000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [3000/3000 00:02&amp;lt;00:00]&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb87"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb87-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb87-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;nb_reg_pp_full_df &lt;span class="op"&gt;=&lt;/span&gt; make_pp_full_df(nb_reg_pp_trace[&lt;span class="st"&gt;"obs"&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb88"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb88-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb88-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;nb_reg_pp_df &lt;span class="op"&gt;=&lt;/span&gt; summarize_pp_df(nb_reg_pp_full_df)&lt;/span&gt;
&lt;span id="cb88-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb88-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid &lt;span class="op"&gt;=&lt;/span&gt; sns.FacetGrid(nb_reg_pp_df.reset_index(), col&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"State"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb88-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb88-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     col_wrap&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, aspect&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;1.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb88-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb88-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid.map_dataframe(plot_pp_over_time)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb88-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb88-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb88-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb88-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid.axes[&lt;span class="dv"&gt;0&lt;/span&gt;].legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"upper left"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb88-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb88-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid.set_titles(&lt;span class="st"&gt;"&lt;/span&gt;&lt;span class="sc"&gt;{col_name}&lt;/span&gt;&lt;span class="st"&gt;"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb88-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb88-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid.fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_113_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb89"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb89-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;nb_reg_pp_state_df &lt;span class="op"&gt;=&lt;/span&gt; summarize_pp_df(nb_reg_pp_full_df, level&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"State"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb89-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; (nb_reg_pp_state_df.reset_index()&lt;/span&gt;
&lt;span id="cb89-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    .plot.scatter(&lt;span class="st"&gt;"mean"&lt;/span&gt;, &lt;span class="st"&gt;"State"&lt;/span&gt;, color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb89-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                  xerr&lt;span class="op"&gt;=&lt;/span&gt;nb_reg_pp_state_df[[&lt;span class="st"&gt;"low"&lt;/span&gt;, &lt;span class="st"&gt;"high"&lt;/span&gt;]]&lt;/span&gt;
&lt;span id="cb89-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                     .sub(nb_reg_pp_state_df[&lt;span class="st"&gt;"mean"&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb89-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                          axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb89-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                     .&lt;span class="bu"&gt;abs&lt;/span&gt;()&lt;/span&gt;
&lt;span id="cb89-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                     .values.T,&lt;/span&gt;
&lt;span id="cb89-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                  zorder&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;5&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb89-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                  label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Posterior predictive mean"&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb89-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(attacks_df.reset_index()&lt;/span&gt;
&lt;span id="cb89-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           .plot.scatter(&lt;span class="st"&gt;"Attacks"&lt;/span&gt;, &lt;span class="st"&gt;"State"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb89-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb89-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Actual"&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;ax))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb89-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb89-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Number of shark Attacks"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb89-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb89-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.invert_yaxis()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_114_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;These predictions certainly appear visually better than those from the regular negative binomial model without predictors, but still leave significant room for improvement, espescially in states like Florida, California, Hawaii, and the Carolinas.&lt;/p&gt;
&lt;p&gt;We use &lt;a href="https://arxiv.org/abs/1507.04544"&gt;Pareto-smoothed importance sampling leave-one-out cross-validation&lt;/a&gt; (PSIS-LOO) to quantify the improvement of this model over the basic negative binomial model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb90"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb90-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb90-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;traces &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb90-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb90-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"NB"&lt;/span&gt;: nb_trace,&lt;/span&gt;
&lt;span id="cb90-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb90-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"NB regression"&lt;/span&gt;: nb_reg_trace&lt;/span&gt;
&lt;span id="cb90-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb90-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb91"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb91-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb91-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots()&lt;/span&gt;
&lt;span id="cb91-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb91-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb91-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb91-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;comp_df &lt;span class="op"&gt;=&lt;/span&gt; az.compare(traces)&lt;/span&gt;
&lt;span id="cb91-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb91-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_compare(comp_df, plot_ic_diff&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_117_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that the PSIS-LOO score of the regression model is significantly higher than that of the simple negative binomial model.&lt;/p&gt;
&lt;h3 id="mixed-effects"&gt;Mixed effects&lt;/h3&gt;
&lt;p&gt;There are many factors about each state that we have not included as predictors (average water temperature, prevalence of beach tourism, etc.). To account for this these and other unmeasured differences between states, we now add state-level &lt;a href="https://en.wikipedia.org/wiki/Mixed_model"&gt;mixed effects&lt;/a&gt; to our model.&lt;/p&gt;
&lt;p&gt;Let &lt;span class="math inline"&gt;\(j = 1, 2, \ldots, n_{\text{state}}\)&lt;/span&gt; denote the index of a state and &lt;span class="math inline"&gt;\(j(i)\)&lt;/span&gt; denoth the index of the state of the &lt;span class="math inline"&gt;\(i\)&lt;/span&gt;-th observation.&lt;/p&gt;
&lt;p&gt;We place hierarchical normal priors on &lt;span class="math inline"&gt;\(\beta_{0, j},\)&lt;/span&gt; &lt;span class="math inline"&gt;\(\beta_{\text{coast}, j},\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(\beta_{\text{pop}, j}\)&lt;/span&gt; and set&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[\eta_{i, t} = \beta_{0, j(i)} + \beta_{\text{coast}, j(i)} \cdot x_{\text{coast}, i} + \beta_{\text{pop}, j(i)} \cdot x_{\text{pop}, i, t}.\]&lt;/span&gt; Again the mean is then &lt;span class="math inline"&gt;\(\mu_{i, t} = \exp \eta_{i, t}.\)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The hierarchical prior for &lt;span class="math inline"&gt;\(\beta_0\)&lt;/span&gt; is equivalent to&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \mu_{\beta_0}, \gamma_{0, \text{pop}}
        &amp;amp; \sim N(0, 2.5^2) \\
    \sigma_{\beta_0}
        &amp;amp; \sim \operatorname{Half}-N(2.5^2) \\
    \beta_{0, j}
        &amp;amp; \sim N\left(\mu_{\beta_0} + \gamma_{0, \text{pop}} \cdot \bar{x}_{\text{pop}, j}, \sigma_{\beta_0}^2\right).
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In reality, we implement this system of priors using a &lt;a href="https://twiecki.io/blog/2017/02/08/bayesian-hierchical-non-centered/"&gt;non-centered parametrization&lt;/a&gt; that is mathematically equivalent but often more computationally efficient. Note the inclusion of a term for &lt;span class="math inline"&gt;\(\bar{x}_{\text{pop}, j}\)&lt;/span&gt;, which is the average population for the &lt;span class="math inline"&gt;\(j\)&lt;/span&gt;-th state. We include this term to &lt;a href="http://www.stat.columbia.edu/~gelman/research/unpublished/Bafumi_Gelman_Midwest06.pdf"&gt;avoid&lt;/a&gt; violating the &lt;a href="https://en.wikipedia.org/wiki/Gauss%E2%80%93Markov_theorem"&gt;Gauss-Markov assumptions&lt;/a&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb92"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb92-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb92-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;j_, state_map &lt;span class="op"&gt;=&lt;/span&gt; (attacks_df.index&lt;/span&gt;
&lt;span id="cb92-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb92-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                          .get_level_values(&lt;span class="st"&gt;"State"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb92-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb92-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                          .factorize(sort&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb92-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb92-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_state &lt;span class="op"&gt;=&lt;/span&gt; state_map.size&lt;/span&gt;
&lt;span id="cb92-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb92-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;j &lt;span class="op"&gt;=&lt;/span&gt; at.constant(j_)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb93"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb93-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb93-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;x_pop_bar &lt;span class="op"&gt;=&lt;/span&gt; at.constant(standardize(&lt;/span&gt;
&lt;span id="cb93-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb93-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    attacks_df.assign(x_pop&lt;span class="op"&gt;=&lt;/span&gt;x_pop.&lt;span class="bu"&gt;eval&lt;/span&gt;())&lt;/span&gt;
&lt;span id="cb93-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb93-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .groupby(level&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"State"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb93-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb93-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              [&lt;span class="st"&gt;"x_pop"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb93-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb93-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .mean()&lt;/span&gt;
&lt;span id="cb93-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb93-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .values&lt;/span&gt;
&lt;span id="cb93-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb93-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb94"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb94-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; noncentered_normal(name, shape, μ&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb94-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; μ &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb94-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        μ &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="ss"&gt;f"μ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb94-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb94-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    Δ &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="ss"&gt;f"Δ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;1.&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;shape)&lt;/span&gt;
&lt;span id="cb94-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="ss"&gt;f"σ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb94-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb94-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; pm.Deterministic(name, μ &lt;span class="op"&gt;+&lt;/span&gt; Δ &lt;span class="op"&gt;*&lt;/span&gt; σ)&lt;/span&gt;
&lt;span id="cb94-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb94-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; noncentered_normal_with_avg(name, avg_map, shape, μ&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb94-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; μ &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb94-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        μ &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="ss"&gt;f"μ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb94-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb94-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    avg_terms_sum &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="fl"&gt;0.&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb94-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb94-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;for&lt;/span&gt; term_name, x_bar &lt;span class="kw"&gt;in&lt;/span&gt; avg_map.items():&lt;/span&gt;
&lt;span id="cb94-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        avg_terms_sum &lt;span class="op"&gt;+=&lt;/span&gt; pm.Normal(&lt;span class="ss"&gt;f"γ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;term_name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;_bar"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;) &lt;span class="op"&gt;*&lt;/span&gt; x_bar&lt;/span&gt;
&lt;span id="cb94-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb94-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb94-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; noncentered_normal(name, shape, μ&lt;span class="op"&gt;=&lt;/span&gt;μ &lt;span class="op"&gt;+&lt;/span&gt; avg_terms_sum)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb95"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb95-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb95-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; mixed_model:&lt;/span&gt;
&lt;span id="cb95-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb95-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; noncentered_normal_with_avg(&lt;/span&gt;
&lt;span id="cb95-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb95-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;"β0"&lt;/span&gt;, {&lt;span class="st"&gt;"pop"&lt;/span&gt;: x_pop_bar}, n_state&lt;/span&gt;
&lt;span id="cb95-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb95-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The prior for &lt;span class="math inline"&gt;\(\beta_{\text{coast}, j}\)&lt;/span&gt; is&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \mu_{\beta_\text{coast}}, \gamma_{\text{coast}^2}, \gamma_{\text{coast}, \text{pop}}
        &amp;amp; \sim N(0, 2.5^2) \\
    \sigma_{\beta_{\text{coast}}}
        &amp;amp; \sim \operatorname{Half}-N(2.5^2) \\
    \beta_{\text{coast}, j}
        &amp;amp; \sim N\left(\mu_{\beta_\text{coast}} + \gamma_{\text{coast}^2} \cdot x_{\text{coast}, j} + \gamma_{\text{coast}, \text{pop}} \cdot \bar{x}_{\text{pop}, j}, \sigma_{\beta_0}^2\right)
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Here &lt;span class="math inline"&gt;\(\bar{x}_{\text{coast}, j} = x_{\text{coast}, j}\)&lt;/span&gt; since the a state’s coastline does not change over time (we ignoring the effects of global warming here). Due to this fact, we do not include the term &lt;span class="math inline"&gt;\(\gamma_{0, \text{coast}} \cdot x_{\text{coast}, j}\)&lt;/span&gt; in the definition of &lt;span class="math inline"&gt;\(\beta_0\)&lt;/span&gt;, because this term would lead to &lt;span class="math inline"&gt;\(\mu_{\beta_{\text{coast}}}\)&lt;/span&gt; becoming unidentified. We use the analagous system of priors for &lt;span class="math inline"&gt;\(\beta_{\text{pop}}.\)&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb96"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb96-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb96-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;log_state_coast &lt;span class="op"&gt;=&lt;/span&gt; np.log(coast_df[&lt;span class="st"&gt;"Coastline"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb96-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb96-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                 .loc[state_map]&lt;/span&gt;
&lt;span id="cb96-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb96-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                 .values)&lt;/span&gt;
&lt;span id="cb96-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb96-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;x_coast_bar &lt;span class="op"&gt;=&lt;/span&gt; at.constant(standardize(log_state_coast))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb97"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb97-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb97-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; mixed_model:&lt;/span&gt;
&lt;span id="cb97-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb97-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_coast &lt;span class="op"&gt;=&lt;/span&gt; noncentered_normal_with_avg(&lt;/span&gt;
&lt;span id="cb97-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb97-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;"β_coast"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb97-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb97-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        {&lt;span class="st"&gt;"pop"&lt;/span&gt;: x_pop_bar, &lt;span class="st"&gt;"coast"&lt;/span&gt;: x_coast_bar},&lt;/span&gt;
&lt;span id="cb97-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb97-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        n_state&lt;/span&gt;
&lt;span id="cb97-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb97-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb97-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb97-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_pop &lt;span class="op"&gt;=&lt;/span&gt; noncentered_normal_with_avg(&lt;/span&gt;
&lt;span id="cb97-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb97-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;"β_pop"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb97-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb97-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        {&lt;span class="st"&gt;"pop"&lt;/span&gt;: x_pop_bar, &lt;span class="st"&gt;"coast"&lt;/span&gt;: x_coast_bar},&lt;/span&gt;
&lt;span id="cb97-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb97-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        n_state)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The definitions of &lt;span class="math inline"&gt;\(\eta_{i, t}\)&lt;/span&gt;, &lt;span class="math inline"&gt;\(\mu_{i, t}\)&lt;/span&gt;, and &lt;span class="math inline"&gt;\(\alpha\)&lt;/span&gt; are similar to those in the previous model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb98"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb98-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb98-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; mixed_model:&lt;/span&gt;
&lt;span id="cb98-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb98-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    η &lt;span class="op"&gt;=&lt;/span&gt; β&lt;span class="dv"&gt;0&lt;/span&gt;[j] &lt;span class="op"&gt;+&lt;/span&gt; β_coast[j] &lt;span class="op"&gt;*&lt;/span&gt; x_coast &lt;span class="op"&gt;+&lt;/span&gt; β_pop[j] &lt;span class="op"&gt;*&lt;/span&gt; x_pop&lt;/span&gt;
&lt;span id="cb98-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb98-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; at.exp(η)&lt;/span&gt;
&lt;span id="cb98-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb98-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb98-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb98-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    α &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"α"&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb98-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb98-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs &lt;span class="op"&gt;=&lt;/span&gt; pm.NegativeBinomial(&lt;span class="st"&gt;"obs"&lt;/span&gt;, μ, α, observed&lt;span class="op"&gt;=&lt;/span&gt;y)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We again sample from the posterior distribution of the model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb99"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb99-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb99-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; mixed_model:&lt;/span&gt;
&lt;span id="cb99-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb99-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    mixed_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS, target_accept&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.95&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [μ_β0, γ_β0_pop_bar, Δ_β0, σ_β0, μ_β_coast, γ_β_coast_pop_bar, γ_β_coast_coast_bar, Δ_β_coast, σ_β_coast, μ_β_pop, γ_β_pop_pop_bar, γ_β_pop_coast_bar, Δ_β_pop, σ_β_pop, α]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="6000" class max="6000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [6000/6000 24:00&amp;lt;00:00 Sampling 3 chains, 3 divergences]&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Sampling 3 chains for 1_000 tune and 1_000 draw iterations (3_000 + 3_000 draws total) took 1441 seconds.
There was 1 divergence after tuning. Increase `target_accept` or reparameterize.
There were 2 divergences after tuning. Increase `target_accept` or reparameterize.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The few divergences here could be eliminated by increasing &lt;code&gt;target_accept&lt;/code&gt; and waiting longer, but we will proceed with our analysis (I’m impatient). As before, the standard sampling diagnostics show no cause for concern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb102"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb102-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb102-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_diagnostic_plots(mixed_trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_132_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;To see if the inclusion of mixed effects has improved the model fit, we sample from and plot the posterior predictive distributions per state-year.&lt;/p&gt;
&lt;div class="sourceCode" id="cb103"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb103-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb103-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; mixed_model:&lt;/span&gt;
&lt;span id="cb103-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb103-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    mixed_pp_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample_posterior_predictive(mixed_trace)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="3000" class max="3000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [3000/3000 00:05&amp;lt;00:00]&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb104"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb104-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb104-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;mixed_pp_full_df &lt;span class="op"&gt;=&lt;/span&gt; make_pp_full_df(mixed_pp_trace[&lt;span class="st"&gt;"obs"&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb105"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb105-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb105-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;mixed_pp_df &lt;span class="op"&gt;=&lt;/span&gt; summarize_pp_df(mixed_pp_full_df)&lt;/span&gt;
&lt;span id="cb105-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb105-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid &lt;span class="op"&gt;=&lt;/span&gt; sns.FacetGrid(mixed_pp_df.reset_index(), col&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"State"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb105-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb105-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     col_wrap&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, aspect&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;1.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb105-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb105-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid.map_dataframe(plot_pp_over_time)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb105-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb105-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb105-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb105-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid.axes[&lt;span class="dv"&gt;0&lt;/span&gt;].legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"upper left"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb105-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb105-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid.set_titles(&lt;span class="st"&gt;"&lt;/span&gt;&lt;span class="sc"&gt;{col_name}&lt;/span&gt;&lt;span class="st"&gt;"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb105-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb105-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid.fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_136_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb106"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb106-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;mixed_pp_state_df &lt;span class="op"&gt;=&lt;/span&gt; summarize_pp_df(mixed_pp_full_df, level&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"State"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb106-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; (mixed_pp_state_df.reset_index()&lt;/span&gt;
&lt;span id="cb106-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    .plot.scatter(&lt;span class="st"&gt;"mean"&lt;/span&gt;, &lt;span class="st"&gt;"State"&lt;/span&gt;, color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb106-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                  xerr&lt;span class="op"&gt;=&lt;/span&gt;mixed_pp_state_df[[&lt;span class="st"&gt;"low"&lt;/span&gt;, &lt;span class="st"&gt;"high"&lt;/span&gt;]]&lt;/span&gt;
&lt;span id="cb106-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                     .sub(mixed_pp_state_df[&lt;span class="st"&gt;"mean"&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb106-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                          axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb106-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                     .&lt;span class="bu"&gt;abs&lt;/span&gt;()&lt;/span&gt;
&lt;span id="cb106-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                     .values.T,&lt;/span&gt;
&lt;span id="cb106-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                  zorder&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;5&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb106-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                  label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Posterior predictive mean"&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb106-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(attacks_df.reset_index()&lt;/span&gt;
&lt;span id="cb106-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           .plot.scatter(&lt;span class="st"&gt;"Attacks"&lt;/span&gt;, &lt;span class="st"&gt;"State"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb106-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb106-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Actual"&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;ax))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb106-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb106-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Number of shark Attacks"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb106-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb106-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.invert_yaxis()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_137_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that the predictions for Florida, California, Hawaii, and the Carolinas are much better in this model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb107"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb107-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb107-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;traces[&lt;span class="st"&gt;"NB mixed"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; mixed_trace&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb108"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb108-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb108-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots()&lt;/span&gt;
&lt;span id="cb108-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb108-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb108-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb108-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;comp_df &lt;span class="op"&gt;=&lt;/span&gt; az.compare(traces)&lt;/span&gt;
&lt;span id="cb108-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb108-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_compare(comp_df, plot_ic_diff&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sharks_pycm3_files/sharks_pycm3_140_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;As expected the PSIS-LOO score for this model is significantly better than the fixed effects negative binomial regression model.&lt;/p&gt;
&lt;p&gt;It is interesting but not surprising that mixed effects are required to produce reasonable predictions of the number of shark attacks in each state over time. Future posts may investigate further explanatory variables and other aspects of this data set.&lt;/p&gt;
&lt;p&gt;This post is available as a Jupyter notebook &lt;a href="https://nbviewer.jupyter.org/gist/AustinRochford/ce87b0d4e77ad9879a46a1322ea5b141"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb109"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb109-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb109-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;load_ext watermark&lt;/span&gt;
&lt;span id="cb109-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html#cb109-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;watermark &lt;span class="op"&gt;-&lt;/span&gt;n &lt;span class="op"&gt;-&lt;/span&gt;u &lt;span class="op"&gt;-&lt;/span&gt;v &lt;span class="op"&gt;-&lt;/span&gt;iv&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Last updated: Sun Jun 27 2021

Python implementation: CPython
Python version       : 3.8.8
IPython version      : 7.22.0

numpy     : 1.20.2
matplotlib: 3.4.1
pandas    : 1.2.3
us        : 2.0.2
seaborn   : 0.11.1
aesara    : 2.0.12
arviz     : 0.11.2
pymc3     : 4.0&lt;/code&gt;&lt;/pre&gt;</description><category>Bayesian Statistics</category><category>PyMC3</category><category>Sharks</category><guid>https://austinrochford.com/posts/2021-06-27-sharks-pymc3.html</guid><pubDate>Sun, 27 Jun 2021 04:00:00 GMT</pubDate></item><item><title>A Bayesian Analysis of Lego Prices in Python with PyMC3</title><link>https://austinrochford.com/posts/2021-06-10-lego-pymc3.html</link><dc:creator>Austin Rochford</dc:creator><description>&lt;p&gt;This post is the second in a series of posts analyzing Lego pricing data scraped from &lt;a href="https://brickset.com/"&gt;brickset.com&lt;/a&gt;. The &lt;a href="https://austinrochford.com/posts/2021-06-03-vader-meditation.html"&gt;first post&lt;/a&gt; gave an empirical analysis of the fairness of the price for Darth Vader’s Meditation Chamber (&lt;a href="https://www.lego.com/en-us/product/darth-vader-meditation-chamber-75296"&gt;75296&lt;/a&gt;), disproving my initial impression that the set was overpriced for its size and prompting me to preorder it. In this post we will build several more formal models of the price of Lego sets based on their size and use them to answer a few related questions.&lt;/p&gt;
&lt;center&gt;
&lt;figure&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/tantiveiv.png" width="500"&gt; &lt;br&gt;
&lt;caption&gt;
The newest addition to my collection (&lt;a href="https://brickset.com/sets/75244-1/Tantive-IV"&gt;75244&lt;/a&gt;).
&lt;/caption&gt;
&lt;/figure&gt;
&lt;/center&gt;
&lt;p&gt;First we make the necessary Python imports and do some light housekeeping.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb1-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;matplotlib inline&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb2-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; datetime&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; functools &lt;span class="im"&gt;import&lt;/span&gt; &lt;span class="bu"&gt;reduce&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; itertools &lt;span class="im"&gt;as&lt;/span&gt; itl&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; warnings &lt;span class="im"&gt;import&lt;/span&gt; filterwarnings&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb3-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; aesara &lt;span class="im"&gt;import&lt;/span&gt; shared, tensor &lt;span class="im"&gt;as&lt;/span&gt; at&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; arviz &lt;span class="im"&gt;as&lt;/span&gt; az&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib &lt;span class="im"&gt;import&lt;/span&gt; MatplotlibDeprecationWarning, pyplot &lt;span class="im"&gt;as&lt;/span&gt; plt&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib.lines &lt;span class="im"&gt;import&lt;/span&gt; Line2D&lt;/span&gt;
&lt;span id="cb3-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb3-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib.ticker &lt;span class="im"&gt;import&lt;/span&gt; FuncFormatter, MultipleLocator, StrMethodFormatter&lt;/span&gt;
&lt;span id="cb3-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb3-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; numpy &lt;span class="im"&gt;as&lt;/span&gt; np&lt;/span&gt;
&lt;span id="cb3-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb3-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pandas &lt;span class="im"&gt;as&lt;/span&gt; pd&lt;/span&gt;
&lt;span id="cb3-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb3-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pymc3 &lt;span class="im"&gt;as&lt;/span&gt; pm&lt;/span&gt;
&lt;span id="cb3-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb3-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; scipy &lt;span class="im"&gt;as&lt;/span&gt; sp&lt;/span&gt;
&lt;span id="cb3-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb3-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; sklearn.preprocessing &lt;span class="im"&gt;import&lt;/span&gt; StandardScaler&lt;/span&gt;
&lt;span id="cb3-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb3-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; seaborn &lt;span class="im"&gt;as&lt;/span&gt; sns&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb4-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;filterwarnings(&lt;span class="st"&gt;'ignore'&lt;/span&gt;, category&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="pp"&gt;UserWarning&lt;/span&gt;, message&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;".*FixedFormatter.*"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb4-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;filterwarnings(&lt;span class="st"&gt;'ignore'&lt;/span&gt;, category&lt;span class="op"&gt;=&lt;/span&gt;MatplotlibDeprecationWarning, module&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'pandas'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb4-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb4-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;filterwarnings(&lt;span class="st"&gt;'ignore'&lt;/span&gt;, category&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="pp"&gt;UserWarning&lt;/span&gt;, module&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'aesara'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb4-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb4-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;filterwarnings(&lt;span class="st"&gt;'ignore'&lt;/span&gt;, category&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="pp"&gt;UserWarning&lt;/span&gt;, module&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'arviz'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb4-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb4-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;filterwarnings(&lt;span class="st"&gt;'ignore'&lt;/span&gt;, category&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="pp"&gt;UserWarning&lt;/span&gt;, module&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'pandas'&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb5-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plt.rcParams[&lt;span class="st"&gt;'figure.figsize'&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb5-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb5-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb5-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb5-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.&lt;span class="bu"&gt;set&lt;/span&gt;(color_codes&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb5-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb5-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb5-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb5-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;dollar_formatter &lt;span class="op"&gt;=&lt;/span&gt; StrMethodFormatter(&lt;span class="st"&gt;"${x:,.2f}"&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="load-the-data"&gt;Load the Data&lt;/h2&gt;
&lt;p&gt;We begin the real work by loading the data scraped from Brickset. See the &lt;a href="https://austinrochford.com/posts/2021-06-03-vader-meditation.html"&gt;first post&lt;/a&gt; in this series for more background on the data.&lt;/p&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb6-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;DATA_URL &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="st"&gt;'https://austinrochford.com/resources/lego/brickset_01011980_06012021.csv.gz'&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb7-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb7-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; to_datetime(year):&lt;/span&gt;
&lt;span id="cb7-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb7-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; np.datetime64(&lt;span class="ss"&gt;f"&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;&lt;span class="bu"&gt;round&lt;/span&gt;(year)&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;-01-01"&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb8-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;full_df &lt;span class="op"&gt;=&lt;/span&gt; (pd.read_csv(DATA_URL,&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb8-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                       usecols&lt;span class="op"&gt;=&lt;/span&gt;[&lt;/span&gt;
&lt;span id="cb8-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb8-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                           &lt;span class="st"&gt;"Year released"&lt;/span&gt;, &lt;span class="st"&gt;"Set number"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb8-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                           &lt;span class="st"&gt;"Name"&lt;/span&gt;, &lt;span class="st"&gt;"Set type"&lt;/span&gt;, &lt;span class="st"&gt;"Theme"&lt;/span&gt;, &lt;span class="st"&gt;"Subtheme"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb8-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                           &lt;span class="st"&gt;"Pieces"&lt;/span&gt;, &lt;span class="st"&gt;"RRP"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb8-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                       ])&lt;/span&gt;
&lt;span id="cb8-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb8-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             .dropna(subset&lt;span class="op"&gt;=&lt;/span&gt;[&lt;/span&gt;
&lt;span id="cb8-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb8-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 &lt;span class="st"&gt;"Year released"&lt;/span&gt;, &lt;span class="st"&gt;"Set number"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb8-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 &lt;span class="st"&gt;"Name"&lt;/span&gt;, &lt;span class="st"&gt;"Set type"&lt;/span&gt;, &lt;span class="st"&gt;"Theme"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb8-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 &lt;span class="st"&gt;"Pieces"&lt;/span&gt;, &lt;span class="st"&gt;"RRP"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb8-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             ]))&lt;/span&gt;
&lt;span id="cb8-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb8-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;full_df[&lt;span class="st"&gt;"Year released"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; full_df[&lt;span class="st"&gt;"Year released"&lt;/span&gt;].&lt;span class="bu"&gt;apply&lt;/span&gt;(to_datetime)&lt;/span&gt;
&lt;span id="cb8-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb8-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;full_df &lt;span class="op"&gt;=&lt;/span&gt; (full_df.set_index([&lt;span class="st"&gt;"Year released"&lt;/span&gt;, &lt;span class="st"&gt;"Set number"&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb8-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb8-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                  .sort_index())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We see that the data set contains information on approximately 8,500 Lego sets produced between 1980 and June 2021.&lt;/p&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb9-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;full_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Name
&lt;/th&gt;
&lt;th&gt;
Set type
&lt;/th&gt;
&lt;th&gt;
Theme
&lt;/th&gt;
&lt;th&gt;
Pieces
&lt;/th&gt;
&lt;th&gt;
RRP
&lt;/th&gt;
&lt;th&gt;
Subtheme
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Year released
&lt;/th&gt;
&lt;th&gt;
Set number
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th rowspan="5" valign="top"&gt;
1980-01-01
&lt;/th&gt;
&lt;th&gt;
1041-2
&lt;/th&gt;
&lt;td&gt;
Educational Duplo Building Set
&lt;/td&gt;
&lt;td&gt;
Normal
&lt;/td&gt;
&lt;td&gt;
Dacta
&lt;/td&gt;
&lt;td&gt;
68.0
&lt;/td&gt;
&lt;td&gt;
36.50
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1075-1
&lt;/th&gt;
&lt;td&gt;
LEGO People Supplementary Set
&lt;/td&gt;
&lt;td&gt;
Normal
&lt;/td&gt;
&lt;td&gt;
Dacta
&lt;/td&gt;
&lt;td&gt;
304.0
&lt;/td&gt;
&lt;td&gt;
14.50
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1101-1
&lt;/th&gt;
&lt;td&gt;
Replacement 4.5V Motor
&lt;/td&gt;
&lt;td&gt;
Normal
&lt;/td&gt;
&lt;td&gt;
Service Packs
&lt;/td&gt;
&lt;td&gt;
1.0
&lt;/td&gt;
&lt;td&gt;
5.65
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1123-1
&lt;/th&gt;
&lt;td&gt;
Ball and Socket Couplings &amp;amp; One Articulated Joint
&lt;/td&gt;
&lt;td&gt;
Normal
&lt;/td&gt;
&lt;td&gt;
Service Packs
&lt;/td&gt;
&lt;td&gt;
8.0
&lt;/td&gt;
&lt;td&gt;
16.00
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1130-1
&lt;/th&gt;
&lt;td&gt;
Plastic Folder for Building Instructions
&lt;/td&gt;
&lt;td&gt;
Normal
&lt;/td&gt;
&lt;td&gt;
Service Packs
&lt;/td&gt;
&lt;td&gt;
1.0
&lt;/td&gt;
&lt;td&gt;
14.00
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb10"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb10-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb10-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;full_df.tail()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Name
&lt;/th&gt;
&lt;th&gt;
Set type
&lt;/th&gt;
&lt;th&gt;
Theme
&lt;/th&gt;
&lt;th&gt;
Pieces
&lt;/th&gt;
&lt;th&gt;
RRP
&lt;/th&gt;
&lt;th&gt;
Subtheme
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Year released
&lt;/th&gt;
&lt;th&gt;
Set number
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th rowspan="5" valign="top"&gt;
2021-01-01
&lt;/th&gt;
&lt;th&gt;
80022-1
&lt;/th&gt;
&lt;td&gt;
Spider Queen’s Arachnoid Base
&lt;/td&gt;
&lt;td&gt;
Normal
&lt;/td&gt;
&lt;td&gt;
Monkie Kid
&lt;/td&gt;
&lt;td&gt;
1170.0
&lt;/td&gt;
&lt;td&gt;
119.99
&lt;/td&gt;
&lt;td&gt;
Season 2
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
80023-1
&lt;/th&gt;
&lt;td&gt;
Monkie Kid’s Team Dronecopter
&lt;/td&gt;
&lt;td&gt;
Normal
&lt;/td&gt;
&lt;td&gt;
Monkie Kid
&lt;/td&gt;
&lt;td&gt;
1462.0
&lt;/td&gt;
&lt;td&gt;
149.99
&lt;/td&gt;
&lt;td&gt;
Season 2
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
80024-1
&lt;/th&gt;
&lt;td&gt;
The Legendary Flower Fruit Mountain
&lt;/td&gt;
&lt;td&gt;
Normal
&lt;/td&gt;
&lt;td&gt;
Monkie Kid
&lt;/td&gt;
&lt;td&gt;
1949.0
&lt;/td&gt;
&lt;td&gt;
169.99
&lt;/td&gt;
&lt;td&gt;
Season 2
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
80106-1
&lt;/th&gt;
&lt;td&gt;
Story of Nian
&lt;/td&gt;
&lt;td&gt;
Normal
&lt;/td&gt;
&lt;td&gt;
Seasonal
&lt;/td&gt;
&lt;td&gt;
1067.0
&lt;/td&gt;
&lt;td&gt;
79.99
&lt;/td&gt;
&lt;td&gt;
Chinese Traditional Festivals
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
80107-1
&lt;/th&gt;
&lt;td&gt;
Spring Lantern Festival
&lt;/td&gt;
&lt;td&gt;
Normal
&lt;/td&gt;
&lt;td&gt;
Seasonal
&lt;/td&gt;
&lt;td&gt;
1793.0
&lt;/td&gt;
&lt;td&gt;
119.99
&lt;/td&gt;
&lt;td&gt;
Chinese Traditional Festivals
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb11"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb11-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb11-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;full_df.describe()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Pieces
&lt;/th&gt;
&lt;th&gt;
RRP
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
count
&lt;/th&gt;
&lt;td&gt;
8502.000000
&lt;/td&gt;
&lt;td&gt;
8502.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
mean
&lt;/th&gt;
&lt;td&gt;
258.739591
&lt;/td&gt;
&lt;td&gt;
31.230506
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
std
&lt;/th&gt;
&lt;td&gt;
481.627846
&lt;/td&gt;
&lt;td&gt;
44.993559
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
min
&lt;/th&gt;
&lt;td&gt;
0.000000
&lt;/td&gt;
&lt;td&gt;
0.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
25%
&lt;/th&gt;
&lt;td&gt;
32.000000
&lt;/td&gt;
&lt;td&gt;
7.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
50%
&lt;/th&gt;
&lt;td&gt;
98.000000
&lt;/td&gt;
&lt;td&gt;
17.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
75%
&lt;/th&gt;
&lt;td&gt;
300.000000
&lt;/td&gt;
&lt;td&gt;
39.990000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
max
&lt;/th&gt;
&lt;td&gt;
11695.000000
&lt;/td&gt;
&lt;td&gt;
799.990000
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;We also load data about my personal collection and add a column to &lt;code&gt;full_df&lt;/code&gt; indicating whether or not I own each set.&lt;/p&gt;
&lt;div class="sourceCode" id="cb12"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb12-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb12-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;MY_COLLECTION_URL &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="st"&gt;'https://austinrochford.com/resources/lego/Brickset-MySets-owned-20210602.csv'&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb13"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb13-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb13-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;my_df &lt;span class="op"&gt;=&lt;/span&gt; pd.read_csv(MY_COLLECTION_URL)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb14"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb14-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb14-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;my_df.index&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Index(['8092-1', '10221-1', '10266-1', '10281-1', '10283-1', '21309-1',
       '21312-1', '21320-1', '21321-1', '31091-1', '40174-1', '40268-1',
       '40391-1', '40431-1', '40440-1', '41602-1', '41608-1', '41609-1',
       '41628-1', '75030-1', '75049-1', '75074-1', '75075-1', '75093-1',
       '75099-1', '75136-1', '75137-1', '75138-1', '75162-1', '75176-1',
       '75187-1', '75229-1', '75243-1', '75244-1', '75248-1', '75254-1',
       '75255-1', '75263-1', '75264-1', '75266-1', '75267-1', '75269-1',
       '75273-1', '75277-1', '75278-1', '75283-1', '75292-1', '75297-1',
       '75302-1', '75306-1', '75308-1', '75317-1', '75318-1'],
      dtype='object')&lt;/code&gt;&lt;/pre&gt;
&lt;div class="sourceCode" id="cb16"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb16-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb16-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;full_df[&lt;span class="st"&gt;"austin"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (full_df.index&lt;/span&gt;
&lt;span id="cb16-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb16-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                            .get_level_values(&lt;span class="st"&gt;"Set number"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb16-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb16-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                            .isin(my_df.index))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since the data spans more than 40 years, it is important to adjust for inflation. We use the &lt;a href="https://fred.stlouisfed.org/series/CPIAUCNS"&gt;Consumer Price Index for All Urban Consumers: All Items in U.S. City Average&lt;/a&gt; from the U.S. Federal Reserve to adjust for inflation.&lt;/p&gt;
&lt;div class="sourceCode" id="cb17"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb17-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb17-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;CPI_URL &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="st"&gt;'https://austinrochford.com/resources/lego/CPIAUCNS202100401.csv'&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb18"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb18-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb18-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;years &lt;span class="op"&gt;=&lt;/span&gt; pd.date_range(&lt;span class="st"&gt;'1979-01-01'&lt;/span&gt;, &lt;span class="st"&gt;'2021-01-01'&lt;/span&gt;, freq&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'Y'&lt;/span&gt;) &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb18-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;+&lt;/span&gt; datetime.timedelta(days&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb18-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb18-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;cpi_df &lt;span class="op"&gt;=&lt;/span&gt; (pd.read_csv(CPI_URL, index_col&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"DATE"&lt;/span&gt;, parse_dates&lt;span class="op"&gt;=&lt;/span&gt;[&lt;span class="st"&gt;"DATE"&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb18-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb18-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .loc[years])&lt;/span&gt;
&lt;span id="cb18-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb18-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;cpi_df[&lt;span class="st"&gt;"to2021"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; cpi_df.loc[&lt;span class="st"&gt;"2021-01-01"&lt;/span&gt;] &lt;span class="op"&gt;/&lt;/span&gt; cpi_df&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now add a column &lt;code&gt;RRP2021&lt;/code&gt;, which is &lt;code&gt;RRP&lt;/code&gt; adjusted to 2021 dollars.&lt;/p&gt;
&lt;div class="sourceCode" id="cb19"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb19-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb19-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;full_df[&lt;span class="st"&gt;"RRP2021"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (pd.merge(full_df, cpi_df,&lt;/span&gt;
&lt;span id="cb19-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb19-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               left_on&lt;span class="op"&gt;=&lt;/span&gt;[&lt;span class="st"&gt;"Year released"&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb19-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb19-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               right_index&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb19-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb19-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        .&lt;span class="bu"&gt;apply&lt;/span&gt;(&lt;span class="kw"&gt;lambda&lt;/span&gt; df: df[&lt;span class="st"&gt;"RRP"&lt;/span&gt;] &lt;span class="op"&gt;*&lt;/span&gt; df[&lt;span class="st"&gt;"to2021"&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb19-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb19-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Based on the exploratory data analysis in the previous post, we filter &lt;code&gt;full_df&lt;/code&gt; down to approximately 6,300 sets to be included in our analysis.&lt;/p&gt;
&lt;div class="sourceCode" id="cb20"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb20-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb20-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;FILTERS &lt;span class="op"&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb20-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb20-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    full_df[&lt;span class="st"&gt;"Set type"&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="st"&gt;"Normal"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb20-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb20-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    full_df[&lt;span class="st"&gt;"Pieces"&lt;/span&gt;] &lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="dv"&gt;10&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb20-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb20-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    full_df[&lt;span class="st"&gt;"Theme"&lt;/span&gt;] &lt;span class="op"&gt;!=&lt;/span&gt; &lt;span class="st"&gt;"Duplo"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb20-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb20-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    full_df[&lt;span class="st"&gt;"Theme"&lt;/span&gt;] &lt;span class="op"&gt;!=&lt;/span&gt; &lt;span class="st"&gt;"Service Packs"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb20-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb20-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    full_df[&lt;span class="st"&gt;"Theme"&lt;/span&gt;] &lt;span class="op"&gt;!=&lt;/span&gt; &lt;span class="st"&gt;"Bulk Bricks"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb20-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb20-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    full_df[&lt;span class="st"&gt;"RRP"&lt;/span&gt;] &lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb20-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb21"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb21-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb21-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df &lt;span class="op"&gt;=&lt;/span&gt; full_df[&lt;span class="bu"&gt;reduce&lt;/span&gt;(np.logical_and, FILTERS)].copy()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb22"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb22-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb22-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Name
&lt;/th&gt;
&lt;th&gt;
Set type
&lt;/th&gt;
&lt;th&gt;
Theme
&lt;/th&gt;
&lt;th&gt;
Pieces
&lt;/th&gt;
&lt;th&gt;
RRP
&lt;/th&gt;
&lt;th&gt;
Subtheme
&lt;/th&gt;
&lt;th&gt;
austin
&lt;/th&gt;
&lt;th&gt;
RRP2021
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Year released
&lt;/th&gt;
&lt;th&gt;
Set number
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th rowspan="5" valign="top"&gt;
1980-01-01
&lt;/th&gt;
&lt;th&gt;
1041-2
&lt;/th&gt;
&lt;td&gt;
Educational Duplo Building Set
&lt;/td&gt;
&lt;td&gt;
Normal
&lt;/td&gt;
&lt;td&gt;
Dacta
&lt;/td&gt;
&lt;td&gt;
68.0
&lt;/td&gt;
&lt;td&gt;
36.50
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
False
&lt;/td&gt;
&lt;td&gt;
122.721632
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1075-1
&lt;/th&gt;
&lt;td&gt;
LEGO People Supplementary Set
&lt;/td&gt;
&lt;td&gt;
Normal
&lt;/td&gt;
&lt;td&gt;
Dacta
&lt;/td&gt;
&lt;td&gt;
304.0
&lt;/td&gt;
&lt;td&gt;
14.50
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
False
&lt;/td&gt;
&lt;td&gt;
48.752429
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
5233-1
&lt;/th&gt;
&lt;td&gt;
Bedroom
&lt;/td&gt;
&lt;td&gt;
Normal
&lt;/td&gt;
&lt;td&gt;
Homemaker
&lt;/td&gt;
&lt;td&gt;
26.0
&lt;/td&gt;
&lt;td&gt;
4.50
&lt;/td&gt;
&lt;td&gt;
NaN
&lt;/td&gt;
&lt;td&gt;
False
&lt;/td&gt;
&lt;td&gt;
15.130064
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
6305-1
&lt;/th&gt;
&lt;td&gt;
Trees and Flowers
&lt;/td&gt;
&lt;td&gt;
Normal
&lt;/td&gt;
&lt;td&gt;
Town
&lt;/td&gt;
&lt;td&gt;
12.0
&lt;/td&gt;
&lt;td&gt;
3.75
&lt;/td&gt;
&lt;td&gt;
Accessories
&lt;/td&gt;
&lt;td&gt;
False
&lt;/td&gt;
&lt;td&gt;
12.608387
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
6306-1
&lt;/th&gt;
&lt;td&gt;
Road Signs
&lt;/td&gt;
&lt;td&gt;
Normal
&lt;/td&gt;
&lt;td&gt;
Town
&lt;/td&gt;
&lt;td&gt;
12.0
&lt;/td&gt;
&lt;td&gt;
2.50
&lt;/td&gt;
&lt;td&gt;
Accessories
&lt;/td&gt;
&lt;td&gt;
False
&lt;/td&gt;
&lt;td&gt;
8.405591
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb23"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb23-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb23-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df.describe()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
Pieces
&lt;/th&gt;
&lt;th&gt;
RRP
&lt;/th&gt;
&lt;th&gt;
RRP2021
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
count
&lt;/th&gt;
&lt;td&gt;
6312.000000
&lt;/td&gt;
&lt;td&gt;
6312.000000
&lt;/td&gt;
&lt;td&gt;
6312.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
mean
&lt;/th&gt;
&lt;td&gt;
337.177440
&lt;/td&gt;
&lt;td&gt;
37.038246
&lt;/td&gt;
&lt;td&gt;
45.795998
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
std
&lt;/th&gt;
&lt;td&gt;
535.619271
&lt;/td&gt;
&lt;td&gt;
49.657704
&lt;/td&gt;
&lt;td&gt;
58.952563
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
min
&lt;/th&gt;
&lt;td&gt;
11.000000
&lt;/td&gt;
&lt;td&gt;
0.600000
&lt;/td&gt;
&lt;td&gt;
0.971220
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
25%
&lt;/th&gt;
&lt;td&gt;
68.000000
&lt;/td&gt;
&lt;td&gt;
9.990000
&lt;/td&gt;
&lt;td&gt;
11.866173
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
50%
&lt;/th&gt;
&lt;td&gt;
177.000000
&lt;/td&gt;
&lt;td&gt;
19.990000
&lt;/td&gt;
&lt;td&gt;
26.712319
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
75%
&lt;/th&gt;
&lt;td&gt;
400.000000
&lt;/td&gt;
&lt;td&gt;
49.500000
&lt;/td&gt;
&lt;td&gt;
55.952471
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
max
&lt;/th&gt;
&lt;td&gt;
11695.000000
&lt;/td&gt;
&lt;td&gt;
799.990000
&lt;/td&gt;
&lt;td&gt;
897.373477
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h2 id="modeling"&gt;Modeling&lt;/h2&gt;
&lt;p&gt;Upon plotting the data, a linear relationship between the logarithm of pieces and the logarithm of reccomended retail price (in 2021 dollars) becomes immediately apparent.&lt;/p&gt;
&lt;div class="sourceCode" id="cb24"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb24-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb24-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"RRP2021"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df,&lt;/span&gt;
&lt;span id="cb24-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb24-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.05&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb24-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"RRP2021"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb24-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb24-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                data&lt;span class="op"&gt;=&lt;/span&gt;df[df[&lt;span class="st"&gt;"austin"&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="va"&gt;True&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb24-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb24-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"My sets"&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt; &lt;/span&gt;
&lt;span id="cb24-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb24-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb24-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb24-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb24-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb24-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb24-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb24-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Retail price (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb24-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb24-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb24-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'upper left'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_31_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;h3 id="pooled-model"&gt;Pooled model&lt;/h3&gt;
&lt;p&gt;We start with a very simple pooled linear model of log price versus log pieces. Let &lt;span class="math inline"&gt;\(Y_i\)&lt;/span&gt; denote the recommended retail price of the &lt;span class="math inline"&gt;\(i\)&lt;/span&gt;-th set and &lt;span class="math inline"&gt;\(y_i = \log Y_i\)&lt;/span&gt;. Similarly, let &lt;span class="math inline"&gt;\(X_i\)&lt;/span&gt; denote the number of pieces in the &lt;span class="math inline"&gt;\(i\)&lt;/span&gt;-th set and &lt;span class="math inline"&gt;\(x_i = \log X_i\)&lt;/span&gt;. Due to the log-log linear relationship between &lt;span class="math inline"&gt;\(Y_i\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(X_i\)&lt;/span&gt;, our models will take the form&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[Y_i = f_i(X_i) \cdot \varepsilon_i,\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;where &lt;span class="math inline"&gt;\(\varepsilon_i\)&lt;/span&gt; accounts for the unmeasured noise in the price of the &lt;span class="math inline"&gt;\(i\)&lt;/span&gt;-th set. We place a &lt;a href="https://en.wikipedia.org/wiki/Log-normal_distribution"&gt;log-normal&lt;/a&gt; prior on &lt;span class="math inline"&gt;\(\varepsilon_i\)&lt;/span&gt; so that $ (_i) = 1$ and &lt;span class="math inline"&gt;\(\textrm{Var}\left(\log(\varepsilon_j)\right) = \sigma_i^2.\)&lt;/span&gt; standard &lt;a href="https://en.wikipedia.org/wiki/Log-normal_distribution#Generation_and_parameters"&gt;distributional math&lt;/a&gt; shows that&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[y_i \sim N\left(\log\left(f_i(X_i))\right) - \frac{\sigma_i^2}{2}, \sigma_i^2\right).\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Each model is of the form&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[f_i(X_i) = b_{0, i} \cdot X_i^{\beta_i},\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;so&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[\log\left(f_i(X_i)\right) = \beta_{0, i} + \beta_i x_i,\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;where &lt;span class="math inline"&gt;\(\beta_{0, i} = \log b_{0, i}\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;We define &lt;code&gt;log_pieces&lt;/code&gt; and &lt;code&gt;log_rrp2021&lt;/code&gt; which correspond to &lt;span class="math inline"&gt;\(x_i\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(y_i\)&lt;/span&gt; respectively.&lt;/p&gt;
&lt;div class="sourceCode" id="cb25"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb25-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb25-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pieces &lt;span class="op"&gt;=&lt;/span&gt; df[&lt;span class="st"&gt;"Pieces"&lt;/span&gt;].values&lt;/span&gt;
&lt;span id="cb25-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb25-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;log_pieces &lt;span class="op"&gt;=&lt;/span&gt; np.log(df[&lt;span class="st"&gt;"Pieces"&lt;/span&gt;].values)&lt;/span&gt;
&lt;span id="cb25-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb25-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb25-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb25-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;rrp2021 &lt;span class="op"&gt;=&lt;/span&gt; df[&lt;span class="st"&gt;"RRP2021"&lt;/span&gt;].values&lt;/span&gt;
&lt;span id="cb25-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb25-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;log_rrp2021 &lt;span class="op"&gt;=&lt;/span&gt; np.log(rrp2021)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For computational efficiency, we will standardize &lt;span class="math inline"&gt;\(x_i\)&lt;/span&gt; to produce &lt;span class="math inline"&gt;\(\tilde{x}_i\)&lt;/span&gt; which has mean zero and variance one.&lt;/p&gt;
&lt;div class="sourceCode" id="cb26"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb26-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb26-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;scaler &lt;span class="op"&gt;=&lt;/span&gt; StandardScaler().fit(log_pieces[:, np.newaxis])&lt;/span&gt;
&lt;span id="cb26-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb26-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb26-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb26-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; scale_log_pieces(log_pieces, scaler&lt;span class="op"&gt;=&lt;/span&gt;scaler):&lt;/span&gt;
&lt;span id="cb26-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb26-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; scaler.transform(log_pieces[:, np.newaxis])[:, &lt;span class="dv"&gt;0&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb26-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb26-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb26-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb26-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_log_pieces &lt;span class="op"&gt;=&lt;/span&gt; scale_log_pieces(log_pieces)&lt;/span&gt;
&lt;span id="cb26-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb26-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_log_pieces_ &lt;span class="op"&gt;=&lt;/span&gt; shared(std_log_pieces)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here definining &lt;code&gt;std_log_pieces_&lt;/code&gt; as an &lt;code&gt;aesara&lt;/code&gt; &lt;code&gt;shared&lt;/code&gt; variable will allow us to change its value later for posterior predictive sampling.&lt;/p&gt;
&lt;p&gt;Our models are therefore given by&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[\log\left(f_i(X_i)\right) = \beta_{0, i} + \beta_i \tilde{x}_i.\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For the pooled model, &lt;span class="math inline"&gt;\(\beta_{0, i} = \beta_0\)&lt;/span&gt;, &lt;span class="math inline"&gt;\(\beta_i = \beta\)&lt;/span&gt;, and &lt;span class="math inline"&gt;\(\sigma_i = \sigma\)&lt;/span&gt; are constant across all sets. We give them the priors&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \beta_0
        &amp;amp; \sim N(0, 2.5^2) \\
    \beta
        &amp;amp; \sim N(0, 2.5^2) \\
    \sigma
        &amp;amp; \sim \textrm{HalfNormal}(5^2).
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb27"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb27-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb27-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; pooled_model:&lt;/span&gt;
&lt;span id="cb27-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb27-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"β0"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb27-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb27-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_pieces &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"β_pieces"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb27-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb27-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb27-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb27-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"σ"&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We define the mean and likelihood of the observed data as above.&lt;/p&gt;
&lt;div class="sourceCode" id="cb28"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb28-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb28-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pooled_model:&lt;/span&gt;
&lt;span id="cb28-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb28-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; β_pieces &lt;span class="op"&gt;*&lt;/span&gt; std_log_pieces_ &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="fl"&gt;0.5&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; σ&lt;span class="op"&gt;**&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb28-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"obs"&lt;/span&gt;, μ, σ, observed&lt;span class="op"&gt;=&lt;/span&gt;log_rrp2021)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now sample from posterior distribution of this model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb29"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb29-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb29-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;CHAINS &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb29-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SEED &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;123456789&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb29-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb29-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SAMPLE_KWARGS &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb29-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb29-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'cores'&lt;/span&gt;: CHAINS,&lt;/span&gt;
&lt;span id="cb29-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb29-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'random_seed'&lt;/span&gt;: [SEED &lt;span class="op"&gt;+&lt;/span&gt; i &lt;span class="cf"&gt;for&lt;/span&gt; i &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;range&lt;/span&gt;(CHAINS)],&lt;/span&gt;
&lt;span id="cb29-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb29-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'return_inferencedata'&lt;/span&gt;: &lt;span class="va"&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb29-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb30"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb30-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb30-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pooled_model:&lt;/span&gt;
&lt;span id="cb30-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb30-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    pooled_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [β0, β_pieces, σ]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="6000" class max="6000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [6000/6000 00:15&amp;lt;00:00 Sampling 3 chains, 0 divergences]&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Sampling 3 chains for 1_000 tune and 1_000 draw iterations (3_000 + 3_000 draws total) took 18 seconds.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The energy plot, BFMI, and &lt;span class="math inline"&gt;\(\hat{R}\)&lt;/span&gt; statistics for these samples show no cause for concern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb33"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb33-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; make_diagnostic_plots(trace, axes&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, min_mult&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.995&lt;/span&gt;, max_mult&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;1.005&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb33-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; axes &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb33-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb33-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                 figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;16&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb33-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb33-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    az.plot_energy(trace, ax&lt;span class="op"&gt;=&lt;/span&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb33-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb33-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb33-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    rhat &lt;span class="op"&gt;=&lt;/span&gt; az.rhat(trace).&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;
&lt;span id="cb33-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    axes[&lt;span class="dv"&gt;1&lt;/span&gt;].barh(np.arange(&lt;span class="bu"&gt;len&lt;/span&gt;(rhat.variables)), rhat.to_array(),&lt;/span&gt;
&lt;span id="cb33-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 tick_label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="bu"&gt;list&lt;/span&gt;(rhat.variables.keys()))&lt;/span&gt;
&lt;span id="cb33-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    axes[&lt;span class="dv"&gt;1&lt;/span&gt;].axvline(&lt;span class="dv"&gt;1&lt;/span&gt;, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, ls&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'--'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb33-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb33-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_xlim(&lt;/span&gt;
&lt;span id="cb33-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        min_mult &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="bu"&gt;min&lt;/span&gt;(rhat.&lt;span class="bu"&gt;min&lt;/span&gt;().to_array().&lt;span class="bu"&gt;min&lt;/span&gt;(), &lt;span class="dv"&gt;1&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb33-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        max_mult &lt;span class="op"&gt;*&lt;/span&gt; &lt;span class="bu"&gt;max&lt;/span&gt;(rhat.&lt;span class="bu"&gt;max&lt;/span&gt;().to_array().&lt;span class="bu"&gt;max&lt;/span&gt;(), &lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb33-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb33-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_xlabel(&lt;span class="vs"&gt;r"$\hat&lt;/span&gt;&lt;span class="sc"&gt;{R}&lt;/span&gt;&lt;span class="vs"&gt;$"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb33-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb33-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_ylabel(&lt;span class="st"&gt;"Variable"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb33-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb33-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb33-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; fig, axes&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb34"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb34-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb34-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_diagnostic_plots(pooled_trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_45_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We sample from the posterior predictive distribution at the observed data points and plot the residuals.&lt;/p&gt;
&lt;div class="sourceCode" id="cb35"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb35-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb35-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pooled_model:&lt;/span&gt;
&lt;span id="cb35-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb35-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    pp_trace_data &lt;span class="op"&gt;=&lt;/span&gt; pm.sample_posterior_predictive(pooled_trace)&lt;/span&gt;
&lt;span id="cb35-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb35-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb35-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb35-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df[&lt;span class="st"&gt;"pooled_resid"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (log_rrp2021 &lt;span class="op"&gt;-&lt;/span&gt; pp_trace_data[&lt;span class="st"&gt;"obs"&lt;/span&gt;]).mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="3000" class max="3000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [3000/3000 00:02&amp;lt;00:00]&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb36"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb36-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb36-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"pooled_resid"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df,&lt;/span&gt;
&lt;span id="cb36-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb36-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb36-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb36-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb36-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb36-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb36-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Pieces"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb36-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb36-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb36-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Log RRP residual (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb36-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb36-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb36-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Pooled model"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_48_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We will investigate these residuals further shortly. First we sample from the posterior predictive distribution along a grid spanning reasonable values of pieces and plot the resulting predictions.&lt;/p&gt;
&lt;div class="sourceCode" id="cb37"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb37-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb37-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_pieces &lt;span class="op"&gt;=&lt;/span&gt; np.logspace(&lt;span class="dv"&gt;1&lt;/span&gt;, np.log10(pieces.&lt;span class="bu"&gt;max&lt;/span&gt;()))&lt;/span&gt;
&lt;span id="cb37-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb37-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_log_pieces &lt;span class="op"&gt;=&lt;/span&gt; np.log(pp_pieces)&lt;/span&gt;
&lt;span id="cb37-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb37-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_std_log_pieces &lt;span class="op"&gt;=&lt;/span&gt; scale_log_pieces(pp_log_pieces)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb38"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb38-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb38-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_log_pieces_.set_value(pp_std_log_pieces)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb39"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb39-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb39-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pooled_model:&lt;/span&gt;
&lt;span id="cb39-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb39-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    pooled_pp_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample_posterior_predictive(pooled_trace)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="3000" class max="3000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [3000/3000 00:01&amp;lt;00:00]&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb40"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb40-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"RRP2021"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df,&lt;/span&gt;
&lt;span id="cb40-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.05&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb40-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"RRP2021"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb40-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                data&lt;span class="op"&gt;=&lt;/span&gt;df[df[&lt;span class="st"&gt;"austin"&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="va"&gt;True&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb40-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"My sets"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb40-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb40-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb40-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_low, pp_high &lt;span class="op"&gt;=&lt;/span&gt; np.percentile(&lt;/span&gt;
&lt;span id="cb40-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    np.exp(pooled_pp_trace[&lt;span class="st"&gt;"obs"&lt;/span&gt;]),&lt;/span&gt;
&lt;span id="cb40-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    [&lt;span class="fl"&gt;2.5&lt;/span&gt;, &lt;span class="fl"&gt;97.4&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb40-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb40-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb40-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot(pp_pieces, np.exp(pooled_pp_trace[&lt;span class="st"&gt;"obs"&lt;/span&gt;]).mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb40-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Posterior predicted mean"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb40-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.fill_between(pp_pieces, pp_low, pp_high,&lt;/span&gt;
&lt;span id="cb40-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.15&lt;/span&gt;, zorder&lt;span class="op"&gt;=-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb40-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"95% posterior interval"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb40-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb40-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb40-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb40-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb40-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Retail price (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb40-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb40-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb40-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'upper left'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_53_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The predictions seem reasonable. We now plot the posterior distribution of the regression coefficients.&lt;/p&gt;
&lt;div class="sourceCode" id="cb41"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb41-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb41-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_posterior(pooled_trace, var_names&lt;span class="op"&gt;=&lt;/span&gt;[&lt;span class="st"&gt;"β0"&lt;/span&gt;, &lt;span class="st"&gt;"β_pieces"&lt;/span&gt;])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_55_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;When we break down the residuals for a few notable themes, we see that Star Wars and Disney sets have larger residuals than Creator sets with the corresponding number of pieces.&lt;/p&gt;
&lt;div class="sourceCode" id="cb42"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb42-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb42-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"pooled_resid"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df,&lt;/span&gt;
&lt;span id="cb42-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb42-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb42-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb42-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb42-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;for&lt;/span&gt; theme &lt;span class="kw"&gt;in&lt;/span&gt; [&lt;span class="st"&gt;"Star Wars"&lt;/span&gt;, &lt;span class="st"&gt;"Creator"&lt;/span&gt;, &lt;span class="st"&gt;"Disney"&lt;/span&gt;]:&lt;/span&gt;
&lt;span id="cb42-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb42-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"pooled_resid"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb42-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb42-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    data&lt;span class="op"&gt;=&lt;/span&gt;df[df[&lt;span class="st"&gt;"Theme"&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; theme],&lt;/span&gt;
&lt;span id="cb42-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb42-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;f"&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;theme&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt; sets"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb42-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb42-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb42-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb42-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb42-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Pieces"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb42-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb42-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Log RRP residual (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb42-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb42-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Pooled model"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_57_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;This difference in the distribution of residuals across themes suggests that we introduce theme-specific factors into our model.&lt;/p&gt;
&lt;h3 id="unpooled-model"&gt;Unpooled model&lt;/h3&gt;
&lt;p&gt;In order to introduce theme-specific factors, we create indicator variables for each theme.&lt;/p&gt;
&lt;div class="sourceCode" id="cb43"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb43-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb43-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;theme_id, theme_map &lt;span class="op"&gt;=&lt;/span&gt; df[&lt;span class="st"&gt;"Theme"&lt;/span&gt;].factorize(sort&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb43-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb43-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_theme &lt;span class="op"&gt;=&lt;/span&gt; theme_map.size&lt;/span&gt;
&lt;span id="cb43-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb43-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb43-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb43-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;theme_id_ &lt;span class="op"&gt;=&lt;/span&gt; shared(theme_id)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The simplest model that includes theme-specific factors is an unpooled model that consists of independent regressions per theme. With &lt;span class="math inline"&gt;\(j(i)\)&lt;/span&gt; denoting the index of the theme of the &lt;span class="math inline"&gt;\(i\)&lt;/span&gt;-th set, we have the model&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[\log\left(f_i(X_i)\right) = \beta_{0, j(i)} + \beta_{j(i)} \tilde{x}_i\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;with the &lt;a href="https://en.wikipedia.org/wiki/Independent_and_identically_distributed_random_variables"&gt;i.i.d.&lt;/a&gt; priors&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \beta_{0, 1}, \ldots \beta_{0, n_j}
        &amp;amp; \sim N(0, 2.5^2) \\
    \beta_1, \ldots \beta_{n_j}
        &amp;amp; \sim N(0, 2.5^2) \\
    \sigma_1, \ldots, \sigma_{n_j}
        &amp;amp; \sim \textrm{HalfNormal}(5^2).
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb44"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb44-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb44-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_log_pieces_.set_value(std_log_pieces)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb45"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb45-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb45-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; unpooled_model:&lt;/span&gt;
&lt;span id="cb45-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb45-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"β0"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;n_theme)&lt;/span&gt;
&lt;span id="cb45-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb45-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_pieces &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"β_pieces"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;n_theme)&lt;/span&gt;
&lt;span id="cb45-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb45-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb45-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb45-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"σ"&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;n_theme)&lt;/span&gt;
&lt;span id="cb45-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb45-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; β&lt;span class="dv"&gt;0&lt;/span&gt;[theme_id_] &lt;span class="op"&gt;+&lt;/span&gt; β_pieces[theme_id_] &lt;span class="op"&gt;*&lt;/span&gt; std_log_pieces_ &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb45-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="fl"&gt;0.5&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; σ[theme_id_]&lt;span class="op"&gt;**&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb45-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb45-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb45-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"obs"&lt;/span&gt;, μ, σ[theme_id_], observed&lt;span class="op"&gt;=&lt;/span&gt;log_rrp2021)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We don’t actually sample from this model because it is underdetermined for many themes that have few sets associated with them, as the following plot shows.&lt;/p&gt;
&lt;div class="sourceCode" id="cb46"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb46-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb46-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; (df[&lt;span class="st"&gt;"Theme"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb46-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb46-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .value_counts()&lt;/span&gt;
&lt;span id="cb46-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb46-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .nsmallest(n&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;20&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb46-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb46-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .plot.barh())&lt;/span&gt;
&lt;span id="cb46-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb46-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb46-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb46-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Number of sets"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb46-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb46-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Theme"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_65_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;There are five themes with only a single set, and a number of themes with fewer than five sets total. Regression models with only a single data point are underdetermined, and those with few observations are likely to have wide error bars. Instead of imposing a minimum number of sets per theme and then using an unpooled model, we will use a partially pooled model to share some information across themes/regularize while allowing themes with many sets to deviate from the average if the data indicate that they should.&lt;/p&gt;
&lt;h3 id="partially-pooled-model"&gt;Partially pooled model&lt;/h3&gt;
&lt;p&gt;One model that shares information across themes is called “partially pooled” (it may also be called multilevel or hierarchical). In the partially pooled model, the intercept and piece coefficient for each theme are drawn not from i.i.d normal distributions but from a normal distribution with a common mean and variance. This shared hyperprior distribution regularizes the theme intercepts and coefficients, shrinking those for themes with fewer sets towards the pooled values.&lt;/p&gt;
&lt;p&gt;Conceptually, we use the priors&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \mu_{\beta_0}
        &amp;amp; \sim N(0, 2.5^2) \\
    \sigma_{\beta_0}
        &amp;amp; \sim \textrm{HalfNormal}(2.5^2) \\
    \beta_{0, 1}, \ldots, \beta_{0, n_j}
        &amp;amp; \sim N\left(\mu_{\beta_0}, \sigma_{\beta_0}^2\right)
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;and similarly for &lt;span class="math inline"&gt;\(\beta\)&lt;/span&gt;. In reality, we use a &lt;a href="https://twiecki.io/blog/2017/02/08/bayesian-hierchical-non-centered/"&gt;non-centered parametrization&lt;/a&gt; parameterization that is mathematically equivalent but often more computationally efficient.&lt;/p&gt;
&lt;div class="sourceCode" id="cb47"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb47-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb47-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; hierarchical_normal(name, shape, μ&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb47-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb47-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; μ &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb47-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb47-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        μ &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="ss"&gt;f"μ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb47-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb47-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb47-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb47-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    Δ &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="ss"&gt;f"Δ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;1.&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;shape)&lt;/span&gt;
&lt;span id="cb47-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb47-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="ss"&gt;f"σ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb47-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb47-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb47-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb47-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; pm.Deterministic(name, μ &lt;span class="op"&gt;+&lt;/span&gt; Δ &lt;span class="op"&gt;*&lt;/span&gt; σ)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb48"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb48-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb48-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; partial_model:&lt;/span&gt;
&lt;span id="cb48-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb48-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal(&lt;span class="st"&gt;"β0"&lt;/span&gt;, n_theme)&lt;/span&gt;
&lt;span id="cb48-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb48-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_pieces &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal(&lt;span class="st"&gt;"β_pieces"&lt;/span&gt;, n_theme)&lt;/span&gt;
&lt;span id="cb48-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb48-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb48-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb48-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"σ"&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb48-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb48-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; β&lt;span class="dv"&gt;0&lt;/span&gt;[theme_id_] &lt;span class="op"&gt;+&lt;/span&gt; β_pieces[theme_id_] &lt;span class="op"&gt;*&lt;/span&gt; std_log_pieces_ &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb48-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb48-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="fl"&gt;0.5&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; σ&lt;span class="op"&gt;**&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb48-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb48-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb48-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb48-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"obs"&lt;/span&gt;, μ, σ, observed&lt;span class="op"&gt;=&lt;/span&gt;log_rrp2021)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb49"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb49-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb49-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; partial_model:&lt;/span&gt;
&lt;span id="cb49-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb49-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    partial_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [μ_β0, Δ_β0, σ_β0, μ_β_pieces, Δ_β_pieces, σ_β_pieces, σ]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="6000" class max="6000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [6000/6000 03:15&amp;lt;00:00 Sampling 3 chains, 0 divergences]&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Sampling 3 chains for 1_000 tune and 1_000 draw iterations (3_000 + 3_000 draws total) took 196 seconds.
The estimated number of effective samples is smaller than 200 for some parameters.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again our diagnostics show no cause for concern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb52"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb52-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb52-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_diagnostic_plots(partial_trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_72_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;After calculating the residuals for the partially pooled model we see that they tend to be closer to zero and the diagonal bands are less pronounced.&lt;/p&gt;
&lt;div class="sourceCode" id="cb53"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb53-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb53-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; partial_model:&lt;/span&gt;
&lt;span id="cb53-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb53-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    pp_trace_data &lt;span class="op"&gt;=&lt;/span&gt; pm.sample_posterior_predictive(partial_trace)&lt;/span&gt;
&lt;span id="cb53-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb53-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb53-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb53-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df[&lt;span class="st"&gt;"partial_resid"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (log_rrp2021 &lt;span class="op"&gt;-&lt;/span&gt; pp_trace_data[&lt;span class="st"&gt;"obs"&lt;/span&gt;]).mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="3000" class max="3000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [3000/3000 00:02&amp;lt;00:00]&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb54"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb54-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb54-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;14&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb54-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb54-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"pooled_resid"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df,&lt;/span&gt;
&lt;span id="cb54-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.1&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb54-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb54-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;].set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb54-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;].set_xlabel(&lt;span class="st"&gt;"Pieces"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb54-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb54-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;].set_ylabel(&lt;span class="st"&gt;"Log RRP residual (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb54-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb54-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;].set_title(&lt;span class="st"&gt;"Pooled model"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb54-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb54-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"partial_resid"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df,&lt;/span&gt;
&lt;span id="cb54-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.1&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb54-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb54-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb54-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_xlabel(&lt;span class="st"&gt;"Pieces"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb54-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb54-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_ylabel(&lt;span class="st"&gt;"Log RRP residual (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb54-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb54-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_title(&lt;span class="st"&gt;"Partially pooled model"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb54-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb54-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb54-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_75_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We also see that the residuals for the example themes (Star Wars, Creator, and Disney) are more comingled than for the pooled model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb55"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb55-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb55-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;14&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb55-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb55-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"pooled_resid"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df,&lt;/span&gt;
&lt;span id="cb55-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.1&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb55-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;for&lt;/span&gt; theme &lt;span class="kw"&gt;in&lt;/span&gt; [&lt;span class="st"&gt;"Star Wars"&lt;/span&gt;, &lt;span class="st"&gt;"Creator"&lt;/span&gt;, &lt;span class="st"&gt;"Disney"&lt;/span&gt;]:&lt;/span&gt;
&lt;span id="cb55-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"pooled_resid"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb55-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    data&lt;span class="op"&gt;=&lt;/span&gt;df[df[&lt;span class="st"&gt;"Theme"&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; theme],&lt;/span&gt;
&lt;span id="cb55-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;f"&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;theme&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt; sets"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb55-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    ax&lt;span class="op"&gt;=&lt;/span&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb55-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;].set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;].set_xlabel(&lt;span class="st"&gt;"Pieces"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb55-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;].set_ylabel(&lt;span class="st"&gt;"Log RRP residual (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb55-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;].set_title(&lt;span class="st"&gt;"Pooled model"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb55-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"partial_resid"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df,&lt;/span&gt;
&lt;span id="cb55-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.1&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb55-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;for&lt;/span&gt; theme &lt;span class="kw"&gt;in&lt;/span&gt; [&lt;span class="st"&gt;"Star Wars"&lt;/span&gt;, &lt;span class="st"&gt;"Creator"&lt;/span&gt;, &lt;span class="st"&gt;"Disney"&lt;/span&gt;]:&lt;/span&gt;
&lt;span id="cb55-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"partial_resid"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb55-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    data&lt;span class="op"&gt;=&lt;/span&gt;df[df[&lt;span class="st"&gt;"Theme"&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; theme],&lt;/span&gt;
&lt;span id="cb55-26"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;f"&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;theme&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt; sets"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb55-27"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    ax&lt;span class="op"&gt;=&lt;/span&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-28"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb55-29"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-30"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_xlabel(&lt;span class="st"&gt;"Pieces"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-31"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb55-32"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_ylabel(&lt;span class="st"&gt;"Log RRP residual (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-33"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb55-34"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_title(&lt;span class="st"&gt;"Partially pooloed model"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb55-35"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb55-36"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb55-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_77_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Now that we have posterior samples from two models, we use Pareto-smoothed importance sampling leave-one-out cross validation&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb56"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb56-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb56-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;traces &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb56-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb56-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"Unpooled"&lt;/span&gt;: pooled_trace,&lt;/span&gt;
&lt;span id="cb56-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb56-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"Partially pooled"&lt;/span&gt;: partial_trace&lt;/span&gt;
&lt;span id="cb56-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb56-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb57"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb57-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb57-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;comp_df &lt;span class="op"&gt;=&lt;/span&gt; az.compare(traces)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb58"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb58-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb58-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;comp_df.loc[:, :&lt;span class="st"&gt;"weight"&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
rank
&lt;/th&gt;
&lt;th&gt;
loo
&lt;/th&gt;
&lt;th&gt;
p_loo
&lt;/th&gt;
&lt;th&gt;
d_loo
&lt;/th&gt;
&lt;th&gt;
weight
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
Partially pooled
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
-2315.578245
&lt;/td&gt;
&lt;td&gt;
190.594364
&lt;/td&gt;
&lt;td&gt;
0.000000
&lt;/td&gt;
&lt;td&gt;
0.99951
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Unpooled
&lt;/th&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
-5133.311893
&lt;/td&gt;
&lt;td&gt;
4.871287
&lt;/td&gt;
&lt;td&gt;
2817.733648
&lt;/td&gt;
&lt;td&gt;
0.00049
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb59"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb59-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb59-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;12&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb59-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb59-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb59-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb59-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_compare(comp_df, plot_ic_diff&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_82_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The table and chart show that by sharing some information across themes while also incorporating their varying effects the partially pooled model has substantially better predictive accuracy than the pooled model (higher values of &lt;code&gt;loo&lt;/code&gt; correspond to better predictive ability).&lt;/p&gt;
&lt;p&gt;In order to compare the posterior predictions of the pooled and partially pooled model directly, we need to define a grid over theme/standardized log piece combinations.&lt;/p&gt;
&lt;div class="sourceCode" id="cb60"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb60-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb60-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_df &lt;span class="op"&gt;=&lt;/span&gt; pd.DataFrame.from_records(&lt;/span&gt;
&lt;span id="cb60-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb60-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    itl.product(&lt;span class="bu"&gt;range&lt;/span&gt;(n_theme), pp_std_log_pieces),&lt;/span&gt;
&lt;span id="cb60-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb60-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    columns&lt;span class="op"&gt;=&lt;/span&gt;[&lt;span class="st"&gt;"theme_id"&lt;/span&gt;, &lt;span class="st"&gt;"std_log_pieces"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb60-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb60-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb60-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb60-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_df[&lt;span class="st"&gt;"theme"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; theme_map[pp_df[&lt;span class="st"&gt;"theme_id"&lt;/span&gt;].values]&lt;/span&gt;
&lt;span id="cb60-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb60-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_df[&lt;span class="st"&gt;"pieces"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; np.exp(&lt;/span&gt;
&lt;span id="cb60-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb60-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    scaler.inverse_transform(pp_df[&lt;span class="st"&gt;"std_log_pieces"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb60-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb60-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                  .values[:, np.newaxis])&lt;/span&gt;
&lt;span id="cb60-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb60-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          .ravel()&lt;/span&gt;
&lt;span id="cb60-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb60-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb61"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb61-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb61-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
theme_id
&lt;/th&gt;
&lt;th&gt;
std_log_pieces
&lt;/th&gt;
&lt;th&gt;
theme
&lt;/th&gt;
&lt;th&gt;
pieces
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
-2.373432
&lt;/td&gt;
&lt;td&gt;
4 Juniors
&lt;/td&gt;
&lt;td&gt;
10.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
-2.252260
&lt;/td&gt;
&lt;td&gt;
4 Juniors
&lt;/td&gt;
&lt;td&gt;
11.550805
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
-2.131088
&lt;/td&gt;
&lt;td&gt;
4 Juniors
&lt;/td&gt;
&lt;td&gt;
13.342109
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
3
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
-2.009916
&lt;/td&gt;
&lt;td&gt;
4 Juniors
&lt;/td&gt;
&lt;td&gt;
15.411210
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
4
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
-1.888744
&lt;/td&gt;
&lt;td&gt;
4 Juniors
&lt;/td&gt;
&lt;td&gt;
17.801188
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb62"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb62-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb62-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_df.tail()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
theme_id
&lt;/th&gt;
&lt;th&gt;
std_log_pieces
&lt;/th&gt;
&lt;th&gt;
theme
&lt;/th&gt;
&lt;th&gt;
pieces
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
6545
&lt;/th&gt;
&lt;td&gt;
130
&lt;/td&gt;
&lt;td&gt;
3.079305
&lt;/td&gt;
&lt;td&gt;
Znap
&lt;/td&gt;
&lt;td&gt;
6569.786072
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
6546
&lt;/th&gt;
&lt;td&gt;
130
&lt;/td&gt;
&lt;td&gt;
3.200477
&lt;/td&gt;
&lt;td&gt;
Znap
&lt;/td&gt;
&lt;td&gt;
7588.631734
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
6547
&lt;/th&gt;
&lt;td&gt;
130
&lt;/td&gt;
&lt;td&gt;
3.321649
&lt;/td&gt;
&lt;td&gt;
Znap
&lt;/td&gt;
&lt;td&gt;
8765.480484
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
6548
&lt;/th&gt;
&lt;td&gt;
130
&lt;/td&gt;
&lt;td&gt;
3.442820
&lt;/td&gt;
&lt;td&gt;
Znap
&lt;/td&gt;
&lt;td&gt;
10124.835517
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
6549
&lt;/th&gt;
&lt;td&gt;
130
&lt;/td&gt;
&lt;td&gt;
3.563992
&lt;/td&gt;
&lt;td&gt;
Znap
&lt;/td&gt;
&lt;td&gt;
11695.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb63"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb63-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb63-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_log_pieces_.set_value(pp_df[&lt;span class="st"&gt;"std_log_pieces"&lt;/span&gt;].values)&lt;/span&gt;
&lt;span id="cb63-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb63-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;theme_id_.set_value(pp_df[&lt;span class="st"&gt;"theme_id"&lt;/span&gt;].values)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now sample from the posterior predictive distribution and compare the predictions to those from the pooled model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb64"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb64-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb64-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; partial_model:&lt;/span&gt;
&lt;span id="cb64-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb64-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    partial_pp_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample_posterior_predictive(partial_trace)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="3000" class max="3000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [3000/3000 00:02&amp;lt;00:00]&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb65"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb65-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb65-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_df[&lt;span class="st"&gt;"pp_partial_mean"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; np.exp(partial_pp_trace[&lt;span class="st"&gt;"obs"&lt;/span&gt;]).mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb65-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb65-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_df[&lt;span class="st"&gt;"pp_partial_low"&lt;/span&gt;], pp_df[&lt;span class="st"&gt;"pp_partial_high"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; np.percentile(&lt;/span&gt;
&lt;span id="cb65-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb65-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    np.exp(partial_pp_trace[&lt;span class="st"&gt;"obs"&lt;/span&gt;]),&lt;/span&gt;
&lt;span id="cb65-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb65-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    [&lt;span class="fl"&gt;2.5&lt;/span&gt;, &lt;span class="fl"&gt;97.5&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb65-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb65-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb65-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb65-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb66"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb66-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb66-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
theme_id
&lt;/th&gt;
&lt;th&gt;
std_log_pieces
&lt;/th&gt;
&lt;th&gt;
theme
&lt;/th&gt;
&lt;th&gt;
pieces
&lt;/th&gt;
&lt;th&gt;
pp_partial_mean
&lt;/th&gt;
&lt;th&gt;
pp_partial_low
&lt;/th&gt;
&lt;th&gt;
pp_partial_high
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
-2.373432
&lt;/td&gt;
&lt;td&gt;
4 Juniors
&lt;/td&gt;
&lt;td&gt;
10.000000
&lt;/td&gt;
&lt;td&gt;
5.214650
&lt;/td&gt;
&lt;td&gt;
2.380664
&lt;/td&gt;
&lt;td&gt;
10.484612
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
-2.252260
&lt;/td&gt;
&lt;td&gt;
4 Juniors
&lt;/td&gt;
&lt;td&gt;
11.550805
&lt;/td&gt;
&lt;td&gt;
5.917360
&lt;/td&gt;
&lt;td&gt;
2.668467
&lt;/td&gt;
&lt;td&gt;
11.413480
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
-2.131088
&lt;/td&gt;
&lt;td&gt;
4 Juniors
&lt;/td&gt;
&lt;td&gt;
13.342109
&lt;/td&gt;
&lt;td&gt;
6.864103
&lt;/td&gt;
&lt;td&gt;
3.045283
&lt;/td&gt;
&lt;td&gt;
13.610948
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
3
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
-2.009916
&lt;/td&gt;
&lt;td&gt;
4 Juniors
&lt;/td&gt;
&lt;td&gt;
15.411210
&lt;/td&gt;
&lt;td&gt;
7.653877
&lt;/td&gt;
&lt;td&gt;
3.515344
&lt;/td&gt;
&lt;td&gt;
14.966362
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
4
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
-1.888744
&lt;/td&gt;
&lt;td&gt;
4 Juniors
&lt;/td&gt;
&lt;td&gt;
17.801188
&lt;/td&gt;
&lt;td&gt;
8.679962
&lt;/td&gt;
&lt;td&gt;
4.009006
&lt;/td&gt;
&lt;td&gt;
16.935274
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb67"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb67-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"RRP2021"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df,&lt;/span&gt;
&lt;span id="cb67-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.05&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb67-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(pp_df.groupby(&lt;span class="st"&gt;"theme_id"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb67-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .plot(&lt;span class="st"&gt;"pieces"&lt;/span&gt;, &lt;span class="st"&gt;"pp_partial_mean"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb67-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.1&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'_nolegend_'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb67-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ax&lt;span class="op"&gt;=&lt;/span&gt;ax))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot(pp_pieces, np.exp(pooled_pp_trace[&lt;span class="st"&gt;"obs"&lt;/span&gt;]).mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb67-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'r'&lt;/span&gt;, lw&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pooled"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb67-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb67-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Retail price (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb67-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb67-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;handles, _ &lt;span class="op"&gt;=&lt;/span&gt; ax.get_legend_handles_labels()&lt;/span&gt;
&lt;span id="cb67-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;partial_line &lt;span class="op"&gt;=&lt;/span&gt; Line2D([&lt;span class="dv"&gt;0&lt;/span&gt;], [&lt;span class="dv"&gt;0&lt;/span&gt;], color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb67-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Partially pooled"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb67-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;handles.append(partial_line)&lt;/span&gt;
&lt;span id="cb67-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb67-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend(handles&lt;span class="op"&gt;=&lt;/span&gt;handles,&lt;/span&gt;
&lt;span id="cb67-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          title&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Posterior predicted mean"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb67-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb67-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'upper left'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_92_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Note that the partial pooling model produces one line per theme, with varying slopes and intercepts. We can see that while the predictions for some themes are quite far away from the pooled predictions most are close to them, as shown by the stacking of the semi-transparent lines. Below we highlight the partially pooled predictions for a few themes of interest among all partially pooled predictions.&lt;/p&gt;
&lt;div class="sourceCode" id="cb68"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb68-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb68-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;PLOT_THEMES &lt;span class="op"&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb68-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb68-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"Creator Expert"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb68-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb68-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"Disney"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb68-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb68-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"Star Wars"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb68-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb68-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"Harry Potter"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb68-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb68-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"Marvel Super Heroes"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb68-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb68-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"Ninjago"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb68-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb68-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"City"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb68-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb68-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"Space"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb68-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb68-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"Jurassic World"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb68-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb68-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb69"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb69-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"RRP2021"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df,&lt;/span&gt;
&lt;span id="cb69-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.05&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb69-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb69-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(pp_df.groupby(&lt;span class="st"&gt;"theme_id"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb69-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .plot(&lt;span class="st"&gt;"pieces"&lt;/span&gt;, &lt;span class="st"&gt;"pp_partial_mean"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb69-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.1&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'_nolegend_'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb69-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ax&lt;span class="op"&gt;=&lt;/span&gt;ax))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb69-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(pp_df[pp_df[&lt;span class="st"&gt;"theme"&lt;/span&gt;].isin(PLOT_THEMES)]&lt;/span&gt;
&lt;span id="cb69-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .groupby(&lt;span class="st"&gt;"theme_id"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb69-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .plot(&lt;span class="st"&gt;"pieces"&lt;/span&gt;, &lt;span class="st"&gt;"pp_partial_mean"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb69-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'r'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'_nolegend_'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb69-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ax&lt;span class="op"&gt;=&lt;/span&gt;ax))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb69-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb69-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb69-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb69-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb69-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Retail price (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb69-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb69-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;title &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="st"&gt;"Highlighted: "&lt;/span&gt; \&lt;/span&gt;
&lt;span id="cb69-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="st"&gt;", "&lt;/span&gt;.join(PLOT_THEMES[:&lt;span class="dv"&gt;4&lt;/span&gt;]) &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="st"&gt;",&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;"&lt;/span&gt; \&lt;/span&gt;
&lt;span id="cb69-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="st"&gt;", "&lt;/span&gt;.join(PLOT_THEMES[&lt;span class="dv"&gt;4&lt;/span&gt;:&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;]) &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb69-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="st"&gt;", and "&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; PLOT_THEMES[&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb69-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb69-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(title)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_95_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;These notable themes have preditions close to the global average, which makes sense since they all have a fair number of sets, so the global mean is pulled towards their theme effects.&lt;/p&gt;
&lt;p&gt;It has long been known in the quantitative social sciences that when naively modeled (as we have) that group-level effects (in this case theme-level effects), can strongly correlate with item-level covariates (in this case standardized log pieces). We now investigate whether our partially pooled model results in such a correlation.&lt;/p&gt;
&lt;p&gt;First we calculate the average value of &lt;code&gt;std_log_pieces&lt;/code&gt; within each theme.&lt;/p&gt;
&lt;div class="sourceCode" id="cb70"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb70-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb70-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;theme_mean_std_log_pieces &lt;span class="op"&gt;=&lt;/span&gt; (pd.Series(std_log_pieces, index&lt;span class="op"&gt;=&lt;/span&gt;df.index)&lt;/span&gt;
&lt;span id="cb70-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb70-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               .groupby(df[&lt;span class="st"&gt;"Theme"&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb70-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb70-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               .mean())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb71"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb71-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb71-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; theme_mean_std_log_pieces.plot.hist(bins&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;20&lt;/span&gt;, lw&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb71-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb71-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb71-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb71-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Average standardized log pieces&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;per set within theme"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_98_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that these theme averages vary fairly widely. The following plots show the relationship between each theme’s average standardized log pieces and the posterior expected values of &lt;span class="math inline"&gt;\(\beta_{0, j}\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(\beta_j\)&lt;/span&gt; respectively.&lt;/p&gt;
&lt;div class="sourceCode" id="cb72"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb72-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb72-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;post_β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; partial_trace[&lt;span class="st"&gt;"posterior"&lt;/span&gt;][&lt;span class="st"&gt;"β0"&lt;/span&gt;].mean(dim&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="st"&gt;'chain'&lt;/span&gt;, &lt;span class="st"&gt;'draw'&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb72-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb72-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;post_β_pieces &lt;span class="op"&gt;=&lt;/span&gt; partial_trace[&lt;span class="st"&gt;"posterior"&lt;/span&gt;][&lt;span class="st"&gt;"β_pieces"&lt;/span&gt;].mean(dim&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="st"&gt;'chain'&lt;/span&gt;, &lt;span class="st"&gt;'draw'&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb73"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb73-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, (β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;, β_pieces_ax) &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots( &lt;/span&gt;
&lt;span id="cb73-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb73-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;15&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb73-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb73-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb73-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;.scatter(theme_mean_std_log_pieces, post_β&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb73-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb73-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;.set_xlabel(&lt;span class="st"&gt;"Average standardized log pieces&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;per set within theme"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb73-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;.set_ylabel(&lt;span class="st"&gt;"Posterior expected&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;value of $&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="st"&gt;beta_0$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb73-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt; &lt;/span&gt;
&lt;span id="cb73-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_corr&lt;/span&gt;, β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_corr_p_val&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; sp.stats.pearsonr(&lt;/span&gt;
&lt;span id="cb73-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    theme_mean_std_log_pieces.values,&lt;/span&gt;
&lt;span id="cb73-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    post_β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb73-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb73-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;.set_title(&lt;span class="ss"&gt;f"Correlation coefficient = &lt;/span&gt;&lt;span class="sc"&gt;{β&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_corr&lt;/span&gt;&lt;span class="sc"&gt;:0.2f}&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb73-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="ss"&gt;f"Two-tailed p-value &lt;/span&gt;&lt;span class="sc"&gt;{β&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_corr_p_val&lt;/span&gt;&lt;span class="sc"&gt;:.2e}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb73-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb73-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β_pieces_ax.scatter(theme_mean_std_log_pieces, post_β_pieces)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb73-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb73-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β_pieces_ax.set_xlabel(&lt;span class="st"&gt;"Average standardized log pieces&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;per set within theme"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb73-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β_pieces_ax.set_ylabel(&lt;span class="st"&gt;"Posterior expected&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;value of $&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="st"&gt;beta_&lt;/span&gt;&lt;span class="sc"&gt;{pieces}&lt;/span&gt;&lt;span class="st"&gt;$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb73-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb73-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β_pieces_corr, β_pieces_corr_p_val &lt;span class="op"&gt;=&lt;/span&gt; sp.stats.pearsonr(&lt;/span&gt;
&lt;span id="cb73-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    theme_mean_std_log_pieces.values,&lt;/span&gt;
&lt;span id="cb73-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    post_β_pieces&lt;/span&gt;
&lt;span id="cb73-26"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb73-27"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β_pieces_ax.set_title(&lt;span class="ss"&gt;f"Correlation coefficient = &lt;/span&gt;&lt;span class="sc"&gt;{β&lt;/span&gt;_pieces_corr&lt;span class="sc"&gt;:0.2f}&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb73-28"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb73-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      &lt;span class="ss"&gt;f"Two-tailed p-value &lt;/span&gt;&lt;span class="sc"&gt;{β&lt;/span&gt;_pieces_corr_p_val&lt;span class="sc"&gt;:.2e}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_101_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Both plots show highly significant correlations, with a stronger correlation between the theme average and the posterior expected average of &lt;span class="math inline"&gt;\(\beta_{0, j}\)&lt;/span&gt;. These correlations lead to violations of the &lt;a href="https://en.wikipedia.org/wiki/Gauss%E2%80%93Markov_theorem"&gt;Gauss-Markov assumptions&lt;/a&gt; in our regression design, so we remedy them with an expanded model in the next section.&lt;/p&gt;
&lt;h3 id="partially-pooled-mean-model"&gt;Partially pooled mean model&lt;/h3&gt;
&lt;p&gt;Fortunately Bafumi and Gelman&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; show how to remedy this violation by including the theme-level average standardized log pieces as a covariate in &lt;span class="math inline"&gt;\(\beta_{0, j}\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(\beta_j\)&lt;/span&gt;. if we denote the average standardized log pieces for sets in the &lt;span class="math inline"&gt;\(j\)&lt;/span&gt;-th theme as &lt;span class="math inline"&gt;\(\bar{\tilde{x}}_j\)&lt;/span&gt;, in this extended model, &lt;span class="math inline"&gt;\(\beta_{0, j}\)&lt;/span&gt; is defined as&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \mu_{\beta_0}, \gamma_{\beta, 0}
        &amp;amp; \sim N(0, 2.5^2) \\
    \sigma_{\beta_0}
        &amp;amp; \sim \textrm{HalfNormal}(2.5^2) \\
    \beta_{0, j}
        &amp;amp; \sim N\left(\mu_{\beta_0} + \gamma_{\beta, 0} \cdot \bar{\tilde{x}}_j, \sigma_{\beta_0}^2\right),
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;and similarly for &lt;span class="math inline"&gt;\(\beta_j\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb74"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb74-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb74-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; hierarchical_normal_with_mean(name, x_mean, shape, μ&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb74-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb74-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    γ &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="ss"&gt;f"γ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb74-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb74-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb74-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb74-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; hierarchical_normal(name, shape, μ&lt;span class="op"&gt;=&lt;/span&gt;μ) &lt;span class="op"&gt;+&lt;/span&gt; γ &lt;span class="op"&gt;*&lt;/span&gt; x_mean&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb75"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb75-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb75-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; mean_model:&lt;/span&gt;
&lt;span id="cb75-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb75-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"σ"&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb75-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb75-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb75-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb75-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal_with_mean(&lt;/span&gt;
&lt;span id="cb75-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb75-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;"β0"&lt;/span&gt;, at.constant(theme_mean_std_log_pieces),&lt;/span&gt;
&lt;span id="cb75-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb75-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        n_theme&lt;/span&gt;
&lt;span id="cb75-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb75-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb75-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb75-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_pieces &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal_with_mean(&lt;/span&gt;
&lt;span id="cb75-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb75-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;"β_pieces"&lt;/span&gt;, at.constant(theme_mean_std_log_pieces),&lt;/span&gt;
&lt;span id="cb75-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb75-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        n_theme&lt;/span&gt;
&lt;span id="cb75-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb75-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb75-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb75-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb75-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb75-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; β&lt;span class="dv"&gt;0&lt;/span&gt;[theme_id_] &lt;span class="op"&gt;+&lt;/span&gt; β_pieces[theme_id_] &lt;span class="op"&gt;*&lt;/span&gt; std_log_pieces_ &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb75-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb75-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="fl"&gt;0.5&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; σ&lt;span class="op"&gt;**&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb75-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb75-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb75-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb75-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"obs"&lt;/span&gt;, μ, σ, observed&lt;span class="op"&gt;=&lt;/span&gt;log_rrp2021)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now sample from this model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb76"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb76-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb76-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;std_log_pieces_.set_value(std_log_pieces)&lt;/span&gt;
&lt;span id="cb76-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb76-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;theme_id_.set_value(theme_id)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb77"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb77-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb77-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; mean_model:&lt;/span&gt;
&lt;span id="cb77-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb77-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    mean_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [σ, γ_β0, μ_β0, Δ_β0, σ_β0, γ_β_pieces, μ_β_pieces, Δ_β_pieces, σ_β_pieces]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="6000" class max="6000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [6000/6000 03:57&amp;lt;00:00 Sampling 3 chains, 0 divergences]&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Sampling 3 chains for 1_000 tune and 1_000 draw iterations (3_000 + 3_000 draws total) took 239 seconds.
The number of effective samples is smaller than 10% for some parameters.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once again the sampling diagnostics show no cause for concern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb80"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb80-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb80-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_diagnostic_plots(mean_trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_110_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The correlations from above have disappeared in this model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb81"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb81-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb81-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;post_β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; mean_trace[&lt;span class="st"&gt;"posterior"&lt;/span&gt;][&lt;span class="st"&gt;"β0"&lt;/span&gt;].mean(dim&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="st"&gt;'chain'&lt;/span&gt;, &lt;span class="st"&gt;'draw'&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb81-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb81-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;post_β_pieces &lt;span class="op"&gt;=&lt;/span&gt; mean_trace[&lt;span class="st"&gt;"posterior"&lt;/span&gt;][&lt;span class="st"&gt;"β_pieces"&lt;/span&gt;].mean(dim&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="st"&gt;'chain'&lt;/span&gt;, &lt;span class="st"&gt;'draw'&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb82"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb82-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, (β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;, β_pieces_ax) &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots( &lt;/span&gt;
&lt;span id="cb82-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb82-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;15&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb82-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb82-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb82-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;.scatter(theme_mean_std_log_pieces, post_β&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb82-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb82-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;.set_xlabel(&lt;span class="st"&gt;"Average standardized log pieces&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;per set within theme"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb82-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;.set_ylabel(&lt;span class="st"&gt;"Posterior expected&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;value of $&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="st"&gt;beta_0$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb82-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt; &lt;/span&gt;
&lt;span id="cb82-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_corr&lt;/span&gt;, β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_corr_p_val&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; sp.stats.pearsonr(&lt;/span&gt;
&lt;span id="cb82-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    theme_mean_std_log_pieces.values,&lt;/span&gt;
&lt;span id="cb82-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    post_β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb82-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb82-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;.set_title(&lt;span class="ss"&gt;f"Correlation coefficient = &lt;/span&gt;&lt;span class="sc"&gt;{β&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_corr&lt;/span&gt;&lt;span class="sc"&gt;:0.2f}&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb82-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="ss"&gt;f"Two-tailed p-value &lt;/span&gt;&lt;span class="sc"&gt;{β&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_corr_p_val&lt;/span&gt;&lt;span class="sc"&gt;:.2f}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb82-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb82-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β_pieces_ax.scatter(theme_mean_std_log_pieces, post_β_pieces)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb82-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb82-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β_pieces_ax.set_xlabel(&lt;span class="st"&gt;"Average standardized log pieces&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;per set within theme"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb82-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β_pieces_ax.set_ylabel(&lt;span class="st"&gt;"Posterior expected&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;value of $&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="st"&gt;beta_&lt;/span&gt;&lt;span class="sc"&gt;{pieces}&lt;/span&gt;&lt;span class="st"&gt;$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb82-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb82-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β_pieces_corr, β_pieces_corr_p_val &lt;span class="op"&gt;=&lt;/span&gt; sp.stats.pearsonr(&lt;/span&gt;
&lt;span id="cb82-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    theme_mean_std_log_pieces.values,&lt;/span&gt;
&lt;span id="cb82-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    post_β_pieces&lt;/span&gt;
&lt;span id="cb82-26"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb82-27"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;β_pieces_ax.set_title(&lt;span class="ss"&gt;f"Correlation coefficient = &lt;/span&gt;&lt;span class="sc"&gt;{β&lt;/span&gt;_pieces_corr&lt;span class="sc"&gt;:0.2f}&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb82-28"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb82-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      &lt;span class="ss"&gt;f"Two-tailed p-value &lt;/span&gt;&lt;span class="sc"&gt;{β&lt;/span&gt;_pieces_corr_p_val&lt;span class="sc"&gt;:.2f}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_113_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We add this model to our comparison.&lt;/p&gt;
&lt;div class="sourceCode" id="cb83"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb83-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb83-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;traces[&lt;span class="st"&gt;"Partially pooled with mean"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; mean_trace&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb84"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb84-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb84-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;comp_df &lt;span class="op"&gt;=&lt;/span&gt; az.compare(traces)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb85"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb85-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb85-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;comp_df.loc[:, :&lt;span class="st"&gt;"weight"&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
rank
&lt;/th&gt;
&lt;th&gt;
loo
&lt;/th&gt;
&lt;th&gt;
p_loo
&lt;/th&gt;
&lt;th&gt;
d_loo
&lt;/th&gt;
&lt;th&gt;
weight
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
Partially pooled
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
-2315.578245
&lt;/td&gt;
&lt;td&gt;
190.594364
&lt;/td&gt;
&lt;td&gt;
0.000000
&lt;/td&gt;
&lt;td&gt;
0.958583
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Partially pooled with mean
&lt;/th&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
-2316.840059
&lt;/td&gt;
&lt;td&gt;
187.512592
&lt;/td&gt;
&lt;td&gt;
1.261814
&lt;/td&gt;
&lt;td&gt;
0.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Unpooled
&lt;/th&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
-5133.311893
&lt;/td&gt;
&lt;td&gt;
4.871287
&lt;/td&gt;
&lt;td&gt;
2817.733648
&lt;/td&gt;
&lt;td&gt;
0.041417
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb86"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb86-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb86-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;12&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb86-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb86-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb86-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb86-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_compare(comp_df, plot_ic_diff&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_118_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that the the PSIS-LOO scores of both partially pooled model are better than the pooled model and statistically indistinguishable from each other. Given these scores, we will work with the model that accounts for the theme’s average standardized log pieces going forward, since it satisfies the Gauss-Markov assumptions better.&lt;/p&gt;
&lt;p&gt;The residuals from the two partially pooled models are also visually quite similar, though the second partial pooling model does have less pronounced diagonal bands.&lt;/p&gt;
&lt;div class="sourceCode" id="cb87"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb87-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb87-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; mean_model:&lt;/span&gt;
&lt;span id="cb87-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb87-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    pp_trace_data &lt;span class="op"&gt;=&lt;/span&gt; pm.sample_posterior_predictive(mean_trace)&lt;/span&gt;
&lt;span id="cb87-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb87-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb87-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb87-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df[&lt;span class="st"&gt;"mean_resid"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (log_rrp2021 &lt;span class="op"&gt;-&lt;/span&gt; pp_trace_data[&lt;span class="st"&gt;"obs"&lt;/span&gt;]).mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="3000" class max="3000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [3000/3000 00:01&amp;lt;00:00]&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb88"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb88-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb88-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;14&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb88-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb88-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"pooled_resid"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df,&lt;/span&gt;
&lt;span id="cb88-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.1&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb88-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb88-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;].set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb88-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;].set_xlabel(&lt;span class="st"&gt;"Pieces"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb88-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb88-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;].set_ylabel(&lt;span class="st"&gt;"Log RRP residual (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb88-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb88-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;].set_title(&lt;span class="st"&gt;"Partially pooled model"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb88-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb88-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"mean_resid"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df,&lt;/span&gt;
&lt;span id="cb88-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.1&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb88-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb88-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb88-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_xlabel(&lt;span class="st"&gt;"Pieces"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb88-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb88-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_ylabel(&lt;span class="st"&gt;"Log RRP residual (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb88-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb88-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_title(&lt;span class="st"&gt;"Partially pooled mean model"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb88-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb88-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb88-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_121_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Interestingly, there is more variation in the varying intercepts (&lt;span class="math inline"&gt;\(\beta_{0, j}\)&lt;/span&gt;) than the varying slopes (&lt;span class="math inline"&gt;\(\beta_j\)&lt;/span&gt;), since &lt;span class="math inline"&gt;\(\sigma_{\beta_0}\)&lt;/span&gt; has a larger posterior expected value than &lt;span class="math inline"&gt;\(\sigma_{\beta}\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb89"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb89-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb89-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_posterior(mean_trace,&lt;/span&gt;
&lt;span id="cb89-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb89-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                  var_names&lt;span class="op"&gt;=&lt;/span&gt;[&lt;/span&gt;
&lt;span id="cb89-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb89-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      &lt;span class="st"&gt;"μ_β0"&lt;/span&gt;, &lt;span class="st"&gt;"μ_β_pieces"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb89-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb89-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      &lt;span class="st"&gt;"σ_β0"&lt;/span&gt;, &lt;span class="st"&gt;"σ_β_pieces"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb89-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb89-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                  ],&lt;/span&gt;
&lt;span id="cb89-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb89-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                  grid&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;2&lt;/span&gt;, &lt;span class="dv"&gt;2&lt;/span&gt;))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_123_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Plotting the residuals of log RRP in 2021 dollars versus time shows that the residuals for this model are significantly larger for sets between 1980 and 1995. This phenomenon makes sense as Lego has released many more sets per year after 1995 than in the initial period, so the estimates are dominated by the data in this later period.&lt;/p&gt;
&lt;div class="sourceCode" id="cb90"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb90-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; (df.groupby(level&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Year released"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb90-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        [&lt;span class="st"&gt;"mean_resid"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb90-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .mean()&lt;/span&gt;
&lt;span id="cb90-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .plot(c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Year average"&lt;/span&gt;))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb90-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb90-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;strip_ax &lt;span class="op"&gt;=&lt;/span&gt; ax.twiny()&lt;/span&gt;
&lt;span id="cb90-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.stripplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Year released"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"mean_resid"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb90-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              data&lt;span class="op"&gt;=&lt;/span&gt;df.reset_index(),&lt;/span&gt;
&lt;span id="cb90-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              jitter&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;1.5&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb90-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.1&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb90-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              ax&lt;span class="op"&gt;=&lt;/span&gt;strip_ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb90-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb90-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;strip_ax.set_axis_off()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb90-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb90-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylim(&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, &lt;span class="dv"&gt;2&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb90-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Log RRP residual (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb90-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb90-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb90-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'upper left'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_125_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;h3 id="time-varying-model"&gt;Time-varying model&lt;/h3&gt;
&lt;p&gt;We address this issue with the residuals by adding a time-varying component to &lt;span class="math inline"&gt;\(\beta_0\)&lt;/span&gt;. First we build &lt;code&gt;t&lt;/code&gt;, which indicates the number of years after the data begins in 1980 that the set was released.&lt;/p&gt;
&lt;div class="sourceCode" id="cb91"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb91-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb91-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;year &lt;span class="op"&gt;=&lt;/span&gt; df.index.get_level_values(&lt;span class="st"&gt;"Year released"&lt;/span&gt;).year.values&lt;/span&gt;
&lt;span id="cb91-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb91-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;t &lt;span class="op"&gt;=&lt;/span&gt; year &lt;span class="op"&gt;-&lt;/span&gt; year.&lt;span class="bu"&gt;min&lt;/span&gt;()&lt;/span&gt;
&lt;span id="cb91-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb91-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;t_ &lt;span class="op"&gt;=&lt;/span&gt; shared(t)&lt;/span&gt;
&lt;span id="cb91-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb91-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_year &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="bu"&gt;int&lt;/span&gt;(t.&lt;span class="bu"&gt;max&lt;/span&gt;() &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The prior on &lt;span class="math inline"&gt;\(\beta_j\)&lt;/span&gt; stays the same as in the mean model, but we add a Gaussian random walk term, &lt;span class="math inline"&gt;\(\beta_{0, t}\)&lt;/span&gt; to the intercept, &lt;span class="math inline"&gt;\(\beta_0\)&lt;/span&gt;. We use the priors&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \mu_{\beta_{0, pieces}}, \gamma_{\beta_{0, pieces}}
        &amp;amp; \sim N(0, 2.5^2) \\
    \sigma_{\beta_{0, pieces}}
        &amp;amp; \sim \textrm{HalfNormal}(2.5^2) \\
    \Delta_{\beta_{0, i}}
        &amp;amp; \sim N(0, 0.25^2) \\
    \beta_{0, t}
        &amp;amp; \sim \sum_{i = 1}^t \Delta_{\beta_{0, i}} \\
    \beta_{0, j, t}
        &amp;amp; \sim N\left(\mu_{\beta_0} + \beta_{0, t} + \gamma_{\beta, 0} \cdot \bar{\tilde{x}}_j, \sigma_{\beta_0}^2\right).
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We see that the time-varying factor &lt;span class="math inline"&gt;\(\beta_{0, t}\)&lt;/span&gt; is constant across themes in order to reduce the computational burden when sampling from this model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb92"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb92-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; time_model:&lt;/span&gt;
&lt;span id="cb92-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    Δ_β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_t&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"Δ_β0_t"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;0.25&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;n_year)&lt;/span&gt;
&lt;span id="cb92-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_t&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;span class="st"&gt;"β0_t"&lt;/span&gt;, Δ_β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_t&lt;/span&gt;.cumsum())&lt;/span&gt;
&lt;span id="cb92-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb92-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_theme&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal_with_mean(&lt;/span&gt;
&lt;span id="cb92-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;"β0_theme"&lt;/span&gt;, at.constant(theme_mean_std_log_pieces),&lt;/span&gt;
&lt;span id="cb92-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        n_theme&lt;/span&gt;
&lt;span id="cb92-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb92-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_i&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_t&lt;/span&gt;[t_] &lt;span class="op"&gt;+&lt;/span&gt; β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_theme&lt;/span&gt;[theme_id_]&lt;/span&gt;
&lt;span id="cb92-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb92-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_pieces &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal_with_mean(&lt;/span&gt;
&lt;span id="cb92-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;"β_pieces"&lt;/span&gt;, at.constant(theme_mean_std_log_pieces),&lt;/span&gt;
&lt;span id="cb92-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        n_theme&lt;/span&gt;
&lt;span id="cb92-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb92-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb92-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"σ"&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb92-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; β&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_i&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; β_pieces[theme_id_] &lt;span class="op"&gt;*&lt;/span&gt; std_log_pieces_ &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="fl"&gt;0.5&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; σ&lt;span class="op"&gt;**&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb92-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb92-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb92-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"obs"&lt;/span&gt;, μ, σ, observed&lt;span class="op"&gt;=&lt;/span&gt;log_rrp2021)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now sample from this model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb93"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb93-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb93-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; time_model:&lt;/span&gt;
&lt;span id="cb93-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb93-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    time_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [Δ_β0_t, γ_β0_theme, μ_β0_theme, Δ_β0_theme, σ_β0_theme, γ_β_pieces, μ_β_pieces, Δ_β_pieces, σ_β_pieces, σ]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="6000" class max="6000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [6000/6000 17:36&amp;lt;00:00 Sampling 3 chains, 0 divergences]&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Sampling 3 chains for 1_000 tune and 1_000 draw iterations (3_000 + 3_000 draws total) took 1056 seconds.
The number of effective samples is smaller than 25% for some parameters.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once again the sampling diagnostics show no cause for concern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb96"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb96-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb96-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_diagnostic_plots(time_trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_133_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that the time-varying model performs noticeably better than the other models in terms of PSIS-LOO score.&lt;/p&gt;
&lt;div class="sourceCode" id="cb97"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb97-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb97-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;traces[&lt;span class="st"&gt;"Partially pooled with mean and time"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; time_trace&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb98"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb98-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb98-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;comp_df &lt;span class="op"&gt;=&lt;/span&gt; az.compare(traces)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb99"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb99-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb99-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;comp_df.loc[:, :&lt;span class="st"&gt;"weight"&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
rank
&lt;/th&gt;
&lt;th&gt;
loo
&lt;/th&gt;
&lt;th&gt;
p_loo
&lt;/th&gt;
&lt;th&gt;
d_loo
&lt;/th&gt;
&lt;th&gt;
weight
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
Partially pooled with mean and time
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
-2058.373203
&lt;/td&gt;
&lt;td&gt;
245.239325
&lt;/td&gt;
&lt;td&gt;
0.000000
&lt;/td&gt;
&lt;td&gt;
9.205189e-01
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Partially pooled
&lt;/th&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
-2315.578245
&lt;/td&gt;
&lt;td&gt;
190.594364
&lt;/td&gt;
&lt;td&gt;
257.205042
&lt;/td&gt;
&lt;td&gt;
4.565283e-02
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Partially pooled with mean
&lt;/th&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
-2316.840059
&lt;/td&gt;
&lt;td&gt;
187.512592
&lt;/td&gt;
&lt;td&gt;
258.466855
&lt;/td&gt;
&lt;td&gt;
1.857221e-12
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Unpooled
&lt;/th&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
-5133.311893
&lt;/td&gt;
&lt;td&gt;
4.871287
&lt;/td&gt;
&lt;td&gt;
3074.938690
&lt;/td&gt;
&lt;td&gt;
3.382830e-02
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb100"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb100-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb100-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;12&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb100-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb100-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb100-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb100-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_compare(comp_df, plot_ic_diff&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_138_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The residuals for this model are similar to those of the previous one when plotted against the number of pieces in the set.&lt;/p&gt;
&lt;div class="sourceCode" id="cb101"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb101-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb101-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; time_model:&lt;/span&gt;
&lt;span id="cb101-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb101-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    pp_time_data &lt;span class="op"&gt;=&lt;/span&gt; pm.sample_posterior_predictive(time_trace)&lt;/span&gt;
&lt;span id="cb101-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb101-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb101-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb101-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df[&lt;span class="st"&gt;"time_resid"&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (log_rrp2021 &lt;span class="op"&gt;-&lt;/span&gt; pp_time_data[&lt;span class="st"&gt;"obs"&lt;/span&gt;]).mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="3000" class max="3000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [3000/3000 00:02&amp;lt;00:00]&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb102"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb102-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb102-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;14&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb102-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb102-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"mean_resid"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df,&lt;/span&gt;
&lt;span id="cb102-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.1&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb102-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb102-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;].set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb102-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;].set_xlabel(&lt;span class="st"&gt;"Pieces"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb102-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb102-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;].set_ylabel(&lt;span class="st"&gt;"Log RRP residual (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb102-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb102-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;].set_title(&lt;span class="st"&gt;"Partially pooled mean model"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb102-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb102-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.scatterplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pieces"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"time_resid"&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df,&lt;/span&gt;
&lt;span id="cb102-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.1&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb102-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb102-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb102-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_xlabel(&lt;span class="st"&gt;"Pieces"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb102-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb102-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_ylabel(&lt;span class="st"&gt;"Log RRP residual (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb102-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb102-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;].set_title(&lt;span class="st"&gt;"Partially pooled mean model with time"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb102-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb102-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb102-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_141_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The following plot shows that this model has significantly reduced the amount of time-dependence in the residuals.&lt;/p&gt;
&lt;div class="sourceCode" id="cb103"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb103-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; (df.groupby(level&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Year released"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb103-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        [&lt;span class="st"&gt;"time_resid"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb103-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .mean()&lt;/span&gt;
&lt;span id="cb103-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .plot(c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Year average"&lt;/span&gt;))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb103-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb103-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;strip_ax &lt;span class="op"&gt;=&lt;/span&gt; ax.twiny()&lt;/span&gt;
&lt;span id="cb103-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.stripplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Year released"&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"time_resid"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb103-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              data&lt;span class="op"&gt;=&lt;/span&gt;df.reset_index(),&lt;/span&gt;
&lt;span id="cb103-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              jitter&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;1.5&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb103-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.1&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb103-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              ax&lt;span class="op"&gt;=&lt;/span&gt;strip_ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb103-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb103-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;strip_ax.set_axis_off()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb103-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb103-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylim(&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, &lt;span class="dv"&gt;2&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb103-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Log RRP residual (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb103-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb103-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb103-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'upper left'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_143_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Again, there is more variation in the varying intercepts (&lt;span class="math inline"&gt;\(\beta_{0, j}\)&lt;/span&gt;) than the varying slopes (&lt;span class="math inline"&gt;\(\beta_j\)&lt;/span&gt;), since &lt;span class="math inline"&gt;\(\sigma_{\beta_0}\)&lt;/span&gt; has a larger posterior expected value than &lt;span class="math inline"&gt;\(\sigma_{\beta}\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb104"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb104-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb104-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_posterior(time_trace,&lt;/span&gt;
&lt;span id="cb104-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb104-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                  var_names&lt;span class="op"&gt;=&lt;/span&gt;[&lt;/span&gt;
&lt;span id="cb104-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb104-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      &lt;span class="st"&gt;"μ_β0_theme"&lt;/span&gt;, &lt;span class="st"&gt;"μ_β_pieces"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb104-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb104-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      &lt;span class="st"&gt;"σ_β0_theme"&lt;/span&gt;, &lt;span class="st"&gt;"σ_β_pieces"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb104-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb104-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                  ],&lt;/span&gt;
&lt;span id="cb104-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb104-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                  grid&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;2&lt;/span&gt;, &lt;span class="dv"&gt;2&lt;/span&gt;))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_145_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We now revisit the question of whether or not Darth Vader’s Meditation Chamber is fairly priced. In the previous post in this series, we compared the price per piece of this set to all sets, all Star Wars sets, and all sets currently in my collection. We found that it was in or near the first quartile of price per piece among all sets and Star Wars sets, and near the median priece per piece in my collection. With this model in hand, we can ask where the adjusted recommended retail price falls in the predicted distribution of posterior predicted prices for a Star Wars set with 663 pieces.&lt;/p&gt;
&lt;div class="sourceCode" id="cb105"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb105-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb105-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;VADER_MEDITATION &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="st"&gt;"75296-1"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb105-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb105-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb105-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb105-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;vader_info &lt;span class="op"&gt;=&lt;/span&gt; df.xs(VADER_MEDITATION, level&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Set number"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb105-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb105-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;vader_iloc &lt;span class="op"&gt;=&lt;/span&gt; (df.index&lt;/span&gt;
&lt;span id="cb105-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb105-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .get_level_values(&lt;span class="st"&gt;"Set number"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb105-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb105-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .isin([VADER_MEDITATION])&lt;/span&gt;
&lt;span id="cb105-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb105-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .argmax())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb106"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb106-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb106-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(vader_info[&lt;span class="st"&gt;"RRP2021"&lt;/span&gt;].values[&lt;span class="dv"&gt;0&lt;/span&gt;] &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb106-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb106-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="op"&gt;&amp;gt;=&lt;/span&gt; np.exp(pp_trace_data[&lt;span class="st"&gt;"obs"&lt;/span&gt;][:, vader_iloc])).mean()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;0.2816666666666667&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The set falls in towards the bottom of the second quartile of predicted prices for such a set, which is consistent with the empirical price per piece analysis of the previous post. This model can also answer some counterfactual questions about my collection. We see that my sets are highly concentrated in the Star Wars theme, with a smattering of other themes represented as well.&lt;/p&gt;
&lt;div class="sourceCode" id="cb108"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb108-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb108-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(df[df[&lt;span class="st"&gt;"austin"&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="va"&gt;True&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb108-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb108-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   [&lt;span class="st"&gt;"Theme"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb108-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb108-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   .value_counts(ascending&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb108-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb108-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   .plot.barh())&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_150_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;This preponderance of Star Wars sets is even stronger than it initially appears because all but one of my BrickHeadz sets are Star Wars characters. The single exception are the adorable German Shepherds (&lt;a href="https://www.lego.com/en-us/product/german-shepherd-40440"&gt;40440&lt;/a&gt;).&lt;/p&gt;
&lt;center&gt;
&lt;img src="https://www.lego.com/cdn/cs/set/assets/blt5e9ef14c0a074aa4/40440.jpg" width="500"&gt;
&lt;/center&gt;
&lt;p&gt;In particular, we can compare the actual cost of my collection to the predicted expected cost of my collection conditioned on the piece count and theme of the sets.&lt;/p&gt;
&lt;div class="sourceCode" id="cb109"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb109-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb109-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;coll_value &lt;span class="op"&gt;=&lt;/span&gt; (df[df[&lt;span class="st"&gt;"austin"&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="va"&gt;True&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb109-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb109-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                [&lt;span class="st"&gt;"RRP2021"&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb109-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb109-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .&lt;span class="bu"&gt;sum&lt;/span&gt;())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb110"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb110-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb110-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;coll_value&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;3206.3933684401236&lt;/code&gt;&lt;/pre&gt;
&lt;div class="sourceCode" id="cb112"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb112-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb112-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(np.exp(pp_trace_data[&lt;span class="st"&gt;"obs"&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb112-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb112-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     [:, df[&lt;span class="st"&gt;"austin"&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="va"&gt;True&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb112-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb112-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     .mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb112-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb112-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     .&lt;span class="bu"&gt;sum&lt;/span&gt;())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;3826.537853977332&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So my collection cost about 20% less than expected conditioned on piece count and theme. (This figure actually understates my frugality as I have received several sets as gifts, notably the massive Super Star Destroyer (&lt;a href="https://brickset.com/sets/10221-1/Super-Star-Destroyer"&gt;10221&lt;/a&gt;).) We can easily check where my collection’s actual value falls in the posterior predictive distribution of its possible values.&lt;/p&gt;
&lt;div class="sourceCode" id="cb114"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb114-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb114-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_coll_value &lt;span class="op"&gt;=&lt;/span&gt; (np.exp(pp_trace_data[&lt;span class="st"&gt;"obs"&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb114-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb114-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   [:, df[&lt;span class="st"&gt;"austin"&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="va"&gt;True&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb114-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb114-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   .&lt;span class="bu"&gt;sum&lt;/span&gt;(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb115"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb115-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb115-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax, &lt;span class="op"&gt;=&lt;/span&gt; (sns.displot(pp_coll_value, kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'kde'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb115-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb115-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   height&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;6&lt;/span&gt;, aspect&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;8&lt;/span&gt; &lt;span class="op"&gt;/&lt;/span&gt; &lt;span class="dv"&gt;6&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb115-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb115-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Posterior predictive distribution"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb115-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb115-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          .axes.flatten())&lt;/span&gt;
&lt;span id="cb115-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb115-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb115-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb115-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.axvline(coll_value, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, ls&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'--'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb115-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb115-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Actual value"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb115-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb115-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb115-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb115-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.xaxis.set_major_formatter(dollar_formatter)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb115-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb115-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Collection value (2021 $)"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb115-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb115-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb115-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb115-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yticks([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb115-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb115-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb115-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb115-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'upper right'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_158_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb116"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb116-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb116-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(coll_value &lt;span class="op"&gt;&amp;gt;&lt;/span&gt; pp_coll_value).mean()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;0.007&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;My collection’s actual value is in the first percentile of the posterior predictive distribution of possible collection values; according to this model, I really am quite cheap!&lt;/p&gt;
&lt;p&gt;It is worth noting that in this post we have modeled log price directly, not price per piece as in the last model. Those familiar with offset terms in offsets in generalizedl linear models will notice that the model we have specified can be equivalent to an model of (log) price per piece if we fix &lt;span class="math inline"&gt;\(\beta_j = 1\)&lt;/span&gt;, since &lt;span class="math inline"&gt;\(\log\left(\frac{x}{y}\right) = \log x - \log y.\)&lt;/span&gt; The following plot shows how far outside the high density area of the posterior distribution of &lt;span class="math inline"&gt;\(\mu_{\beta_0}\)&lt;/span&gt; the value one is.&lt;/p&gt;
&lt;div class="sourceCode" id="cb118"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb118-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb118-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_posterior(time_trace, var_names&lt;span class="op"&gt;=&lt;/span&gt;[&lt;span class="st"&gt;"μ_β0_theme"&lt;/span&gt;], ref_val&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;1.&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/lego_pymc3_files/lego_pymc3_161_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Due to this fact, we prefer to model (log) price directly over using an offset model that includes (log) piece count on both sides of the equal sign.&lt;/p&gt;
&lt;p&gt;Future posts will explore further inferences from this model and develop extended models using other attributes of each set available via Brickset.&lt;/p&gt;
&lt;p&gt;This post is available as a Jupyter notebook &lt;a href="https://nbviewer.jupyter.org/gist/AustinRochford/f75d687d383b0a884c7782af1419bcf9"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb119"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb119-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb119-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;load_ext watermark&lt;/span&gt;
&lt;span id="cb119-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#cb119-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;watermark &lt;span class="op"&gt;-&lt;/span&gt;n &lt;span class="op"&gt;-&lt;/span&gt;u &lt;span class="op"&gt;-&lt;/span&gt;v &lt;span class="op"&gt;-&lt;/span&gt;iv&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Last updated: Thu Jun 10 2021

Python implementation: CPython
Python version       : 3.8.8
IPython version      : 7.22.0

pandas    : 1.2.3
aesara    : 2.0.10
pymc3     : 4.0
scipy     : 1.6.2
seaborn   : 0.11.1
matplotlib: 3.4.1
arviz     : 0.11.2
numpy     : 1.20.2&lt;/code&gt;&lt;/pre&gt;
&lt;section class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn1" role="doc-endnote"&gt;&lt;p&gt;Vehtari, A., Gelman, A., &amp;amp; Gabry, J. (2017). &lt;a href="https://arxiv.org/abs/1507.04544"&gt;Practical Bayesian model evaluation using leave-one-out cross-validation and WAIC.&lt;/a&gt; (PSIS-LOO) to compare them.) &lt;em&gt;Statistics and computing&lt;/em&gt;, 27(5), 1413-1432.&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#fnref1" class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn2" role="doc-endnote"&gt;&lt;p&gt;Bafumi, J., &amp;amp; Gelman, A. E. (2006). &lt;a href="http://www.stat.columbia.edu/~gelman/research/unpublished/Bafumi_Gelman_Midwest06.pdf"&gt;Fitting multilevel models when predictors and group effects correlate.&lt;/a&gt;&lt;a href="https://austinrochford.com/posts/2021-06-10-lego-pymc3.html#fnref2" class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description><category>Bayesian Statistics</category><category>Lego</category><category>PyMC3</category><category>Python</category><guid>https://austinrochford.com/posts/2021-06-10-lego-pymc3.html</guid><pubDate>Thu, 10 Jun 2021 04:00:00 GMT</pubDate></item><item><title>The Hierarchical Regularized Horseshoe Prior in PyMC3</title><link>https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html</link><dc:creator>Austin Rochford</dc:creator><description>&lt;p&gt;For some time I have been interested in better understanding the &lt;a href="http://proceedings.mlr.press/v5/carvalho09a"&gt;horseshoe prior&lt;/a&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; by implementing it in PyMC3. The horsehoe prior is a continuous alternative to the &lt;a href="https://en.wikipedia.org/wiki/Spike-and-slab_regression"&gt;spike-and-slab&lt;/a&gt; prior for sparse Bayesian estimation. The continuity of the horeshoe prior allows for simpler estimation using general purpose Bayesian computation packages such as &lt;a href="https://docs.pymc.io/"&gt;&lt;code&gt;pymc3&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://mc-stan.org/"&gt;Stan&lt;/a&gt;. &lt;a href="https://projecteuclid.org/journals/electronic-journal-of-statistics/volume-11/issue-2/Sparsity-information-and-regularization-in-the-horseshoe-and-other-shrinkage/10.1214/17-EJS1337SI.full"&gt;Piironen and Vehtari&lt;/a&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; have proposed a hierarchical regularized horseshoe prior that has advantages over the original horseshoe prior when it comes to specifying the hyperprior distributions on the regularization parameters. In the appendix of their paper, Piironen and Vehtari give a sample implementation in Stan. This post gives a corresponding implementation in &lt;code&gt;pymc3&lt;/code&gt; and tests it on simulated data.&lt;/p&gt;
&lt;center&gt;
&lt;img src="https://upload.wikimedia.org/wikipedia/commons/f/f1/Horseshoe.jpg" width="300"&gt;
&lt;/center&gt;
&lt;p&gt;First we import the necessary Python packages and do some light housekeeping.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb1-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;matplotlib inline&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb2-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; warnings &lt;span class="im"&gt;import&lt;/span&gt; filterwarnings&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb3-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; aesara &lt;span class="im"&gt;import&lt;/span&gt; tensor &lt;span class="im"&gt;as&lt;/span&gt; at&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; arviz &lt;span class="im"&gt;as&lt;/span&gt; az&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib &lt;span class="im"&gt;import&lt;/span&gt; pyplot &lt;span class="im"&gt;as&lt;/span&gt; plt&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; numpy &lt;span class="im"&gt;as&lt;/span&gt; np&lt;/span&gt;
&lt;span id="cb3-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb3-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pymc3 &lt;span class="im"&gt;as&lt;/span&gt; pm&lt;/span&gt;
&lt;span id="cb3-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb3-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; seaborn &lt;span class="im"&gt;as&lt;/span&gt; sns&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb4-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;filterwarnings(&lt;span class="st"&gt;'ignore'&lt;/span&gt;, category&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="pp"&gt;UserWarning&lt;/span&gt;, module&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'aesara'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb4-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;filterwarnings(&lt;span class="st"&gt;'ignore'&lt;/span&gt;, category&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="pp"&gt;UserWarning&lt;/span&gt;, module&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'arviz'&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb5-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.&lt;span class="bu"&gt;set&lt;/span&gt;(color_codes&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="simulated-data"&gt;Simulated Data&lt;/h2&gt;
&lt;p&gt;Since the horseshoe is designed for sparse estimation of regression parameters, we simulate data from a model with &lt;span class="math inline"&gt;\(D = 50\)&lt;/span&gt; variables, &lt;span class="math inline"&gt;\(D_0 = 5\)&lt;/span&gt; of which are nonzero.&lt;/p&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb6-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;D &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;50&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb6-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;D0 &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;5&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb7-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb7-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SEED &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;123456789&lt;/span&gt; &lt;span class="co"&gt;# for reproducibility&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb7-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb7-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb7-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;rng &lt;span class="op"&gt;=&lt;/span&gt; np.random.default_rng(SEED)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb8-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;INTERCEPT &lt;span class="op"&gt;=&lt;/span&gt; rng.uniform(&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;3&lt;/span&gt;, &lt;span class="dv"&gt;3&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb8-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb8-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb8-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;COEF &lt;span class="op"&gt;=&lt;/span&gt; np.zeros(D)&lt;/span&gt;
&lt;span id="cb8-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb8-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;COEF[:D0] &lt;span class="op"&gt;=&lt;/span&gt; rng.choice([&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;1&lt;/span&gt;], size&lt;span class="op"&gt;=&lt;/span&gt;D0) &lt;span class="op"&gt;*&lt;/span&gt; rng.normal(&lt;span class="dv"&gt;5&lt;/span&gt;, &lt;span class="dv"&gt;1&lt;/span&gt;, size&lt;span class="op"&gt;=&lt;/span&gt;D0)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we draw &lt;span class="math inline"&gt;\(N = 100\)&lt;/span&gt; random observations with &lt;span class="math inline"&gt;\(x_i \sim N(0, 1).\)&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb9-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;N &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;100&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb10"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb10-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb10-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;X &lt;span class="op"&gt;=&lt;/span&gt; rng.normal(size&lt;span class="op"&gt;=&lt;/span&gt;(N, D))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now simulate responses from this regression model with &lt;span class="math inline"&gt;\(N(0, 1)\)&lt;/span&gt;-distributed noise.&lt;/p&gt;
&lt;div class="sourceCode" id="cb11"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb11-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb11-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SIGMA &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="fl"&gt;1.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb12"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb12-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb12-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;y &lt;span class="op"&gt;=&lt;/span&gt; INTERCEPT &lt;span class="op"&gt;+&lt;/span&gt; X.dot(COEF) &lt;span class="op"&gt;+&lt;/span&gt; rng.normal(&lt;span class="dv"&gt;0&lt;/span&gt;, SIGMA, size&lt;span class="op"&gt;=&lt;/span&gt;N)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We see that there is a linear relationship between &lt;span class="math inline"&gt;\(y\)&lt;/span&gt; and the first &lt;span class="math inline"&gt;\(D_0\)&lt;/span&gt; variables and no relationship between &lt;span class="math inline"&gt;\(y\)&lt;/span&gt; and a random sample from the subsequent &lt;span class="math inline"&gt;\(D - D0\)&lt;/span&gt; variables.&lt;/p&gt;
&lt;div class="sourceCode" id="cb13"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb13-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(nrows&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, ncols&lt;span class="op"&gt;=&lt;/span&gt;D0,&lt;/span&gt;
&lt;span id="cb13-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb13-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;16&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb13-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;for&lt;/span&gt; i, (ax, coef) &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;enumerate&lt;/span&gt;(&lt;span class="bu"&gt;zip&lt;/span&gt;(axes[&lt;span class="dv"&gt;0&lt;/span&gt;], COEF)):&lt;/span&gt;
&lt;span id="cb13-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.scatter(X[:, i], y, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.75&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb13-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_xlabel(&lt;span class="ss"&gt;f"$x_&lt;/span&gt;&lt;span class="ch"&gt;{{&lt;/span&gt;&lt;span class="ss"&gt; &lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;i&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt; &lt;/span&gt;&lt;span class="ch"&gt;}}&lt;/span&gt;&lt;span class="ss"&gt;$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_title(&lt;span class="ss"&gt;f"$&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="ss"&gt;beta_&lt;/span&gt;&lt;span class="ch"&gt;{{&lt;/span&gt;&lt;span class="ss"&gt; &lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;i&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt; &lt;/span&gt;&lt;span class="ch"&gt;}}&lt;/span&gt;&lt;span class="ss"&gt; &lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="ss"&gt;approx &lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;coef&lt;span class="sc"&gt;:.2f}&lt;/span&gt;&lt;span class="ss"&gt;$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;zero_coef_ix &lt;span class="op"&gt;=&lt;/span&gt; rng.choice(&lt;span class="bu"&gt;range&lt;/span&gt;(D0, D), replace&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, size&lt;span class="op"&gt;=&lt;/span&gt;D0)&lt;/span&gt;
&lt;span id="cb13-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;zero_coef_ix.sort()&lt;/span&gt;
&lt;span id="cb13-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;for&lt;/span&gt; ax, i &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;zip&lt;/span&gt;(axes[&lt;span class="dv"&gt;1&lt;/span&gt;], zero_coef_ix):&lt;/span&gt;
&lt;span id="cb13-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.scatter(X[:, i], y, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.75&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb13-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_xlabel(&lt;span class="ss"&gt;f"$x_&lt;/span&gt;&lt;span class="ch"&gt;{{&lt;/span&gt;&lt;span class="ss"&gt; &lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;i&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt; &lt;/span&gt;&lt;span class="ch"&gt;}}&lt;/span&gt;&lt;span class="ss"&gt;$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_title(&lt;span class="ss"&gt;f"$&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="ss"&gt;beta_&lt;/span&gt;&lt;span class="ch"&gt;{{&lt;/span&gt;&lt;span class="ss"&gt; &lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;i&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt; &lt;/span&gt;&lt;span class="ch"&gt;}}&lt;/span&gt;&lt;span class="ss"&gt; = 0$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb13-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;0&lt;/span&gt;, &lt;span class="dv"&gt;0&lt;/span&gt;].set_ylabel(&lt;span class="st"&gt;"$y$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;axes[&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;0&lt;/span&gt;].set_ylabel(&lt;span class="st"&gt;"$y$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb13-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/horseshoe_files/horseshoe_18_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;h2 id="the-regularized-horseshoe"&gt;The Regularized Horseshoe&lt;/h2&gt;
&lt;p&gt;First we place a reasonable half-normal prior on the error variance &lt;span class="math inline"&gt;\(\sigma^2\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb14"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb14-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb14-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb14-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb14-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"σ"&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The hierarchical regularized horseshoe uses two levels of regularization, global and local. There is a global parameter, &lt;span class="math inline"&gt;\(\tau\)&lt;/span&gt;, that will shrink all parameters towards zero (similarly to ridge regression) along with local parameters &lt;span class="math inline"&gt;\(\lambda_i\)&lt;/span&gt; for each coefficient. A long-tailed prior on the &lt;span class="math inline"&gt;\(\lambda_i\)&lt;/span&gt;s allows some of them to be nonzero, with the scale of &lt;span class="math inline"&gt;\(\tau\)&lt;/span&gt; setting the prior expected number of nonzero parameters.&lt;/p&gt;
&lt;p&gt;An important calculation (§3.3 of Piironen and Vehtari) shows that if we believe there are actually &lt;span class="math inline"&gt;\(D_*\)&lt;/span&gt; nonzero coefficients, the prior on the global shrinkage parameter &lt;span class="math inline"&gt;\(\tau\)&lt;/span&gt; should be&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\tau \sim \textrm{Half-StudentT}_{2} \left(\frac{D_*}{D - D_*} \cdot \frac{\sigma}{\sqrt{N}}\right).
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Since we know the generating process for this data, we set &lt;span class="math inline"&gt;\(D_* = D_0\)&lt;/span&gt;, although Piironen and Vehtari show that this guess only needs to be order-of-magnitude correct in practice.&lt;/p&gt;
&lt;div class="sourceCode" id="cb15"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb15-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb15-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb15-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb15-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    τ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfStudentT(&lt;span class="st"&gt;"τ"&lt;/span&gt;, &lt;span class="dv"&gt;2&lt;/span&gt;, D0 &lt;span class="op"&gt;/&lt;/span&gt; (D &lt;span class="op"&gt;-&lt;/span&gt; D0) &lt;span class="op"&gt;*&lt;/span&gt; σ &lt;span class="op"&gt;/&lt;/span&gt; np.sqrt(N))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The regularized horseshoe uses the prior&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[\beta_i \sim N\left(0, \tau^2 \cdot \tilde{\lambda}_i^2\right)\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;for the coefficients, where&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[\tilde{\lambda}_i^2 = \frac{c^2 \lambda_i^2}{c^2 + \tau^2 \lambda_i^2}.\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Given these definitions, it only remains to specify priors on &lt;span class="math inline"&gt;\(\lambda_i\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(c\)&lt;/span&gt;. As indicated above, we use a long-tailed prior &lt;span class="math inline"&gt;\(\lambda_i \sim \textrm{Half-StudentT}_5(1)\)&lt;/span&gt; on the local parameters&lt;/p&gt;
&lt;div class="sourceCode" id="cb16"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb16-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb16-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb16-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb16-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    λ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfStudentT(&lt;span class="st"&gt;"λ"&lt;/span&gt;, &lt;span class="dv"&gt;5&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;D)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Following §2.3 of Piironen and Vehtari, we place an inverse gamma prior on &lt;span class="math inline"&gt;\(c^2\)&lt;/span&gt;, &lt;span class="math inline"&gt;\(c^2 \sim \textrm{InverseGamma}(1, 1).\)&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb17"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb17-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb17-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb17-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb17-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    c2 &lt;span class="op"&gt;=&lt;/span&gt; pm.InverseGamma(&lt;span class="st"&gt;"c2"&lt;/span&gt;, &lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With these priors in place, we define &lt;span class="math inline"&gt;\(\tilde{\lambda}_i\)&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb18"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb18-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb18-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb18-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb18-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    λ_ &lt;span class="op"&gt;=&lt;/span&gt; λ &lt;span class="op"&gt;*&lt;/span&gt; at.sqrt(c2 &lt;span class="op"&gt;/&lt;/span&gt; (c2 &lt;span class="op"&gt;+&lt;/span&gt; τ&lt;span class="op"&gt;**&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; λ&lt;span class="op"&gt;**&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To implement &lt;span class="math inline"&gt;\(\beta_i \sim N\left(0, \tau^2 \cdot \tilde{\lambda}_i^2\right)\)&lt;/span&gt; more efficiently, we use the parameterization&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    z_i
        &amp;amp; \sim N(0, 1), \\
     \beta_i
         &amp;amp; = z_i \cdot \tau \cdot \tilde{\lambda_i}.
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb19"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb19-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb19-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb19-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb19-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    z &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"z"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;1.&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;D)&lt;/span&gt;
&lt;span id="cb19-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb19-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;span class="st"&gt;"β"&lt;/span&gt;, z &lt;span class="op"&gt;*&lt;/span&gt; τ &lt;span class="op"&gt;*&lt;/span&gt; λ_)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that it is important to constrain two of the three factors &lt;span class="math inline"&gt;\(z_i\)&lt;/span&gt;, &lt;span class="math inline"&gt;\(\tau\)&lt;/span&gt;, and &lt;span class="math inline"&gt;\(\tilde{\lambda}_i\)&lt;/span&gt; to be positive, otherwise this model will not be fully &lt;a href="https://en.wikipedia.org/wiki/Identifiability"&gt;identified&lt;/a&gt;. Unlike in Piironen and Vehtari, we enforce identifiability by using half-Student T priors on &lt;span class="math inline"&gt;\(\tau\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(\lambda_i\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Using a relatively flat &lt;span class="math inline"&gt;\(N(0, 10^2)\)&lt;/span&gt; prior for the intercept, the likelihood of the observed data is&lt;/p&gt;
&lt;div class="sourceCode" id="cb20"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb20-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb20-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb20-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb20-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"β0"&lt;/span&gt;, &lt;span class="dv"&gt;0&lt;/span&gt;, &lt;span class="fl"&gt;10.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb20-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb20-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb20-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb20-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"obs"&lt;/span&gt;, β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; at.dot(X, β), σ, observed&lt;span class="op"&gt;=&lt;/span&gt;y)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We proceed to sample from this model&lt;/p&gt;
&lt;div class="sourceCode" id="cb21"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb21-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb21-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;CHAINS &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb21-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb21-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb21-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SAMPLE_KWARGS &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb21-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb21-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'cores'&lt;/span&gt;: CHAINS,&lt;/span&gt;
&lt;span id="cb21-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb21-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'target_accept'&lt;/span&gt;: &lt;span class="fl"&gt;0.99&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb21-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb21-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'max_treedepth'&lt;/span&gt;: &lt;span class="dv"&gt;15&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb21-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb21-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'random_seed'&lt;/span&gt;: [SEED &lt;span class="op"&gt;+&lt;/span&gt; i &lt;span class="cf"&gt;for&lt;/span&gt; i &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;range&lt;/span&gt;(CHAINS)],&lt;/span&gt;
&lt;span id="cb21-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb21-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'return_inferencedata'&lt;/span&gt;: &lt;span class="va"&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb21-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb21-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb22"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb22-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb22-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb22-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb22-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [β0, z, c2, λ, τ, σ]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="6000" class max="6000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [6000/6000 05:20&amp;lt;00:00 Sampling 3 chains, 0 divergences]&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Sampling 3 chains for 1_000 tune and 1_000 draw iterations (3_000 + 3_000 draws total) took 322 seconds.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The energy plot, BFMIs, and &lt;span class="math inline"&gt;\(\hat{R}\)&lt;/span&gt; statistics for these samples show no cause for concern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb25"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb25-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb25-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_energy(trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/horseshoe_files/horseshoe_38_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb26"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb26-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb26-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.rhat(trace).&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;svg style="position: absolute; width: 0; height: 0; overflow: hidden"&gt;
&lt;defs&gt; &lt;symbol id="icon-database" viewbox="0 0 32 32"&gt; &lt;path d="M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z"&gt;&lt;/path&gt; &lt;path d="M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;path d="M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;symbol id="icon-file-text2" viewbox="0 0 32 32"&gt; &lt;path d="M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z"&gt;&lt;/path&gt; &lt;path d="M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;/defs&gt;
&lt;/svg&gt;
&lt;style&gt;/* CSS stylesheet for displaying xarray objects in jupyterlab.
 *
 */

:root {
  --xr-font-color0: var(--jp-content-font-color0, rgba(0, 0, 0, 1));
  --xr-font-color2: var(--jp-content-font-color2, rgba(0, 0, 0, 0.54));
  --xr-font-color3: var(--jp-content-font-color3, rgba(0, 0, 0, 0.38));
  --xr-border-color: var(--jp-border-color2, #e0e0e0);
  --xr-disabled-color: var(--jp-layout-color3, #bdbdbd);
  --xr-background-color: var(--jp-layout-color0, white);
  --xr-background-color-row-even: var(--jp-layout-color1, white);
  --xr-background-color-row-odd: var(--jp-layout-color2, #eeeeee);
}

html[theme=dark],
body.vscode-dark {
  --xr-font-color0: rgba(255, 255, 255, 1);
  --xr-font-color2: rgba(255, 255, 255, 0.54);
  --xr-font-color3: rgba(255, 255, 255, 0.38);
  --xr-border-color: #1F1F1F;
  --xr-disabled-color: #515151;
  --xr-background-color: #111111;
  --xr-background-color-row-even: #111111;
  --xr-background-color-row-odd: #313131;
}

.xr-wrap {
  display: block;
  min-width: 300px;
  max-width: 700px;
}

.xr-text-repr-fallback {
  /* fallback to plain text repr when CSS is not injected (untrusted notebook) */
  display: none;
}

.xr-header {
  padding-top: 6px;
  padding-bottom: 6px;
  margin-bottom: 4px;
  border-bottom: solid 1px var(--xr-border-color);
}

.xr-header &gt; div,
.xr-header &gt; ul {
  display: inline;
  margin-top: 0;
  margin-bottom: 0;
}

.xr-obj-type,
.xr-array-name {
  margin-left: 2px;
  margin-right: 10px;
}

.xr-obj-type {
  color: var(--xr-font-color2);
}

.xr-sections {
  padding-left: 0 !important;
  display: grid;
  grid-template-columns: 150px auto auto 1fr 20px 20px;
}

.xr-section-item {
  display: contents;
}

.xr-section-item input {
  display: none;
}

.xr-section-item input + label {
  color: var(--xr-disabled-color);
}

.xr-section-item input:enabled + label {
  cursor: pointer;
  color: var(--xr-font-color2);
}

.xr-section-item input:enabled + label:hover {
  color: var(--xr-font-color0);
}

.xr-section-summary {
  grid-column: 1;
  color: var(--xr-font-color2);
  font-weight: 500;
}

.xr-section-summary &gt; span {
  display: inline-block;
  padding-left: 0.5em;
}

.xr-section-summary-in:disabled + label {
  color: var(--xr-font-color2);
}

.xr-section-summary-in + label:before {
  display: inline-block;
  content: '►';
  font-size: 11px;
  width: 15px;
  text-align: center;
}

.xr-section-summary-in:disabled + label:before {
  color: var(--xr-disabled-color);
}

.xr-section-summary-in:checked + label:before {
  content: '▼';
}

.xr-section-summary-in:checked + label &gt; span {
  display: none;
}

.xr-section-summary,
.xr-section-inline-details {
  padding-top: 4px;
  padding-bottom: 4px;
}

.xr-section-inline-details {
  grid-column: 2 / -1;
}

.xr-section-details {
  display: none;
  grid-column: 1 / -1;
  margin-bottom: 5px;
}

.xr-section-summary-in:checked ~ .xr-section-details {
  display: contents;
}

.xr-array-wrap {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 20px auto;
}

.xr-array-wrap &gt; label {
  grid-column: 1;
  vertical-align: top;
}

.xr-preview {
  color: var(--xr-font-color3);
}

.xr-array-preview,
.xr-array-data {
  padding: 0 5px !important;
  grid-column: 2;
}

.xr-array-data,
.xr-array-in:checked ~ .xr-array-preview {
  display: none;
}

.xr-array-in:checked ~ .xr-array-data,
.xr-array-preview {
  display: inline-block;
}

.xr-dim-list {
  display: inline-block !important;
  list-style: none;
  padding: 0 !important;
  margin: 0;
}

.xr-dim-list li {
  display: inline-block;
  padding: 0;
  margin: 0;
}

.xr-dim-list:before {
  content: '(';
}

.xr-dim-list:after {
  content: ')';
}

.xr-dim-list li:not(:last-child):after {
  content: ',';
  padding-right: 5px;
}

.xr-has-index {
  font-weight: bold;
}

.xr-var-list,
.xr-var-item {
  display: contents;
}

.xr-var-item &gt; div,
.xr-var-item label,
.xr-var-item &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-even);
  margin-bottom: 0;
}

.xr-var-item &gt; .xr-var-name:hover span {
  padding-right: 5px;
}

.xr-var-list &gt; li:nth-child(odd) &gt; div,
.xr-var-list &gt; li:nth-child(odd) &gt; label,
.xr-var-list &gt; li:nth-child(odd) &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-odd);
}

.xr-var-name {
  grid-column: 1;
}

.xr-var-dims {
  grid-column: 2;
}

.xr-var-dtype {
  grid-column: 3;
  text-align: right;
  color: var(--xr-font-color2);
}

.xr-var-preview {
  grid-column: 4;
}

.xr-var-name,
.xr-var-dims,
.xr-var-dtype,
.xr-preview,
.xr-attrs dt {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 10px;
}

.xr-var-name:hover,
.xr-var-dims:hover,
.xr-var-dtype:hover,
.xr-attrs dt:hover {
  overflow: visible;
  width: auto;
  z-index: 1;
}

.xr-var-attrs,
.xr-var-data {
  display: none;
  background-color: var(--xr-background-color) !important;
  padding-bottom: 5px !important;
}

.xr-var-attrs-in:checked ~ .xr-var-attrs,
.xr-var-data-in:checked ~ .xr-var-data {
  display: block;
}

.xr-var-data &gt; table {
  float: right;
}

.xr-var-name span,
.xr-var-data,
.xr-attrs {
  padding-left: 25px !important;
}

.xr-attrs,
.xr-var-attrs,
.xr-var-data {
  grid-column: 1 / -1;
}

dl.xr-attrs {
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 125px auto;
}

.xr-attrs dt,
.xr-attrs dd {
  padding: 0;
  margin: 0;
  float: left;
  padding-right: 10px;
  width: auto;
}

.xr-attrs dt {
  font-weight: normal;
  grid-column: 1;
}

.xr-attrs dt:hover span {
  display: inline-block;
  background: var(--xr-background-color);
  padding-right: 10px;
}

.xr-attrs dd {
  grid-column: 2;
  white-space: pre-wrap;
  word-break: break-all;
}

.xr-icon-database,
.xr-icon-file-text2 {
  display: inline-block;
  vertical-align: middle;
  width: 1em;
  height: 1.5em !important;
  stroke-width: 0;
  stroke: currentColor;
  fill: currentColor;
}
&lt;/style&gt;
&lt;pre class="xr-text-repr-fallback"&gt;&amp;lt;xarray.Dataset&amp;gt;
Dimensions:  ()
Data variables:
    z        float64 1.006
    β0       float64 1.001
    σ        float64 1.001
    τ        float64 1.002
    λ        float64 1.004
    c2       float64 1.0
    β        float64 1.002&lt;/pre&gt;
&lt;div class="xr-wrap" hidden=""&gt;
&lt;div class="xr-header"&gt;
&lt;div class="xr-obj-type"&gt;
xarray.Dataset
&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="xr-sections"&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-fed721cf-8c6d-46da-a16b-22f379af3f92" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-fed721cf-8c6d-46da-a16b-22f379af3f92" class="xr-section-summary" title="Expand/collapse section"&gt;Dimensions:&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-35916933-2414-4cd0-aeea-7f35e685f6a1" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-35916933-2414-4cd0-aeea-7f35e685f6a1" class="xr-section-summary" title="Expand/collapse section"&gt;Coordinates: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-a9fde3d1-4f14-41ee-8417-dff3276a6f39" class="xr-section-summary-in" type="checkbox" checked&gt;&lt;label for="section-a9fde3d1-4f14-41ee-8417-dff3276a6f39" class="xr-section-summary"&gt;Data variables: &lt;span&gt;(7)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;z&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.006
&lt;/div&gt;
&lt;input id="attrs-880a360c-1136-45b9-8fca-5927c13c1122" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-880a360c-1136-45b9-8fca-5927c13c1122" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-e816e0e2-5842-4bb7-b277-90cdedcc8d84" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-e816e0e2-5842-4bb7-b277-90cdedcc8d84" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00634042)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;β0&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.001
&lt;/div&gt;
&lt;input id="attrs-74e72b4d-0132-4819-9915-6f2155db16f4" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-74e72b4d-0132-4819-9915-6f2155db16f4" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-4f4a5400-6e30-4943-8253-6158c4edfba8" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-4f4a5400-6e30-4943-8253-6158c4edfba8" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00109199)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;σ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.001
&lt;/div&gt;
&lt;input id="attrs-9395dc3f-dcb4-4a16-b9e1-4b69b294e9e7" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-9395dc3f-dcb4-4a16-b9e1-4b69b294e9e7" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-5f5da7f7-09d7-42b9-8f86-abef0f36eb82" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-5f5da7f7-09d7-42b9-8f86-abef0f36eb82" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.0012928)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;τ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.002
&lt;/div&gt;
&lt;input id="attrs-f2e350ac-9ba5-4291-9d99-26b6453054e7" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-f2e350ac-9ba5-4291-9d99-26b6453054e7" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-14b84f37-16a7-4a8c-a0be-efe59e114993" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-14b84f37-16a7-4a8c-a0be-efe59e114993" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00197336)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;λ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.004
&lt;/div&gt;
&lt;input id="attrs-6ef40866-ddec-4a77-a6b5-a79ca32af7f2" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-6ef40866-ddec-4a77-a6b5-a79ca32af7f2" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-271fc19c-30a6-43da-8cdc-1dd4106049b7" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-271fc19c-30a6-43da-8cdc-1dd4106049b7" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00367552)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;c2&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.0
&lt;/div&gt;
&lt;input id="attrs-ddd82f73-e6d2-423a-87a5-41fe6b295817" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-ddd82f73-e6d2-423a-87a5-41fe6b295817" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-31b518c1-2741-4bbb-b3e6-56a0a12930f4" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-31b518c1-2741-4bbb-b3e6-56a0a12930f4" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00018438)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;β&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.002
&lt;/div&gt;
&lt;input id="attrs-d01e0c84-8410-496f-8995-50dc44f6a7f8" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-d01e0c84-8410-496f-8995-50dc44f6a7f8" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-33b5bf98-96a8-43c2-8821-c1fb03c0b1a0" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-33b5bf98-96a8-43c2-8821-c1fb03c0b1a0" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00235304)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-ac0c19be-fec5-4acd-8dda-ef868e868ec2" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-ac0c19be-fec5-4acd-8dda-ef868e868ec2" class="xr-section-summary" title="Expand/collapse section"&gt;Attributes: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The relative error in recovering the true nonzero parameters is quite good (the largest relative error is approximately 3%).&lt;/p&gt;
&lt;div class="sourceCode" id="cb27"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb27-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb27-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; post_mean(trace, var_name):&lt;/span&gt;
&lt;span id="cb27-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb27-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; trace[&lt;span class="st"&gt;"posterior"&lt;/span&gt;][var_name].mean(dim&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="st"&gt;"chain"&lt;/span&gt;, &lt;span class="st"&gt;"draw"&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb28"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb28-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb28-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;np.&lt;span class="bu"&gt;abs&lt;/span&gt;((post_mean(trace, &lt;span class="st"&gt;"β"&lt;/span&gt;)[:D0] &lt;span class="op"&gt;-&lt;/span&gt; COEF[:D0]) &lt;span class="op"&gt;/&lt;/span&gt; COEF[:D0]).&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;svg style="position: absolute; width: 0; height: 0; overflow: hidden"&gt;
&lt;defs&gt; &lt;symbol id="icon-database" viewbox="0 0 32 32"&gt; &lt;path d="M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z"&gt;&lt;/path&gt; &lt;path d="M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;path d="M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;symbol id="icon-file-text2" viewbox="0 0 32 32"&gt; &lt;path d="M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z"&gt;&lt;/path&gt; &lt;path d="M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;/defs&gt;
&lt;/svg&gt;
&lt;style&gt;/* CSS stylesheet for displaying xarray objects in jupyterlab.
 *
 */

:root {
  --xr-font-color0: var(--jp-content-font-color0, rgba(0, 0, 0, 1));
  --xr-font-color2: var(--jp-content-font-color2, rgba(0, 0, 0, 0.54));
  --xr-font-color3: var(--jp-content-font-color3, rgba(0, 0, 0, 0.38));
  --xr-border-color: var(--jp-border-color2, #e0e0e0);
  --xr-disabled-color: var(--jp-layout-color3, #bdbdbd);
  --xr-background-color: var(--jp-layout-color0, white);
  --xr-background-color-row-even: var(--jp-layout-color1, white);
  --xr-background-color-row-odd: var(--jp-layout-color2, #eeeeee);
}

html[theme=dark],
body.vscode-dark {
  --xr-font-color0: rgba(255, 255, 255, 1);
  --xr-font-color2: rgba(255, 255, 255, 0.54);
  --xr-font-color3: rgba(255, 255, 255, 0.38);
  --xr-border-color: #1F1F1F;
  --xr-disabled-color: #515151;
  --xr-background-color: #111111;
  --xr-background-color-row-even: #111111;
  --xr-background-color-row-odd: #313131;
}

.xr-wrap {
  display: block;
  min-width: 300px;
  max-width: 700px;
}

.xr-text-repr-fallback {
  /* fallback to plain text repr when CSS is not injected (untrusted notebook) */
  display: none;
}

.xr-header {
  padding-top: 6px;
  padding-bottom: 6px;
  margin-bottom: 4px;
  border-bottom: solid 1px var(--xr-border-color);
}

.xr-header &gt; div,
.xr-header &gt; ul {
  display: inline;
  margin-top: 0;
  margin-bottom: 0;
}

.xr-obj-type,
.xr-array-name {
  margin-left: 2px;
  margin-right: 10px;
}

.xr-obj-type {
  color: var(--xr-font-color2);
}

.xr-sections {
  padding-left: 0 !important;
  display: grid;
  grid-template-columns: 150px auto auto 1fr 20px 20px;
}

.xr-section-item {
  display: contents;
}

.xr-section-item input {
  display: none;
}

.xr-section-item input + label {
  color: var(--xr-disabled-color);
}

.xr-section-item input:enabled + label {
  cursor: pointer;
  color: var(--xr-font-color2);
}

.xr-section-item input:enabled + label:hover {
  color: var(--xr-font-color0);
}

.xr-section-summary {
  grid-column: 1;
  color: var(--xr-font-color2);
  font-weight: 500;
}

.xr-section-summary &gt; span {
  display: inline-block;
  padding-left: 0.5em;
}

.xr-section-summary-in:disabled + label {
  color: var(--xr-font-color2);
}

.xr-section-summary-in + label:before {
  display: inline-block;
  content: '►';
  font-size: 11px;
  width: 15px;
  text-align: center;
}

.xr-section-summary-in:disabled + label:before {
  color: var(--xr-disabled-color);
}

.xr-section-summary-in:checked + label:before {
  content: '▼';
}

.xr-section-summary-in:checked + label &gt; span {
  display: none;
}

.xr-section-summary,
.xr-section-inline-details {
  padding-top: 4px;
  padding-bottom: 4px;
}

.xr-section-inline-details {
  grid-column: 2 / -1;
}

.xr-section-details {
  display: none;
  grid-column: 1 / -1;
  margin-bottom: 5px;
}

.xr-section-summary-in:checked ~ .xr-section-details {
  display: contents;
}

.xr-array-wrap {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 20px auto;
}

.xr-array-wrap &gt; label {
  grid-column: 1;
  vertical-align: top;
}

.xr-preview {
  color: var(--xr-font-color3);
}

.xr-array-preview,
.xr-array-data {
  padding: 0 5px !important;
  grid-column: 2;
}

.xr-array-data,
.xr-array-in:checked ~ .xr-array-preview {
  display: none;
}

.xr-array-in:checked ~ .xr-array-data,
.xr-array-preview {
  display: inline-block;
}

.xr-dim-list {
  display: inline-block !important;
  list-style: none;
  padding: 0 !important;
  margin: 0;
}

.xr-dim-list li {
  display: inline-block;
  padding: 0;
  margin: 0;
}

.xr-dim-list:before {
  content: '(';
}

.xr-dim-list:after {
  content: ')';
}

.xr-dim-list li:not(:last-child):after {
  content: ',';
  padding-right: 5px;
}

.xr-has-index {
  font-weight: bold;
}

.xr-var-list,
.xr-var-item {
  display: contents;
}

.xr-var-item &gt; div,
.xr-var-item label,
.xr-var-item &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-even);
  margin-bottom: 0;
}

.xr-var-item &gt; .xr-var-name:hover span {
  padding-right: 5px;
}

.xr-var-list &gt; li:nth-child(odd) &gt; div,
.xr-var-list &gt; li:nth-child(odd) &gt; label,
.xr-var-list &gt; li:nth-child(odd) &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-odd);
}

.xr-var-name {
  grid-column: 1;
}

.xr-var-dims {
  grid-column: 2;
}

.xr-var-dtype {
  grid-column: 3;
  text-align: right;
  color: var(--xr-font-color2);
}

.xr-var-preview {
  grid-column: 4;
}

.xr-var-name,
.xr-var-dims,
.xr-var-dtype,
.xr-preview,
.xr-attrs dt {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 10px;
}

.xr-var-name:hover,
.xr-var-dims:hover,
.xr-var-dtype:hover,
.xr-attrs dt:hover {
  overflow: visible;
  width: auto;
  z-index: 1;
}

.xr-var-attrs,
.xr-var-data {
  display: none;
  background-color: var(--xr-background-color) !important;
  padding-bottom: 5px !important;
}

.xr-var-attrs-in:checked ~ .xr-var-attrs,
.xr-var-data-in:checked ~ .xr-var-data {
  display: block;
}

.xr-var-data &gt; table {
  float: right;
}

.xr-var-name span,
.xr-var-data,
.xr-attrs {
  padding-left: 25px !important;
}

.xr-attrs,
.xr-var-attrs,
.xr-var-data {
  grid-column: 1 / -1;
}

dl.xr-attrs {
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 125px auto;
}

.xr-attrs dt,
.xr-attrs dd {
  padding: 0;
  margin: 0;
  float: left;
  padding-right: 10px;
  width: auto;
}

.xr-attrs dt {
  font-weight: normal;
  grid-column: 1;
}

.xr-attrs dt:hover span {
  display: inline-block;
  background: var(--xr-background-color);
  padding-right: 10px;
}

.xr-attrs dd {
  grid-column: 2;
  white-space: pre-wrap;
  word-break: break-all;
}

.xr-icon-database,
.xr-icon-file-text2 {
  display: inline-block;
  vertical-align: middle;
  width: 1em;
  height: 1.5em !important;
  stroke-width: 0;
  stroke: currentColor;
  fill: currentColor;
}
&lt;/style&gt;
&lt;pre class="xr-text-repr-fallback"&gt;&amp;lt;xarray.DataArray 'β' ()&amp;gt;
array(0.03201216)&lt;/pre&gt;
&lt;div class="xr-wrap" hidden=""&gt;
&lt;div class="xr-header"&gt;
&lt;div class="xr-obj-type"&gt;
xarray.DataArray
&lt;/div&gt;
&lt;div class="xr-array-name"&gt;
‘β’
&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="xr-sections"&gt;
&lt;li class="xr-section-item"&gt;
&lt;div class="xr-array-wrap"&gt;
&lt;input id="section-ee713d78-0554-41ea-bfd7-c7e66dc3757c" class="xr-array-in" type="checkbox" checked&gt;&lt;label for="section-ee713d78-0554-41ea-bfd7-c7e66dc3757c" title="Show/hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-array-preview xr-preview"&gt;
&lt;span&gt;0.03201&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-array-data"&gt;
&lt;pre&gt;array(0.03201216)&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-f7b4799e-a0ac-4d6f-8220-b345c102b83b" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-f7b4799e-a0ac-4d6f-8220-b345c102b83b" class="xr-section-summary" title="Expand/collapse section"&gt;Coordinates: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-0ace46a4-ea49-4b34-b437-11419d7da2db" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-0ace46a4-ea49-4b34-b437-11419d7da2db" class="xr-section-summary" title="Expand/collapse section"&gt;Attributes: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Visually, the true parameter values lie comfortably inside the 95% high posterior density intervals for these nonzero parameters.&lt;/p&gt;
&lt;div class="sourceCode" id="cb29"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb29-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax, &lt;span class="op"&gt;=&lt;/span&gt; az.plot_forest(&lt;/span&gt;
&lt;span id="cb29-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    trace, var_names&lt;span class="op"&gt;=&lt;/span&gt;[&lt;span class="st"&gt;"β"&lt;/span&gt;], coords&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;"β_dim_0"&lt;/span&gt;: &lt;span class="bu"&gt;range&lt;/span&gt;(D0)},&lt;/span&gt;
&lt;span id="cb29-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'ridgeplot'&lt;/span&gt;, ridgeplot_truncate&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, ridgeplot_alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb29-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    hdi_prob&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.95&lt;/span&gt;, combined&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb29-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb29-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb29-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.scatter(COEF[:D0][::&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;], ax.get_yticks(),&lt;/span&gt;
&lt;span id="cb29-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C1'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb29-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Actual value"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="vs"&gt;r"$\beta_i$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylim(bottom&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, top&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;1.55&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; ax.get_yticks().&lt;span class="bu"&gt;max&lt;/span&gt;())&lt;/span&gt;
&lt;span id="cb29-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yticklabels(&lt;span class="bu"&gt;range&lt;/span&gt;(D0)[::&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="vs"&gt;r"$i$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'upper center'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb29-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Posterior distribution of nonzero coefficients"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/horseshoe_files/horseshoe_44_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The (absolute) largest posterior expected value for a coefficient that is actually zero is relatively small compared to the scale of the nonzero parameters.&lt;/p&gt;
&lt;div class="sourceCode" id="cb30"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb30-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb30-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;np.&lt;span class="bu"&gt;abs&lt;/span&gt;(post_mean(trace, &lt;span class="st"&gt;"β"&lt;/span&gt;)[D0:]).&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;svg style="position: absolute; width: 0; height: 0; overflow: hidden"&gt;
&lt;defs&gt; &lt;symbol id="icon-database" viewbox="0 0 32 32"&gt; &lt;path d="M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z"&gt;&lt;/path&gt; &lt;path d="M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;path d="M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;symbol id="icon-file-text2" viewbox="0 0 32 32"&gt; &lt;path d="M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z"&gt;&lt;/path&gt; &lt;path d="M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;/defs&gt;
&lt;/svg&gt;
&lt;style&gt;/* CSS stylesheet for displaying xarray objects in jupyterlab.
 *
 */

:root {
  --xr-font-color0: var(--jp-content-font-color0, rgba(0, 0, 0, 1));
  --xr-font-color2: var(--jp-content-font-color2, rgba(0, 0, 0, 0.54));
  --xr-font-color3: var(--jp-content-font-color3, rgba(0, 0, 0, 0.38));
  --xr-border-color: var(--jp-border-color2, #e0e0e0);
  --xr-disabled-color: var(--jp-layout-color3, #bdbdbd);
  --xr-background-color: var(--jp-layout-color0, white);
  --xr-background-color-row-even: var(--jp-layout-color1, white);
  --xr-background-color-row-odd: var(--jp-layout-color2, #eeeeee);
}

html[theme=dark],
body.vscode-dark {
  --xr-font-color0: rgba(255, 255, 255, 1);
  --xr-font-color2: rgba(255, 255, 255, 0.54);
  --xr-font-color3: rgba(255, 255, 255, 0.38);
  --xr-border-color: #1F1F1F;
  --xr-disabled-color: #515151;
  --xr-background-color: #111111;
  --xr-background-color-row-even: #111111;
  --xr-background-color-row-odd: #313131;
}

.xr-wrap {
  display: block;
  min-width: 300px;
  max-width: 700px;
}

.xr-text-repr-fallback {
  /* fallback to plain text repr when CSS is not injected (untrusted notebook) */
  display: none;
}

.xr-header {
  padding-top: 6px;
  padding-bottom: 6px;
  margin-bottom: 4px;
  border-bottom: solid 1px var(--xr-border-color);
}

.xr-header &gt; div,
.xr-header &gt; ul {
  display: inline;
  margin-top: 0;
  margin-bottom: 0;
}

.xr-obj-type,
.xr-array-name {
  margin-left: 2px;
  margin-right: 10px;
}

.xr-obj-type {
  color: var(--xr-font-color2);
}

.xr-sections {
  padding-left: 0 !important;
  display: grid;
  grid-template-columns: 150px auto auto 1fr 20px 20px;
}

.xr-section-item {
  display: contents;
}

.xr-section-item input {
  display: none;
}

.xr-section-item input + label {
  color: var(--xr-disabled-color);
}

.xr-section-item input:enabled + label {
  cursor: pointer;
  color: var(--xr-font-color2);
}

.xr-section-item input:enabled + label:hover {
  color: var(--xr-font-color0);
}

.xr-section-summary {
  grid-column: 1;
  color: var(--xr-font-color2);
  font-weight: 500;
}

.xr-section-summary &gt; span {
  display: inline-block;
  padding-left: 0.5em;
}

.xr-section-summary-in:disabled + label {
  color: var(--xr-font-color2);
}

.xr-section-summary-in + label:before {
  display: inline-block;
  content: '►';
  font-size: 11px;
  width: 15px;
  text-align: center;
}

.xr-section-summary-in:disabled + label:before {
  color: var(--xr-disabled-color);
}

.xr-section-summary-in:checked + label:before {
  content: '▼';
}

.xr-section-summary-in:checked + label &gt; span {
  display: none;
}

.xr-section-summary,
.xr-section-inline-details {
  padding-top: 4px;
  padding-bottom: 4px;
}

.xr-section-inline-details {
  grid-column: 2 / -1;
}

.xr-section-details {
  display: none;
  grid-column: 1 / -1;
  margin-bottom: 5px;
}

.xr-section-summary-in:checked ~ .xr-section-details {
  display: contents;
}

.xr-array-wrap {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 20px auto;
}

.xr-array-wrap &gt; label {
  grid-column: 1;
  vertical-align: top;
}

.xr-preview {
  color: var(--xr-font-color3);
}

.xr-array-preview,
.xr-array-data {
  padding: 0 5px !important;
  grid-column: 2;
}

.xr-array-data,
.xr-array-in:checked ~ .xr-array-preview {
  display: none;
}

.xr-array-in:checked ~ .xr-array-data,
.xr-array-preview {
  display: inline-block;
}

.xr-dim-list {
  display: inline-block !important;
  list-style: none;
  padding: 0 !important;
  margin: 0;
}

.xr-dim-list li {
  display: inline-block;
  padding: 0;
  margin: 0;
}

.xr-dim-list:before {
  content: '(';
}

.xr-dim-list:after {
  content: ')';
}

.xr-dim-list li:not(:last-child):after {
  content: ',';
  padding-right: 5px;
}

.xr-has-index {
  font-weight: bold;
}

.xr-var-list,
.xr-var-item {
  display: contents;
}

.xr-var-item &gt; div,
.xr-var-item label,
.xr-var-item &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-even);
  margin-bottom: 0;
}

.xr-var-item &gt; .xr-var-name:hover span {
  padding-right: 5px;
}

.xr-var-list &gt; li:nth-child(odd) &gt; div,
.xr-var-list &gt; li:nth-child(odd) &gt; label,
.xr-var-list &gt; li:nth-child(odd) &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-odd);
}

.xr-var-name {
  grid-column: 1;
}

.xr-var-dims {
  grid-column: 2;
}

.xr-var-dtype {
  grid-column: 3;
  text-align: right;
  color: var(--xr-font-color2);
}

.xr-var-preview {
  grid-column: 4;
}

.xr-var-name,
.xr-var-dims,
.xr-var-dtype,
.xr-preview,
.xr-attrs dt {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 10px;
}

.xr-var-name:hover,
.xr-var-dims:hover,
.xr-var-dtype:hover,
.xr-attrs dt:hover {
  overflow: visible;
  width: auto;
  z-index: 1;
}

.xr-var-attrs,
.xr-var-data {
  display: none;
  background-color: var(--xr-background-color) !important;
  padding-bottom: 5px !important;
}

.xr-var-attrs-in:checked ~ .xr-var-attrs,
.xr-var-data-in:checked ~ .xr-var-data {
  display: block;
}

.xr-var-data &gt; table {
  float: right;
}

.xr-var-name span,
.xr-var-data,
.xr-attrs {
  padding-left: 25px !important;
}

.xr-attrs,
.xr-var-attrs,
.xr-var-data {
  grid-column: 1 / -1;
}

dl.xr-attrs {
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 125px auto;
}

.xr-attrs dt,
.xr-attrs dd {
  padding: 0;
  margin: 0;
  float: left;
  padding-right: 10px;
  width: auto;
}

.xr-attrs dt {
  font-weight: normal;
  grid-column: 1;
}

.xr-attrs dt:hover span {
  display: inline-block;
  background: var(--xr-background-color);
  padding-right: 10px;
}

.xr-attrs dd {
  grid-column: 2;
  white-space: pre-wrap;
  word-break: break-all;
}

.xr-icon-database,
.xr-icon-file-text2 {
  display: inline-block;
  vertical-align: middle;
  width: 1em;
  height: 1.5em !important;
  stroke-width: 0;
  stroke: currentColor;
  fill: currentColor;
}
&lt;/style&gt;
&lt;pre class="xr-text-repr-fallback"&gt;&amp;lt;xarray.DataArray 'β' ()&amp;gt;
array(0.2778543)&lt;/pre&gt;
&lt;div class="xr-wrap" hidden=""&gt;
&lt;div class="xr-header"&gt;
&lt;div class="xr-obj-type"&gt;
xarray.DataArray
&lt;/div&gt;
&lt;div class="xr-array-name"&gt;
‘β’
&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="xr-sections"&gt;
&lt;li class="xr-section-item"&gt;
&lt;div class="xr-array-wrap"&gt;
&lt;input id="section-69092d20-7c6f-46c3-8847-e664ec3a81a7" class="xr-array-in" type="checkbox" checked&gt;&lt;label for="section-69092d20-7c6f-46c3-8847-e664ec3a81a7" title="Show/hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-array-preview xr-preview"&gt;
&lt;span&gt;0.2779&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-array-data"&gt;
&lt;pre&gt;array(0.2778543)&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-73723dad-4c5e-4277-8694-4d92cb81889f" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-73723dad-4c5e-4277-8694-4d92cb81889f" class="xr-section-summary" title="Expand/collapse section"&gt;Coordinates: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-03993c06-d0ec-41f6-839b-7585a91b32a3" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-03993c06-d0ec-41f6-839b-7585a91b32a3" class="xr-section-summary" title="Expand/collapse section"&gt;Attributes: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The following plot shows the posterior distributions of the &lt;span class="math inline"&gt;\(D - D_0 = 45\)&lt;/span&gt; coefficients. Most of the distributions show a pronounced peak around zero, as we would expect for a sparse estimator.&lt;/p&gt;
&lt;div class="sourceCode" id="cb31"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb31-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb31-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb31-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb31-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb31-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb31-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;for&lt;/span&gt; i &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;range&lt;/span&gt;(D0, D):&lt;/span&gt;
&lt;span id="cb31-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb31-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.hist(trace[&lt;span class="st"&gt;"posterior"&lt;/span&gt;][&lt;span class="st"&gt;"β"&lt;/span&gt;][..., i].data.ravel(),&lt;/span&gt;
&lt;span id="cb31-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb31-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            histtype&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'step'&lt;/span&gt;, bins&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;100&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb31-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb31-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.25&lt;/span&gt;,)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb31-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb31-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb31-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="ss"&gt;f"$&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="ss"&gt;beta_i$&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="ss"&gt;$i = &lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;D0&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;,...,&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;D&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb31-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb31-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb31-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yticks([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb31-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Density"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb31-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb31-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb31-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb31-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Posterior distributions"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/horseshoe_files/horseshoe_48_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;And surely enough, all but one of the 95% high posterior density intervals for the coefficients that are actually zero contain zero.&lt;/p&gt;
&lt;div class="sourceCode" id="cb32"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb32-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb32-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;post_β_low, post_β_high &lt;span class="op"&gt;=&lt;/span&gt; trace[&lt;span class="st"&gt;"posterior"&lt;/span&gt;][&lt;span class="st"&gt;"β"&lt;/span&gt;][..., D0:].quantile([&lt;span class="fl"&gt;0.025&lt;/span&gt;, &lt;span class="fl"&gt;0.975&lt;/span&gt;], dim&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="st"&gt;'chain'&lt;/span&gt;, &lt;span class="st"&gt;'draw'&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb32-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb32-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb32-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb32-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;((post_β_low &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;) &lt;span class="op"&gt;&amp;amp;&lt;/span&gt; (&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;=&lt;/span&gt; post_β_high)).mean()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;svg style="position: absolute; width: 0; height: 0; overflow: hidden"&gt;
&lt;defs&gt; &lt;symbol id="icon-database" viewbox="0 0 32 32"&gt; &lt;path d="M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z"&gt;&lt;/path&gt; &lt;path d="M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;path d="M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;symbol id="icon-file-text2" viewbox="0 0 32 32"&gt; &lt;path d="M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z"&gt;&lt;/path&gt; &lt;path d="M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;/defs&gt;
&lt;/svg&gt;
&lt;style&gt;/* CSS stylesheet for displaying xarray objects in jupyterlab.
 *
 */

:root {
  --xr-font-color0: var(--jp-content-font-color0, rgba(0, 0, 0, 1));
  --xr-font-color2: var(--jp-content-font-color2, rgba(0, 0, 0, 0.54));
  --xr-font-color3: var(--jp-content-font-color3, rgba(0, 0, 0, 0.38));
  --xr-border-color: var(--jp-border-color2, #e0e0e0);
  --xr-disabled-color: var(--jp-layout-color3, #bdbdbd);
  --xr-background-color: var(--jp-layout-color0, white);
  --xr-background-color-row-even: var(--jp-layout-color1, white);
  --xr-background-color-row-odd: var(--jp-layout-color2, #eeeeee);
}

html[theme=dark],
body.vscode-dark {
  --xr-font-color0: rgba(255, 255, 255, 1);
  --xr-font-color2: rgba(255, 255, 255, 0.54);
  --xr-font-color3: rgba(255, 255, 255, 0.38);
  --xr-border-color: #1F1F1F;
  --xr-disabled-color: #515151;
  --xr-background-color: #111111;
  --xr-background-color-row-even: #111111;
  --xr-background-color-row-odd: #313131;
}

.xr-wrap {
  display: block;
  min-width: 300px;
  max-width: 700px;
}

.xr-text-repr-fallback {
  /* fallback to plain text repr when CSS is not injected (untrusted notebook) */
  display: none;
}

.xr-header {
  padding-top: 6px;
  padding-bottom: 6px;
  margin-bottom: 4px;
  border-bottom: solid 1px var(--xr-border-color);
}

.xr-header &gt; div,
.xr-header &gt; ul {
  display: inline;
  margin-top: 0;
  margin-bottom: 0;
}

.xr-obj-type,
.xr-array-name {
  margin-left: 2px;
  margin-right: 10px;
}

.xr-obj-type {
  color: var(--xr-font-color2);
}

.xr-sections {
  padding-left: 0 !important;
  display: grid;
  grid-template-columns: 150px auto auto 1fr 20px 20px;
}

.xr-section-item {
  display: contents;
}

.xr-section-item input {
  display: none;
}

.xr-section-item input + label {
  color: var(--xr-disabled-color);
}

.xr-section-item input:enabled + label {
  cursor: pointer;
  color: var(--xr-font-color2);
}

.xr-section-item input:enabled + label:hover {
  color: var(--xr-font-color0);
}

.xr-section-summary {
  grid-column: 1;
  color: var(--xr-font-color2);
  font-weight: 500;
}

.xr-section-summary &gt; span {
  display: inline-block;
  padding-left: 0.5em;
}

.xr-section-summary-in:disabled + label {
  color: var(--xr-font-color2);
}

.xr-section-summary-in + label:before {
  display: inline-block;
  content: '►';
  font-size: 11px;
  width: 15px;
  text-align: center;
}

.xr-section-summary-in:disabled + label:before {
  color: var(--xr-disabled-color);
}

.xr-section-summary-in:checked + label:before {
  content: '▼';
}

.xr-section-summary-in:checked + label &gt; span {
  display: none;
}

.xr-section-summary,
.xr-section-inline-details {
  padding-top: 4px;
  padding-bottom: 4px;
}

.xr-section-inline-details {
  grid-column: 2 / -1;
}

.xr-section-details {
  display: none;
  grid-column: 1 / -1;
  margin-bottom: 5px;
}

.xr-section-summary-in:checked ~ .xr-section-details {
  display: contents;
}

.xr-array-wrap {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 20px auto;
}

.xr-array-wrap &gt; label {
  grid-column: 1;
  vertical-align: top;
}

.xr-preview {
  color: var(--xr-font-color3);
}

.xr-array-preview,
.xr-array-data {
  padding: 0 5px !important;
  grid-column: 2;
}

.xr-array-data,
.xr-array-in:checked ~ .xr-array-preview {
  display: none;
}

.xr-array-in:checked ~ .xr-array-data,
.xr-array-preview {
  display: inline-block;
}

.xr-dim-list {
  display: inline-block !important;
  list-style: none;
  padding: 0 !important;
  margin: 0;
}

.xr-dim-list li {
  display: inline-block;
  padding: 0;
  margin: 0;
}

.xr-dim-list:before {
  content: '(';
}

.xr-dim-list:after {
  content: ')';
}

.xr-dim-list li:not(:last-child):after {
  content: ',';
  padding-right: 5px;
}

.xr-has-index {
  font-weight: bold;
}

.xr-var-list,
.xr-var-item {
  display: contents;
}

.xr-var-item &gt; div,
.xr-var-item label,
.xr-var-item &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-even);
  margin-bottom: 0;
}

.xr-var-item &gt; .xr-var-name:hover span {
  padding-right: 5px;
}

.xr-var-list &gt; li:nth-child(odd) &gt; div,
.xr-var-list &gt; li:nth-child(odd) &gt; label,
.xr-var-list &gt; li:nth-child(odd) &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-odd);
}

.xr-var-name {
  grid-column: 1;
}

.xr-var-dims {
  grid-column: 2;
}

.xr-var-dtype {
  grid-column: 3;
  text-align: right;
  color: var(--xr-font-color2);
}

.xr-var-preview {
  grid-column: 4;
}

.xr-var-name,
.xr-var-dims,
.xr-var-dtype,
.xr-preview,
.xr-attrs dt {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 10px;
}

.xr-var-name:hover,
.xr-var-dims:hover,
.xr-var-dtype:hover,
.xr-attrs dt:hover {
  overflow: visible;
  width: auto;
  z-index: 1;
}

.xr-var-attrs,
.xr-var-data {
  display: none;
  background-color: var(--xr-background-color) !important;
  padding-bottom: 5px !important;
}

.xr-var-attrs-in:checked ~ .xr-var-attrs,
.xr-var-data-in:checked ~ .xr-var-data {
  display: block;
}

.xr-var-data &gt; table {
  float: right;
}

.xr-var-name span,
.xr-var-data,
.xr-attrs {
  padding-left: 25px !important;
}

.xr-attrs,
.xr-var-attrs,
.xr-var-data {
  grid-column: 1 / -1;
}

dl.xr-attrs {
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 125px auto;
}

.xr-attrs dt,
.xr-attrs dd {
  padding: 0;
  margin: 0;
  float: left;
  padding-right: 10px;
  width: auto;
}

.xr-attrs dt {
  font-weight: normal;
  grid-column: 1;
}

.xr-attrs dt:hover span {
  display: inline-block;
  background: var(--xr-background-color);
  padding-right: 10px;
}

.xr-attrs dd {
  grid-column: 2;
  white-space: pre-wrap;
  word-break: break-all;
}

.xr-icon-database,
.xr-icon-file-text2 {
  display: inline-block;
  vertical-align: middle;
  width: 1em;
  height: 1.5em !important;
  stroke-width: 0;
  stroke: currentColor;
  fill: currentColor;
}
&lt;/style&gt;
&lt;pre class="xr-text-repr-fallback"&gt;&amp;lt;xarray.DataArray 'β' ()&amp;gt;
array(0.97777778)&lt;/pre&gt;
&lt;div class="xr-wrap" hidden=""&gt;
&lt;div class="xr-header"&gt;
&lt;div class="xr-obj-type"&gt;
xarray.DataArray
&lt;/div&gt;
&lt;div class="xr-array-name"&gt;
‘β’
&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="xr-sections"&gt;
&lt;li class="xr-section-item"&gt;
&lt;div class="xr-array-wrap"&gt;
&lt;input id="section-2b99fc40-1305-4580-bbea-8d7cff35ded0" class="xr-array-in" type="checkbox" checked&gt;&lt;label for="section-2b99fc40-1305-4580-bbea-8d7cff35ded0" title="Show/hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-array-preview xr-preview"&gt;
&lt;span&gt;0.9778&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-array-data"&gt;
&lt;pre&gt;array(0.97777778)&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-5b2d8178-0acf-402c-9407-8ddf7b0b0739" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-5b2d8178-0acf-402c-9407-8ddf7b0b0739" class="xr-section-summary" title="Expand/collapse section"&gt;Coordinates: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-bdd78d8f-4da8-45e0-83cd-e77cd074bd7a" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-bdd78d8f-4da8-45e0-83cd-e77cd074bd7a" class="xr-section-summary" title="Expand/collapse section"&gt;Attributes: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This post is available as a Jupyter notebook &lt;a href="https://nbviewer.jupyter.org/gist/AustinRochford/8838035ac87a080af3addbaf95f2a72f"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Many thanks to &lt;a href="https://twitter.com/SueMarquezR"&gt;Sue Márquez&lt;/a&gt; for pointing out that the original post spelled Aki’s name wrong, and sincere apologies to Aki.&lt;/p&gt;
&lt;div class="sourceCode" id="cb33"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb33-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb33-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;load_ext watermark&lt;/span&gt;
&lt;span id="cb33-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#cb33-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;watermark &lt;span class="op"&gt;-&lt;/span&gt;n &lt;span class="op"&gt;-&lt;/span&gt;u &lt;span class="op"&gt;-&lt;/span&gt;v &lt;span class="op"&gt;-&lt;/span&gt;iv&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Last updated: Sat May 29 2021

Python implementation: CPython
Python version       : 3.8.8
IPython version      : 7.22.0

matplotlib: 3.4.1
arviz     : 0.11.2
numpy     : 1.20.2
pymc3     : 3.11.1
aesara    : 2.0.6
seaborn   : 0.11.1&lt;/code&gt;&lt;/pre&gt;
&lt;section class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn1" role="doc-endnote"&gt;&lt;p&gt;Carvalho, C. M., Polson, N. G., &amp;amp; Scott, J. G. (2009, April). Handling sparsity via the horseshoe. In &lt;em&gt;Artificial Intelligence and Statistics&lt;/em&gt; (pp. 73-80). PMLR.&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#fnref1" class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id="fn2" role="doc-endnote"&gt;&lt;p&gt;Piironen, J., &amp;amp; Vehtari, A. (2017). Sparsity information and regularization in the horseshoe and other shrinkage priors. &lt;em&gt;Electronic Journal of Statistics&lt;/em&gt;, 11(2), 5018-5051.&lt;a href="https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html#fnref2" class="footnote-back" role="doc-backlink"&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;</description><category>Bayesian Statistics</category><category>PyMC3</category><category>Python</category><guid>https://austinrochford.com/posts/2021-05-29-horseshoe-pymc3.html</guid><pubDate>Sat, 29 May 2021 04:00:00 GMT</pubDate></item><item><title>A PyMC3 Analysis of Tyrannosaurid Growth Curves</title><link>https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html</link><dc:creator>Austin Rochford</dc:creator><description>&lt;p&gt;In Chapter 7 of their excellent book &lt;a href="https://bayessm.org/"&gt;&lt;em&gt;Bayesian Statistical Methods&lt;/em&gt;&lt;/a&gt; (&lt;em&gt;BSM&lt;/em&gt; from now on), Reich and Ghosh work an &lt;a href="https://www4.stat.ncsu.edu/~bjreich/BSMdata/T_rex.html"&gt;example analysis&lt;/a&gt; of the growth rates of &lt;a href="https://en.wikipedia.org/wiki/Tyrannosauridae"&gt;Tyrannosaurids&lt;/a&gt; in &lt;code&gt;R&lt;/code&gt; using &lt;a href="https://en.wikipedia.org/wiki/Just_another_Gibbs_sampler"&gt;&lt;code&gt;JAGS&lt;/code&gt;&lt;/a&gt;. This dataset and analysis are quite fun, so this post shows how to execute (almost) the same analysis in Python using PyCM3.&lt;/p&gt;
&lt;center&gt;
&lt;img src="https://img1.wsimg.com/isteam/ip/63bbf664-7db2-4c45-85ac-173680b714eb/b6a4ffdf-0e5b-4680-a317-d03661e7fa56.jpg" width="500"&gt;
&lt;/center&gt;
&lt;h2 id="the-dataset"&gt;The Dataset&lt;/h2&gt;
&lt;figure&gt;
&lt;center&gt;
&lt;p&gt;&lt;img src="https://austinrochford.com/resources/img/lego_trex.png" width="700" alt="Lego Tyrannosaurus Rex eating paleontologist minifigure"&gt;&lt;/p&gt;
&lt;caption&gt;
In addition to statistics, I am a Lego nerd.
&lt;/caption&gt;
&lt;/center&gt;
&lt;/figure&gt;
&lt;p&gt;To quote &lt;em&gt;BSM&lt;/em&gt;,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We analyze the data from 20 fossils to estimate the growth curves of four tyrannosaurid species: Albertosaurus, Daspletosaurus, Gorgosaurus and Tyrannosaurus. The data are taken from Table 1 of Erickson, GM et al (2004).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;First we make some standard Python imports and load the dataset from the author’s website.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb1-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;matplotlib inline&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb2-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; warnings &lt;span class="im"&gt;import&lt;/span&gt; filterwarnings&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb3-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; aesara &lt;span class="im"&gt;import&lt;/span&gt; shared, tensor &lt;span class="im"&gt;as&lt;/span&gt; at&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; arviz &lt;span class="im"&gt;as&lt;/span&gt; az&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib &lt;span class="im"&gt;import&lt;/span&gt; MatplotlibDeprecationWarning, pyplot &lt;span class="im"&gt;as&lt;/span&gt; plt&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; numpy &lt;span class="im"&gt;as&lt;/span&gt; np&lt;/span&gt;
&lt;span id="cb3-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb3-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pandas &lt;span class="im"&gt;as&lt;/span&gt; pd&lt;/span&gt;
&lt;span id="cb3-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb3-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pymc3 &lt;span class="im"&gt;as&lt;/span&gt; pm&lt;/span&gt;
&lt;span id="cb3-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb3-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; seaborn &lt;span class="im"&gt;as&lt;/span&gt; sns&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb4-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;filterwarnings(&lt;span class="st"&gt;'ignore'&lt;/span&gt;, category&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="pp"&gt;UserWarning&lt;/span&gt;, module&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'aesara'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb4-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;filterwarnings(&lt;span class="st"&gt;'ignore'&lt;/span&gt;, category&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="pp"&gt;UserWarning&lt;/span&gt;, module&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'arviz'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb4-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb4-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;filterwarnings(&lt;span class="st"&gt;'ignore'&lt;/span&gt;, category&lt;span class="op"&gt;=&lt;/span&gt;MatplotlibDeprecationWarning, module&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'pandas'&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb5-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.&lt;span class="bu"&gt;set&lt;/span&gt;(color_codes&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb6-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%%&lt;/span&gt;bash&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb6-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;DATA_URI&lt;span class="op"&gt;=&lt;/span&gt;https:&lt;span class="op"&gt;//&lt;/span&gt;www4.stat.ncsu.edu&lt;span class="op"&gt;/~&lt;/span&gt;bjreich&lt;span class="op"&gt;/&lt;/span&gt;BSMdata&lt;span class="op"&gt;/&lt;/span&gt;Erickson.csv&lt;/span&gt;
&lt;span id="cb6-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb6-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;DATA_DEST&lt;span class="op"&gt;=/&lt;/span&gt;tmp&lt;span class="op"&gt;/&lt;/span&gt;Erickson.csv&lt;/span&gt;
&lt;span id="cb6-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb6-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb6-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;if&lt;/span&gt; [[ &lt;span class="op"&gt;!&lt;/span&gt; &lt;span class="op"&gt;-&lt;/span&gt;e $DATA_DEST ]]&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb6-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;then&lt;/span&gt;
&lt;span id="cb6-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb6-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wget &lt;span class="op"&gt;-&lt;/span&gt;q &lt;span class="op"&gt;-&lt;/span&gt;O $DATA_DEST $DATA_URI&lt;/span&gt;
&lt;span id="cb6-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb6-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fi&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb7-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb7-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df &lt;span class="op"&gt;=&lt;/span&gt; (pd.read_csv(&lt;span class="st"&gt;'/tmp/Erickson.csv'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb7-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb7-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .rename(columns&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="bu"&gt;str&lt;/span&gt;.lower)&lt;/span&gt;
&lt;span id="cb7-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb7-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .sort_values(&lt;span class="st"&gt;'age'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb7-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb7-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .reset_index(drop&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb8-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style scoped&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;center&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
taxon
&lt;/th&gt;
&lt;th&gt;
spec. #
&lt;/th&gt;
&lt;th&gt;
age
&lt;/th&gt;
&lt;th&gt;
mass
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
Albertosaurus
&lt;/td&gt;
&lt;td&gt;
RTMP 2002.45.46
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
50.3
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1
&lt;/th&gt;
&lt;td&gt;
Tyrannosaurus
&lt;/td&gt;
&lt;td&gt;
LACM 28471
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
29.9
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2
&lt;/th&gt;
&lt;td&gt;
Gorgosaurus
&lt;/td&gt;
&lt;td&gt;
FMNH PR2211
&lt;/td&gt;
&lt;td&gt;
5
&lt;/td&gt;
&lt;td&gt;
127.0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
3
&lt;/th&gt;
&lt;td&gt;
Gorgosaurus
&lt;/td&gt;
&lt;td&gt;
RTMP 86.144.1
&lt;/td&gt;
&lt;td&gt;
7
&lt;/td&gt;
&lt;td&gt;
229.0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
4
&lt;/th&gt;
&lt;td&gt;
Daspletosaurus
&lt;/td&gt;
&lt;td&gt;
RTMP 94.143.1
&lt;/td&gt;
&lt;td&gt;
10
&lt;/td&gt;
&lt;td&gt;
496.0
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;&lt;/div&gt;

&lt;h3 id="exploratory-data-analysis"&gt;Exploratory data analysis&lt;/h3&gt;
&lt;p&gt;First we summarize and plot the data.&lt;/p&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb9-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df.describe()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style scoped&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;center&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
age
&lt;/th&gt;
&lt;th&gt;
mass
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
count
&lt;/th&gt;
&lt;td&gt;
20.00000
&lt;/td&gt;
&lt;td&gt;
20.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
mean
&lt;/th&gt;
&lt;td&gt;
15.10000
&lt;/td&gt;
&lt;td&gt;
1568.760000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
std
&lt;/th&gt;
&lt;td&gt;
7.05542
&lt;/td&gt;
&lt;td&gt;
1562.465702
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
min
&lt;/th&gt;
&lt;td&gt;
2.00000
&lt;/td&gt;
&lt;td&gt;
29.900000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
25%
&lt;/th&gt;
&lt;td&gt;
13.00000
&lt;/td&gt;
&lt;td&gt;
579.250000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
50%
&lt;/th&gt;
&lt;td&gt;
15.50000
&lt;/td&gt;
&lt;td&gt;
1123.500000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
75%
&lt;/th&gt;
&lt;td&gt;
18.75000
&lt;/td&gt;
&lt;td&gt;
1795.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
max
&lt;/th&gt;
&lt;td&gt;
28.00000
&lt;/td&gt;
&lt;td&gt;
5654.000000
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb10"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb10-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb10-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid &lt;span class="op"&gt;=&lt;/span&gt; sns.catplot(x&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'age'&lt;/span&gt;, y&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'mass'&lt;/span&gt;, hue&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'taxon'&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df)&lt;/span&gt;
&lt;span id="cb10-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb10-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb10-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid.ax.set_xlim(left&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb10-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid.ax.set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb10-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb10-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb10-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid.ax.set_ylim(bottom&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;100&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb10-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb10-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid.ax.set_yscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/tyrannosaurid/Growth%20Curves%20REPARAM_14_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Note the logarithmic scale on both of the axes here. A few points are immediately apparent.&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;There are only 20 samples, so the data is fairly small.&lt;/li&gt;
&lt;li&gt;Mass varies fairly widely across taxa.&lt;/li&gt;
&lt;li&gt;The relationship between age and mass appears linear on the log-log scale.&lt;/li&gt;
&lt;li&gt;Variance appears to increase with age.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="modeling"&gt;Modeling&lt;/h2&gt;
&lt;p&gt;Given the third and fourth observations about the data,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[w]e use multiplicative error rather than additive error because variation in the population likely increases with mass/age.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Throughout this post &lt;span class="math inline"&gt;\(Y_i\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(X_i\)&lt;/span&gt; will correspond to the mass and age of the &lt;span class="math inline"&gt;\(i\)&lt;/span&gt;-th sample respectively. Each of our four models will take the form&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[Y_i = f_{j(i)}(X_i) \cdot \varepsilon_{j(i)}.\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Here &lt;span class="math inline"&gt;\(\varepsilon_j\)&lt;/span&gt; corresponds to the multiplicative error for the &lt;span class="math inline"&gt;\(j\)&lt;/span&gt;-th taxon and &lt;span class="math inline"&gt;\(j(i)\)&lt;/span&gt; is the taxon identifier of the &lt;span class="math inline"&gt;\(i\)&lt;/span&gt;-th sample.&lt;/p&gt;
&lt;p&gt;We place a &lt;a href="https://en.wikipedia.org/wiki/Log-normal_distribution"&gt;log-normal&lt;/a&gt; prior on &lt;span class="math inline"&gt;\(\varepsilon_j\)&lt;/span&gt; so that $ (_j) = 1$ and &lt;span class="math inline"&gt;\(\textrm{Var}\left(\log(\varepsilon_j)\right) = \sigma_j^2\)&lt;/span&gt;. With the notation &lt;span class="math inline"&gt;\(y_i = \log Y_i\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(x_i = \log X_i\)&lt;/span&gt;, standard &lt;a href="https://en.wikipedia.org/wiki/Log-normal_distribution#Generation_and_parameters"&gt;distributional math&lt;/a&gt; shows that&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[y_i \sim N\left(\log\left(f_{j(i)}(X_{j(i)})\right) - \frac{\sigma_{j(i)}^2}{2}, \sigma_{j(i)}^2\right).\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Each of the four models we consider arises from a choice of the form of &lt;span class="math inline"&gt;\(f_j(X)\)&lt;/span&gt; (along with a prior for any of its unknown parameters) and a prior on &lt;span class="math inline"&gt;\(\sigma_j\)&lt;/span&gt;.&lt;/p&gt;
&lt;h3 id="unpooled-log-linear-model"&gt;Unpooled log-linear model&lt;/h3&gt;
&lt;p&gt;Given the third observation above, we begin with a log-linear model for the relationship between age and mass. If&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[f_j(X) = A_j \cdot X^{b_j}\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;then&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[\log\left(f_j(X)\right) = a_j + b_j \log X,\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;where &lt;span class="math inline"&gt;\(a_j = \log A_j\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;We define &lt;code&gt;log_age&lt;/code&gt; and &lt;code&gt;log_mass&lt;/code&gt; which correspond to &lt;span class="math inline"&gt;\(x_i\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(y_i\)&lt;/span&gt; respectively.&lt;/p&gt;
&lt;div class="sourceCode" id="cb11"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb11-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb11-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;log_age &lt;span class="op"&gt;=&lt;/span&gt; np.log(df[&lt;span class="st"&gt;'age'&lt;/span&gt;].values)&lt;/span&gt;
&lt;span id="cb11-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb11-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;log_mass &lt;span class="op"&gt;=&lt;/span&gt; np.log(df[&lt;span class="st"&gt;'mass'&lt;/span&gt;].values)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We turn the taxon names into numeric identifiers and set up &lt;code&gt;shared&lt;/code&gt; containers for &lt;code&gt;log_age&lt;/code&gt; and &lt;code&gt;taxon_id&lt;/code&gt;. These &lt;code&gt;shared&lt;/code&gt; containers are &lt;a href="https://github.com/pymc-devs/aesara"&gt;&lt;code&gt;aesara&lt;/code&gt;&lt;/a&gt;’s way to facilitate &lt;a href="https://en.wikipedia.org/wiki/Posterior_predictive_distribution"&gt;posterior predictive&lt;/a&gt; sampling. &lt;code&gt;aesara&lt;/code&gt; is the PyMC team’s fork of &lt;a href="https://github.com/Theano/Theano"&gt;&lt;code&gt;theano&lt;/code&gt;&lt;/a&gt;. Since active development on &lt;code&gt;theano&lt;/code&gt; has ceased, &lt;code&gt;pymc3&lt;/code&gt; now uses &lt;code&gt;aesara&lt;/code&gt; for tensor calculations.&lt;/p&gt;
&lt;div class="sourceCode" id="cb12"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb12-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb12-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;taxon_id, taxon_map &lt;span class="op"&gt;=&lt;/span&gt; df[&lt;span class="st"&gt;'taxon'&lt;/span&gt;].factorize(sort&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb12-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb12-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_taxon &lt;span class="op"&gt;=&lt;/span&gt; taxon_map.size&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb13"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb13-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb13-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;taxon_id_ &lt;span class="op"&gt;=&lt;/span&gt; shared(taxon_id)&lt;/span&gt;
&lt;span id="cb13-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb13-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;log_age_ &lt;span class="op"&gt;=&lt;/span&gt; shared(log_age)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Given the second observation above, we will actually specify one model per taxon (hence the adjective “unpooled”). This model has regression coefficients&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    a_j &amp;amp; \sim N(0, 2.5^2) \\
    b_j &amp;amp; \sim N(0, 2.5^2).
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb14"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb14-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb14-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; loglin_model:&lt;/span&gt;
&lt;span id="cb14-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb14-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    a &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"a"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;n_taxon)&lt;/span&gt;
&lt;span id="cb14-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb14-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    b &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"b"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;n_taxon)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that these prior differs differ slightly (in their variance) from those in the &lt;em&gt;BSM&lt;/em&gt;. Nevertheless, the results will be quite similar. With the prior on &lt;span class="math inline"&gt;\(\sigma_j \sim N(0, 2.5^2)\)&lt;/span&gt;, we can finish specifying the model in code.&lt;/p&gt;
&lt;div class="sourceCode" id="cb15"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb15-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb15-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; loglin_model:&lt;/span&gt;
&lt;span id="cb15-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb15-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"σ"&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;n_taxon)&lt;/span&gt;
&lt;span id="cb15-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb15-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; a[taxon_id_] &lt;span class="op"&gt;+&lt;/span&gt; b[taxon_id_] &lt;span class="op"&gt;*&lt;/span&gt; log_age_ &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="fl"&gt;0.5&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; σ[taxon_id_]&lt;span class="op"&gt;**&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb15-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb15-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb15-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"obs"&lt;/span&gt;, μ, σ[taxon_id_], observed&lt;span class="op"&gt;=&lt;/span&gt;log_mass)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now sample from the posterior distribution of the model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb16"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb16-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb16-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;CHAINS &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb16-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;DRAWS &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;2000&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb16-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SEED &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;12345&lt;/span&gt; &lt;span class="co"&gt;# for reproducibility&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb16-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb16-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb16-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SAMPLE_KWARGS &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb16-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb16-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'cores'&lt;/span&gt;: CHAINS,&lt;/span&gt;
&lt;span id="cb16-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb16-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'draws'&lt;/span&gt;: DRAWS,&lt;/span&gt;
&lt;span id="cb16-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb16-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'random_seed'&lt;/span&gt;: [SEED &lt;span class="op"&gt;+&lt;/span&gt; i &lt;span class="cf"&gt;for&lt;/span&gt; i &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;range&lt;/span&gt;(CHAINS)],&lt;/span&gt;
&lt;span id="cb16-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb16-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'return_inferencedata'&lt;/span&gt;: &lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb16-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb16-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'target_accept'&lt;/span&gt;: &lt;span class="fl"&gt;0.995&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb16-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb17"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb17-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb17-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; loglin_model:&lt;/span&gt;
&lt;span id="cb17-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb17-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    loglin_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [σ, b, a]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="9000" class max="9000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [9000/9000 03:15&amp;lt;00:00 Sampling 3 chains, 0 divergences]&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Sampling 3 chains for 1_000 tune and 2_000 draw iterations (3_000 + 6_000 draws total) took 198 seconds.
The number of effective samples is smaller than 25% for some parameters.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To check that there is no obvious problem with our samples we check the energy plot, Bayesian fraction of missing information (BFMI), and &lt;a href="https://blog.stata.com/2016/05/26/gelman-rubin-convergence-diagnostic-using-multiple-chains/"&gt;Gelman-Rubin statistics&lt;/a&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb20"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb20-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb20-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_energy(loglin_trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/tyrannosaurid/Growth%20Curves%20REPARAM_29_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Since the marginal and transitional energy distributions are similar and each BFMI is greater than 0.2, these diagnostics show no obvious issues.&lt;/p&gt;
&lt;div class="sourceCode" id="cb21"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb21-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb21-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.rhat(loglin_trace).&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;svg style="position: absolute; width: 0; height: 0; overflow: hidden"&gt;
&lt;defs&gt; &lt;symbol id="icon-database" viewbox="0 0 32 32"&gt; &lt;path d="M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z"&gt;&lt;/path&gt; &lt;path d="M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;path d="M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;symbol id="icon-file-text2" viewbox="0 0 32 32"&gt; &lt;path d="M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z"&gt;&lt;/path&gt; &lt;path d="M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;/defs&gt;
&lt;/svg&gt;
&lt;style&gt;/* CSS stylesheet for displaying xarray objects in jupyterlab.
 *
 */

:root {
  --xr-font-color0: var(--jp-content-font-color0, rgba(0, 0, 0, 1));
  --xr-font-color2: var(--jp-content-font-color2, rgba(0, 0, 0, 0.54));
  --xr-font-color3: var(--jp-content-font-color3, rgba(0, 0, 0, 0.38));
  --xr-border-color: var(--jp-border-color2, #e0e0e0);
  --xr-disabled-color: var(--jp-layout-color3, #bdbdbd);
  --xr-background-color: var(--jp-layout-color0, white);
  --xr-background-color-row-even: var(--jp-layout-color1, white);
  --xr-background-color-row-odd: var(--jp-layout-color2, #eeeeee);
}

html[theme=dark],
body.vscode-dark {
  --xr-font-color0: rgba(255, 255, 255, 1);
  --xr-font-color2: rgba(255, 255, 255, 0.54);
  --xr-font-color3: rgba(255, 255, 255, 0.38);
  --xr-border-color: #1F1F1F;
  --xr-disabled-color: #515151;
  --xr-background-color: #111111;
  --xr-background-color-row-even: #111111;
  --xr-background-color-row-odd: #313131;
}

.xr-wrap {
  display: block;
  min-width: 300px;
  max-width: 700px;
}

.xr-text-repr-fallback {
  /* fallback to plain text repr when CSS is not injected (untrusted notebook) */
  display: none;
}

.xr-header {
  padding-top: 6px;
  padding-bottom: 6px;
  margin-bottom: 4px;
  border-bottom: solid 1px var(--xr-border-color);
}

.xr-header &gt; div,
.xr-header &gt; ul {
  display: inline;
  margin-top: 0;
  margin-bottom: 0;
}

.xr-obj-type,
.xr-array-name {
  margin-left: 2px;
  margin-right: 10px;
}

.xr-obj-type {
  color: var(--xr-font-color2);
}

.xr-sections {
  padding-left: 0 !important;
  display: grid;
  grid-template-columns: 150px auto auto 1fr 20px 20px;
}

.xr-section-item {
  display: contents;
}

.xr-section-item input {
  display: none;
}

.xr-section-item input + label {
  color: var(--xr-disabled-color);
}

.xr-section-item input:enabled + label {
  cursor: pointer;
  color: var(--xr-font-color2);
}

.xr-section-item input:enabled + label:hover {
  color: var(--xr-font-color0);
}

.xr-section-summary {
  grid-column: 1;
  color: var(--xr-font-color2);
  font-weight: 500;
}

.xr-section-summary &gt; span {
  display: inline-block;
  padding-left: 0.5em;
}

.xr-section-summary-in:disabled + label {
  color: var(--xr-font-color2);
}

.xr-section-summary-in + label:before {
  display: inline-block;
  content: '►';
  font-size: 11px;
  width: 15px;
  text-align: center;
}

.xr-section-summary-in:disabled + label:before {
  color: var(--xr-disabled-color);
}

.xr-section-summary-in:checked + label:before {
  content: '▼';
}

.xr-section-summary-in:checked + label &gt; span {
  display: none;
}

.xr-section-summary,
.xr-section-inline-details {
  padding-top: 4px;
  padding-bottom: 4px;
}

.xr-section-inline-details {
  grid-column: 2 / -1;
}

.xr-section-details {
  display: none;
  grid-column: 1 / -1;
  margin-bottom: 5px;
}

.xr-section-summary-in:checked ~ .xr-section-details {
  display: contents;
}

.xr-array-wrap {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 20px auto;
}

.xr-array-wrap &gt; label {
  grid-column: 1;
  vertical-align: top;
}

.xr-preview {
  color: var(--xr-font-color3);
}

.xr-array-preview,
.xr-array-data {
  padding: 0 5px !important;
  grid-column: 2;
}

.xr-array-data,
.xr-array-in:checked ~ .xr-array-preview {
  display: none;
}

.xr-array-in:checked ~ .xr-array-data,
.xr-array-preview {
  display: inline-block;
}

.xr-dim-list {
  display: inline-block !important;
  list-style: none;
  padding: 0 !important;
  margin: 0;
}

.xr-dim-list li {
  display: inline-block;
  padding: 0;
  margin: 0;
}

.xr-dim-list:before {
  content: '(';
}

.xr-dim-list:after {
  content: ')';
}

.xr-dim-list li:not(:last-child):after {
  content: ',';
  padding-right: 5px;
}

.xr-has-index {
  font-weight: bold;
}

.xr-var-list,
.xr-var-item {
  display: contents;
}

.xr-var-item &gt; div,
.xr-var-item label,
.xr-var-item &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-even);
  margin-bottom: 0;
}

.xr-var-item &gt; .xr-var-name:hover span {
  padding-right: 5px;
}

.xr-var-list &gt; li:nth-child(odd) &gt; div,
.xr-var-list &gt; li:nth-child(odd) &gt; label,
.xr-var-list &gt; li:nth-child(odd) &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-odd);
}

.xr-var-name {
  grid-column: 1;
}

.xr-var-dims {
  grid-column: 2;
}

.xr-var-dtype {
  grid-column: 3;
  text-align: right;
  color: var(--xr-font-color2);
}

.xr-var-preview {
  grid-column: 4;
}

.xr-var-name,
.xr-var-dims,
.xr-var-dtype,
.xr-preview,
.xr-attrs dt {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 10px;
}

.xr-var-name:hover,
.xr-var-dims:hover,
.xr-var-dtype:hover,
.xr-attrs dt:hover {
  overflow: visible;
  width: auto;
  z-index: 1;
}

.xr-var-attrs,
.xr-var-data {
  display: none;
  background-color: var(--xr-background-color) !important;
  padding-bottom: 5px !important;
}

.xr-var-attrs-in:checked ~ .xr-var-attrs,
.xr-var-data-in:checked ~ .xr-var-data {
  display: block;
}

.xr-var-data &gt; table {
  float: right;
}

.xr-var-name span,
.xr-var-data,
.xr-attrs {
  padding-left: 25px !important;
}

.xr-attrs,
.xr-var-attrs,
.xr-var-data {
  grid-column: 1 / -1;
}

dl.xr-attrs {
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 125px auto;
}

.xr-attrs dt,
.xr-attrs dd {
  padding: 0;
  margin: 0;
  float: left;
  padding-right: 10px;
  width: auto;
}

.xr-attrs dt {
  font-weight: normal;
  grid-column: 1;
}

.xr-attrs dt:hover span {
  display: inline-block;
  background: var(--xr-background-color);
  padding-right: 10px;
}

.xr-attrs dd {
  grid-column: 2;
  white-space: pre-wrap;
  word-break: break-all;
}

.xr-icon-database,
.xr-icon-file-text2 {
  display: inline-block;
  vertical-align: middle;
  width: 1em;
  height: 1.5em !important;
  stroke-width: 0;
  stroke: currentColor;
  fill: currentColor;
}
&lt;/style&gt;
&lt;pre class="xr-text-repr-fallback"&gt;&amp;lt;xarray.Dataset&amp;gt;
Dimensions:  ()
Data variables:
    a        float64 1.008
    b        float64 1.006
    σ        float64 1.003&lt;/pre&gt;
&lt;div class="xr-wrap" hidden=""&gt;
&lt;div class="xr-header"&gt;
&lt;div class="xr-obj-type"&gt;
xarray.Dataset
&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="xr-sections"&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-d9e06707-038b-4547-aa09-f1cf96a4318a" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-d9e06707-038b-4547-aa09-f1cf96a4318a" class="xr-section-summary" title="Expand/collapse section"&gt;Dimensions:&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-afd5b947-fc86-488c-993c-ed479c22e3e0" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-afd5b947-fc86-488c-993c-ed479c22e3e0" class="xr-section-summary" title="Expand/collapse section"&gt;Coordinates: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-2eb92c91-1d1d-4091-92a8-510f97f64f02" class="xr-section-summary-in" type="checkbox" checked&gt;&lt;label for="section-2eb92c91-1d1d-4091-92a8-510f97f64f02" class="xr-section-summary"&gt;Data variables: &lt;span&gt;(3)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;a&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.008
&lt;/div&gt;
&lt;input id="attrs-f5a1c8f7-526e-42bf-8395-82c7d65893e0" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-f5a1c8f7-526e-42bf-8395-82c7d65893e0" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-000f63d2-b8b9-4cf2-895a-4975bb34a926" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-000f63d2-b8b9-4cf2-895a-4975bb34a926" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00765472)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;b&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.006
&lt;/div&gt;
&lt;input id="attrs-19ae3b16-7c53-411f-83f0-85927783274e" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-19ae3b16-7c53-411f-83f0-85927783274e" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-aaec7ffc-0f99-49c9-82d0-62f746b4eb58" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-aaec7ffc-0f99-49c9-82d0-62f746b4eb58" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00622094)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;σ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.003
&lt;/div&gt;
&lt;input id="attrs-f0e8ab0c-5ff7-4eb3-9e57-61767b7163d7" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-f0e8ab0c-5ff7-4eb3-9e57-61767b7163d7" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-4b49b11e-b070-47ba-9498-ea18a0051736" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-4b49b11e-b070-47ba-9498-ea18a0051736" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00281897)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-655ba6c6-33eb-47dd-9d60-e57af97dca0b" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-655ba6c6-33eb-47dd-9d60-e57af97dca0b" class="xr-section-summary" title="Expand/collapse section"&gt;Attributes: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The Gelman-Rubin statistics for each parameter are acceptable (smaller than 1.05) as well.&lt;/p&gt;
&lt;p&gt;We now draw samples from the posterior predictive distribution of &lt;span class="math inline"&gt;\(Y\)&lt;/span&gt;. First we build a grid for &lt;span class="math inline"&gt;\(x\)&lt;/span&gt; (&lt;code&gt;pp_log_age&lt;/code&gt;) and &lt;span class="math inline"&gt;\(j\)&lt;/span&gt; (&lt;code&gt;pp_taxon_id&lt;/code&gt;) that span the observed range of these quantities in the data.&lt;/p&gt;
&lt;div class="sourceCode" id="cb22"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb22-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb22-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_log_age &lt;span class="op"&gt;=&lt;/span&gt; np.repeat(np.linspace(&lt;span class="dv"&gt;0&lt;/span&gt;, np.log(&lt;span class="dv"&gt;30&lt;/span&gt;)), n_taxon)&lt;/span&gt;
&lt;span id="cb22-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb22-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_taxon_id &lt;span class="op"&gt;=&lt;/span&gt; np.tile(np.arange(n_taxon), pp_log_age.size &lt;span class="op"&gt;//&lt;/span&gt; n_taxon)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we sample from the posterior predictive distribution.&lt;/p&gt;
&lt;div class="sourceCode" id="cb23"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb23-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb23-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ALPHA &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="fl"&gt;0.05&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb24"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb24-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; get_pp_df(model, trace, alpha&lt;span class="op"&gt;=&lt;/span&gt;ALPHA):&lt;/span&gt;
&lt;span id="cb24-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    taxon_id_.set_value(pp_taxon_id)&lt;/span&gt;
&lt;span id="cb24-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    log_age_.set_value(pp_log_age)&lt;/span&gt;
&lt;span id="cb24-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb24-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;with&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb24-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        pp_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample_posterior_predictive(trace)&lt;/span&gt;
&lt;span id="cb24-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb24-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    taxon_id_.set_value(taxon_id)&lt;/span&gt;
&lt;span id="cb24-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    log_age_.set_value(log_age)&lt;/span&gt;
&lt;span id="cb24-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb24-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; pd.DataFrame({&lt;/span&gt;
&lt;span id="cb24-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'age'&lt;/span&gt;: np.exp(pp_log_age),&lt;/span&gt;
&lt;span id="cb24-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'taxon_id'&lt;/span&gt;: pp_taxon_id,&lt;/span&gt;
&lt;span id="cb24-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'pp_mean'&lt;/span&gt;: np.exp(pp_trace[&lt;span class="st"&gt;'obs'&lt;/span&gt;].mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)),&lt;/span&gt;
&lt;span id="cb24-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'pp_low'&lt;/span&gt;: np.exp(np.percentile(pp_trace[&lt;span class="st"&gt;'obs'&lt;/span&gt;], &lt;span class="dv"&gt;100&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; alpha &lt;span class="op"&gt;/&lt;/span&gt; &lt;span class="fl"&gt;2.&lt;/span&gt;, axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)),&lt;/span&gt;
&lt;span id="cb24-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'pp_high'&lt;/span&gt;: np.exp(np.percentile(pp_trace[&lt;span class="st"&gt;'obs'&lt;/span&gt;], &lt;span class="dv"&gt;100&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; (&lt;span class="dv"&gt;1&lt;/span&gt; &lt;span class="op"&gt;-&lt;/span&gt; alpha &lt;span class="op"&gt;/&lt;/span&gt; &lt;span class="fl"&gt;2.&lt;/span&gt;), axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb24-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb24-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    })&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note the lines in &lt;code&gt;get_pp_df&lt;/code&gt; where we change the values of the &lt;code&gt;shared&lt;/code&gt; variables &lt;code&gt;taxon_id_&lt;/code&gt; and &lt;code&gt;log_age_&lt;/code&gt; to their posterior predictive grid values before sampling and back to the observed values after sampling.&lt;/p&gt;
&lt;div class="sourceCode" id="cb25"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb25-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb25-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_loglin_df &lt;span class="op"&gt;=&lt;/span&gt; get_pp_df(loglin_model, loglin_trace)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="6000" class max="6000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [6000/6000 00:31&amp;lt;00:00]&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb26"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb26-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb26-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_loglin_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
    vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
age
&lt;/th&gt;
&lt;th&gt;
taxon_id
&lt;/th&gt;
&lt;th&gt;
pp_mean
&lt;/th&gt;
&lt;th&gt;
pp_low
&lt;/th&gt;
&lt;th&gt;
pp_high
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
19.767345
&lt;/td&gt;
&lt;td&gt;
7.513964
&lt;/td&gt;
&lt;td&gt;
44.358809
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
3.751587
&lt;/td&gt;
&lt;td&gt;
0.029910
&lt;/td&gt;
&lt;td&gt;
96.423621
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
8.544977
&lt;/td&gt;
&lt;td&gt;
2.598875
&lt;/td&gt;
&lt;td&gt;
22.385467
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
3
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
7.263371
&lt;/td&gt;
&lt;td&gt;
2.957169
&lt;/td&gt;
&lt;td&gt;
17.696855
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
4
&lt;/th&gt;
&lt;td&gt;
1.071878
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
21.720457
&lt;/td&gt;
&lt;td&gt;
8.950703
&lt;/td&gt;
&lt;td&gt;
48.788518
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;Finally, after all of this preparatory work, we get to the payoff and plot the posterior predictive means and intervals for each taxon across our grid.&lt;/p&gt;
&lt;div class="sourceCode" id="cb27"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb27-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; make_posterior_mean_label(name):&lt;/span&gt;
&lt;span id="cb27-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="st"&gt;"Posterior mean"&lt;/span&gt; &lt;span class="cf"&gt;if&lt;/span&gt; name &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt; &lt;span class="cf"&gt;else&lt;/span&gt; &lt;span class="ss"&gt;f"&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="ss"&gt;posterior mean"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb27-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb27-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; make_posterior_interval_label(name):&lt;/span&gt;
&lt;span id="cb27-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="st"&gt;"95&lt;/span&gt;&lt;span class="sc"&gt;% i&lt;/span&gt;&lt;span class="st"&gt;nterval"&lt;/span&gt; &lt;span class="cf"&gt;if&lt;/span&gt; name &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt; &lt;span class="cf"&gt;else&lt;/span&gt; &lt;span class="ss"&gt;f"&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="ss"&gt;95% interval"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb27-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb27-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; plot_taxon_posterior(taxon, df, pp_df,&lt;/span&gt;
&lt;span id="cb27-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         name&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, plot_data&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb27-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         legend&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb27-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; ax &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb27-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb27-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb27-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.fill_between(pp_df[&lt;span class="st"&gt;'age'&lt;/span&gt;], pp_df[&lt;span class="st"&gt;'pp_low'&lt;/span&gt;], pp_df[&lt;span class="st"&gt;'pp_high'&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb27-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.25&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;make_posterior_interval_label(name))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb27-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    pp_df.plot(&lt;span class="st"&gt;'age'&lt;/span&gt;, &lt;span class="st"&gt;'pp_mean'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;make_posterior_mean_label(name), ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;/span&gt;
&lt;span id="cb27-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb27-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; plot_data:&lt;/span&gt;
&lt;span id="cb27-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        df.plot.scatter(&lt;span class="st"&gt;'age'&lt;/span&gt;, &lt;span class="st"&gt;'mass'&lt;/span&gt;, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Data"&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;/span&gt;
&lt;span id="cb27-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb27-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_title(taxon)&lt;/span&gt;
&lt;span id="cb27-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb27-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; legend:&lt;/span&gt;
&lt;span id="cb27-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb27-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb27-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ax.get_legend().remove()&lt;/span&gt;
&lt;span id="cb27-26"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb27-27"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb27-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; ax&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb28"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb28-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb28-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;FIGSIZE &lt;span class="op"&gt;=&lt;/span&gt; (&lt;span class="dv"&gt;12&lt;/span&gt;, &lt;span class="dv"&gt;9&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb29"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb29-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; plot_pp_by_taxon(pp_df,&lt;/span&gt;
&lt;span id="cb29-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     name&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, plot_data&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb29-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     fig&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, axes&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, figsize&lt;span class="op"&gt;=&lt;/span&gt;FIGSIZE):&lt;/span&gt;
&lt;span id="cb29-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; fig &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt; &lt;span class="kw"&gt;or&lt;/span&gt; axes &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb29-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(nrows&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, figsize&lt;span class="op"&gt;=&lt;/span&gt;figsize)&lt;/span&gt;
&lt;span id="cb29-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;for&lt;/span&gt; plt_taxon_id, ax &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;enumerate&lt;/span&gt;(axes.flatten()):&lt;/span&gt;
&lt;span id="cb29-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        taxon &lt;span class="op"&gt;=&lt;/span&gt; taxon_map[plt_taxon_id]&lt;/span&gt;
&lt;span id="cb29-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        taxon_df &lt;span class="op"&gt;=&lt;/span&gt; df[taxon_id &lt;span class="op"&gt;==&lt;/span&gt; plt_taxon_id]&lt;/span&gt;
&lt;span id="cb29-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        taxon_pp_df &lt;span class="op"&gt;=&lt;/span&gt; pp_df[pp_df[&lt;span class="st"&gt;'taxon_id'&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; plt_taxon_id]&lt;/span&gt;
&lt;span id="cb29-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        plot_taxon_posterior(taxon, taxon_df, taxon_pp_df,&lt;/span&gt;
&lt;span id="cb29-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                             name&lt;span class="op"&gt;=&lt;/span&gt;name, plot_data&lt;span class="op"&gt;=&lt;/span&gt;plot_data,&lt;/span&gt;
&lt;span id="cb29-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                             legend&lt;span class="op"&gt;=&lt;/span&gt;(plt_taxon_id &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;), ax&lt;span class="op"&gt;=&lt;/span&gt;ax)&lt;/span&gt;
&lt;span id="cb29-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ax.set_xlim(right&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;30&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb29-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ax.set_ylim(top&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;6000&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb29-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb29-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb29-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; fig, axes&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb30"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb30-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb30-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_pp_by_taxon(pp_loglin_df)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/tyrannosaurid/Growth%20Curves%20REPARAM_44_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Visually comparing these plots to the corresponding ones in the worked JAGS example shows reasonable agreement in spite of our slightly different prior specification.&lt;/p&gt;
&lt;h3 id="pooled-log-linear-model"&gt;Pooled log-linear model&lt;/h3&gt;
&lt;p&gt;It is quite noticeable that in the above posterior predictive plots that the credible intervals are wider for taxa that have fewer data points. In particular there are only three samples of taxon Daspletosaurus. A hierarchical model will allow us to share information from taxa with more observations when inferring the posterior distributions of parameters for taxa with fewer observations. This information sharing leads to the use of the term “pooled” for this type of model. The pooled log linear model still takes the form&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[\log\left(f_j(X)\right) = a_j + b_j \log X,\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;but uses different priors on &lt;span class="math inline"&gt;\(a_j\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(b_j\)&lt;/span&gt;. Conceptually, the pooled model uses the priors&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \mu_a
        &amp;amp; \sim N(0, 2.5^2) \\
    \sigma_a
        &amp;amp; \sim \textrm{HalfNormal}(2.5^2) \\
    a_j
        &amp;amp; \sim N(\mu_a, \sigma_a^2),
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;and similarly for &lt;span class="math inline"&gt;\(b_j\)&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;In reality, this intuitive parameterization can often present &lt;a href="https://twiecki.io/blog/2017/02/08/bayesian-hierchical-non-centered/"&gt;computational challenges&lt;/a&gt;, so we use the following non-centered parameterization instead.&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \mu_a
        &amp;amp; \sim N(0, 2.5^2) \\
    \Delta_{a_j}
        &amp;amp; \sim N(0, 1) \\
    \sigma_a
        &amp;amp; \sim \textrm{HalfNormal}(2.5^2) \\
    a_j
        &amp;amp; = \mu_a + \Delta_{a_j} \cdot \sigma_a.
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb31"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb31-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb31-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; hierarchical_normal(name, shape):&lt;/span&gt;
&lt;span id="cb31-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb31-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="ss"&gt;f"μ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb31-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    Δ &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="ss"&gt;f"Δ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;1.&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;shape)&lt;/span&gt;
&lt;span id="cb31-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb31-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="ss"&gt;f"σ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb31-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb31-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb31-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; pm.Deterministic(name, μ &lt;span class="op"&gt;+&lt;/span&gt; Δ &lt;span class="op"&gt;*&lt;/span&gt; σ)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb32"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb32-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb32-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; pooled_loglin_model:&lt;/span&gt;
&lt;span id="cb32-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb32-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    a &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal(&lt;span class="st"&gt;"a"&lt;/span&gt;, n_taxon)&lt;/span&gt;
&lt;span id="cb32-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb32-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    b &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal(&lt;span class="st"&gt;"b"&lt;/span&gt;, n_taxon)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;To further share information across taxa, we enforce the constraint that the noise parameters are identical across taxa, &lt;span class="math inline"&gt;\(\sigma_1 = \sigma_2 = \sigma_3 = \sigma_4 = \sigma\)&lt;/span&gt;, with the prior &lt;span class="math inline"&gt;\(\sigma \sim \textrm{HalfNormal}(2.5^2)\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb33"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb33-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb33-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pooled_loglin_model:&lt;/span&gt;
&lt;span id="cb33-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb33-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"σ"&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb33-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb33-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; a[taxon_id_] &lt;span class="op"&gt;+&lt;/span&gt; b[taxon_id_] &lt;span class="op"&gt;*&lt;/span&gt; log_age_ &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="fl"&gt;0.5&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; σ&lt;span class="op"&gt;**&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb33-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb33-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb33-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb33-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"obs"&lt;/span&gt;, μ, σ, observed&lt;span class="op"&gt;=&lt;/span&gt;log_mass)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now sample from the pooled log-linear model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb34"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb34-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb34-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pooled_loglin_model:&lt;/span&gt;
&lt;span id="cb34-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb34-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    pooled_loglin_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [σ, σ_b, Δ_b, μ_b, σ_a, Δ_a, μ_a]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="9000" class max="9000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [9000/9000 08:33&amp;lt;00:00 Sampling 3 chains, 0 divergences]&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Sampling 3 chains for 1_000 tune and 2_000 draw iterations (3_000 + 6_000 draws total) took 514 seconds.
The number of effective samples is smaller than 25% for some parameters.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again our diagnostics show no obvious cause for concern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb37"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb37-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb37-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_energy(pooled_loglin_trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/tyrannosaurid/Growth%20Curves%20REPARAM_54_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb38"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb38-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb38-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.rhat(pooled_loglin_trace).&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;svg style="position: absolute; width: 0; height: 0; overflow: hidden"&gt;
&lt;defs&gt; &lt;symbol id="icon-database" viewbox="0 0 32 32"&gt; &lt;path d="M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z"&gt;&lt;/path&gt; &lt;path d="M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;path d="M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;symbol id="icon-file-text2" viewbox="0 0 32 32"&gt; &lt;path d="M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z"&gt;&lt;/path&gt; &lt;path d="M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;/defs&gt;
&lt;/svg&gt;
&lt;style&gt;/* CSS stylesheet for displaying xarray objects in jupyterlab.
 *
 */

:root {
  --xr-font-color0: var(--jp-content-font-color0, rgba(0, 0, 0, 1));
  --xr-font-color2: var(--jp-content-font-color2, rgba(0, 0, 0, 0.54));
  --xr-font-color3: var(--jp-content-font-color3, rgba(0, 0, 0, 0.38));
  --xr-border-color: var(--jp-border-color2, #e0e0e0);
  --xr-disabled-color: var(--jp-layout-color3, #bdbdbd);
  --xr-background-color: var(--jp-layout-color0, white);
  --xr-background-color-row-even: var(--jp-layout-color1, white);
  --xr-background-color-row-odd: var(--jp-layout-color2, #eeeeee);
}

html[theme=dark],
body.vscode-dark {
  --xr-font-color0: rgba(255, 255, 255, 1);
  --xr-font-color2: rgba(255, 255, 255, 0.54);
  --xr-font-color3: rgba(255, 255, 255, 0.38);
  --xr-border-color: #1F1F1F;
  --xr-disabled-color: #515151;
  --xr-background-color: #111111;
  --xr-background-color-row-even: #111111;
  --xr-background-color-row-odd: #313131;
}

.xr-wrap {
  display: block;
  min-width: 300px;
  max-width: 700px;
}

.xr-text-repr-fallback {
  /* fallback to plain text repr when CSS is not injected (untrusted notebook) */
  display: none;
}

.xr-header {
  padding-top: 6px;
  padding-bottom: 6px;
  margin-bottom: 4px;
  border-bottom: solid 1px var(--xr-border-color);
}

.xr-header &gt; div,
.xr-header &gt; ul {
  display: inline;
  margin-top: 0;
  margin-bottom: 0;
}

.xr-obj-type,
.xr-array-name {
  margin-left: 2px;
  margin-right: 10px;
}

.xr-obj-type {
  color: var(--xr-font-color2);
}

.xr-sections {
  padding-left: 0 !important;
  display: grid;
  grid-template-columns: 150px auto auto 1fr 20px 20px;
}

.xr-section-item {
  display: contents;
}

.xr-section-item input {
  display: none;
}

.xr-section-item input + label {
  color: var(--xr-disabled-color);
}

.xr-section-item input:enabled + label {
  cursor: pointer;
  color: var(--xr-font-color2);
}

.xr-section-item input:enabled + label:hover {
  color: var(--xr-font-color0);
}

.xr-section-summary {
  grid-column: 1;
  color: var(--xr-font-color2);
  font-weight: 500;
}

.xr-section-summary &gt; span {
  display: inline-block;
  padding-left: 0.5em;
}

.xr-section-summary-in:disabled + label {
  color: var(--xr-font-color2);
}

.xr-section-summary-in + label:before {
  display: inline-block;
  content: '►';
  font-size: 11px;
  width: 15px;
  text-align: center;
}

.xr-section-summary-in:disabled + label:before {
  color: var(--xr-disabled-color);
}

.xr-section-summary-in:checked + label:before {
  content: '▼';
}

.xr-section-summary-in:checked + label &gt; span {
  display: none;
}

.xr-section-summary,
.xr-section-inline-details {
  padding-top: 4px;
  padding-bottom: 4px;
}

.xr-section-inline-details {
  grid-column: 2 / -1;
}

.xr-section-details {
  display: none;
  grid-column: 1 / -1;
  margin-bottom: 5px;
}

.xr-section-summary-in:checked ~ .xr-section-details {
  display: contents;
}

.xr-array-wrap {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 20px auto;
}

.xr-array-wrap &gt; label {
  grid-column: 1;
  vertical-align: top;
}

.xr-preview {
  color: var(--xr-font-color3);
}

.xr-array-preview,
.xr-array-data {
  padding: 0 5px !important;
  grid-column: 2;
}

.xr-array-data,
.xr-array-in:checked ~ .xr-array-preview {
  display: none;
}

.xr-array-in:checked ~ .xr-array-data,
.xr-array-preview {
  display: inline-block;
}

.xr-dim-list {
  display: inline-block !important;
  list-style: none;
  padding: 0 !important;
  margin: 0;
}

.xr-dim-list li {
  display: inline-block;
  padding: 0;
  margin: 0;
}

.xr-dim-list:before {
  content: '(';
}

.xr-dim-list:after {
  content: ')';
}

.xr-dim-list li:not(:last-child):after {
  content: ',';
  padding-right: 5px;
}

.xr-has-index {
  font-weight: bold;
}

.xr-var-list,
.xr-var-item {
  display: contents;
}

.xr-var-item &gt; div,
.xr-var-item label,
.xr-var-item &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-even);
  margin-bottom: 0;
}

.xr-var-item &gt; .xr-var-name:hover span {
  padding-right: 5px;
}

.xr-var-list &gt; li:nth-child(odd) &gt; div,
.xr-var-list &gt; li:nth-child(odd) &gt; label,
.xr-var-list &gt; li:nth-child(odd) &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-odd);
}

.xr-var-name {
  grid-column: 1;
}

.xr-var-dims {
  grid-column: 2;
}

.xr-var-dtype {
  grid-column: 3;
  text-align: right;
  color: var(--xr-font-color2);
}

.xr-var-preview {
  grid-column: 4;
}

.xr-var-name,
.xr-var-dims,
.xr-var-dtype,
.xr-preview,
.xr-attrs dt {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 10px;
}

.xr-var-name:hover,
.xr-var-dims:hover,
.xr-var-dtype:hover,
.xr-attrs dt:hover {
  overflow: visible;
  width: auto;
  z-index: 1;
}

.xr-var-attrs,
.xr-var-data {
  display: none;
  background-color: var(--xr-background-color) !important;
  padding-bottom: 5px !important;
}

.xr-var-attrs-in:checked ~ .xr-var-attrs,
.xr-var-data-in:checked ~ .xr-var-data {
  display: block;
}

.xr-var-data &gt; table {
  float: right;
}

.xr-var-name span,
.xr-var-data,
.xr-attrs {
  padding-left: 25px !important;
}

.xr-attrs,
.xr-var-attrs,
.xr-var-data {
  grid-column: 1 / -1;
}

dl.xr-attrs {
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 125px auto;
}

.xr-attrs dt,
.xr-attrs dd {
  padding: 0;
  margin: 0;
  float: left;
  padding-right: 10px;
  width: auto;
}

.xr-attrs dt {
  font-weight: normal;
  grid-column: 1;
}

.xr-attrs dt:hover span {
  display: inline-block;
  background: var(--xr-background-color);
  padding-right: 10px;
}

.xr-attrs dd {
  grid-column: 2;
  white-space: pre-wrap;
  word-break: break-all;
}

.xr-icon-database,
.xr-icon-file-text2 {
  display: inline-block;
  vertical-align: middle;
  width: 1em;
  height: 1.5em !important;
  stroke-width: 0;
  stroke: currentColor;
  fill: currentColor;
}
&lt;/style&gt;
&lt;pre class="xr-text-repr-fallback"&gt;&amp;lt;xarray.Dataset&amp;gt;
Dimensions:  ()
Data variables:
    μ_a      float64 1.002
    Δ_a      float64 1.002
    μ_b      float64 1.0
    Δ_b      float64 1.001
    σ_a      float64 1.002
    a        float64 1.002
    σ_b      float64 1.004
    b        float64 1.002
    σ        float64 1.006&lt;/pre&gt;
&lt;div class="xr-wrap" hidden=""&gt;
&lt;div class="xr-header"&gt;
&lt;div class="xr-obj-type"&gt;
xarray.Dataset
&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="xr-sections"&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-3c17eb08-6762-42b7-b4bf-f54bd2a01e36" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-3c17eb08-6762-42b7-b4bf-f54bd2a01e36" class="xr-section-summary" title="Expand/collapse section"&gt;Dimensions:&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-7ed7a115-a843-48eb-986b-a302a247aec5" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-7ed7a115-a843-48eb-986b-a302a247aec5" class="xr-section-summary" title="Expand/collapse section"&gt;Coordinates: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-02f91719-e66f-40a9-b6a0-c00a59519052" class="xr-section-summary-in" type="checkbox" checked&gt;&lt;label for="section-02f91719-e66f-40a9-b6a0-c00a59519052" class="xr-section-summary"&gt;Data variables: &lt;span&gt;(9)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;μ_a&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.002
&lt;/div&gt;
&lt;input id="attrs-783bd763-2207-4a57-8294-36d92c44e147" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-783bd763-2207-4a57-8294-36d92c44e147" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-19bc9785-67c4-4ef1-a549-cc0ffd213b62" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-19bc9785-67c4-4ef1-a549-cc0ffd213b62" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00208566)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;Δ_a&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.002
&lt;/div&gt;
&lt;input id="attrs-460d97b2-4b7a-4506-ba44-7b95f06d5df9" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-460d97b2-4b7a-4506-ba44-7b95f06d5df9" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-3926da15-bc20-4bf7-9726-ded6ad7fa50a" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-3926da15-bc20-4bf7-9726-ded6ad7fa50a" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00184228)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;μ_b&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.0
&lt;/div&gt;
&lt;input id="attrs-3f8fc75d-29b7-4a05-b5a2-40d8c1dac4eb" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-3f8fc75d-29b7-4a05-b5a2-40d8c1dac4eb" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-b890c5ff-8493-4852-81e0-b4653469b4ba" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-b890c5ff-8493-4852-81e0-b4653469b4ba" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00044944)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;Δ_b&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.001
&lt;/div&gt;
&lt;input id="attrs-f223db23-a2da-42be-9a01-c0b4b5ec5580" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-f223db23-a2da-42be-9a01-c0b4b5ec5580" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-a92d9930-694a-4a42-a044-0ec3198c4883" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-a92d9930-694a-4a42-a044-0ec3198c4883" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00108353)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;σ_a&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.002
&lt;/div&gt;
&lt;input id="attrs-dc339d99-92e8-4ab0-8410-8d5bd3527f32" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-dc339d99-92e8-4ab0-8410-8d5bd3527f32" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-f52122f2-9c8c-4c11-84b7-3c237ec81fd1" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-f52122f2-9c8c-4c11-84b7-3c237ec81fd1" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00158498)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;a&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.002
&lt;/div&gt;
&lt;input id="attrs-50777a4c-8978-4b46-b9a0-4f92d1501ba9" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-50777a4c-8978-4b46-b9a0-4f92d1501ba9" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-bd7e1df4-c2d5-44e4-8f27-060756144a85" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-bd7e1df4-c2d5-44e4-8f27-060756144a85" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00175827)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;σ_b&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.004
&lt;/div&gt;
&lt;input id="attrs-d9fb1fd2-cf37-4ec7-9d86-c6f539f6b9f4" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-d9fb1fd2-cf37-4ec7-9d86-c6f539f6b9f4" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-87934b62-deda-4ac4-a3be-a4ea1786548a" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-87934b62-deda-4ac4-a3be-a4ea1786548a" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00390892)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;b&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.002
&lt;/div&gt;
&lt;input id="attrs-d0d5f26f-aa11-4d68-95dd-7238ac72eeef" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-d0d5f26f-aa11-4d68-95dd-7238ac72eeef" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-183e7681-71b9-45fc-9ac4-3912a45cbaf8" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-183e7681-71b9-45fc-9ac4-3912a45cbaf8" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00210233)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;σ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.006
&lt;/div&gt;
&lt;input id="attrs-11b31e7e-8d19-4ff1-8459-a0aa0c70ce9b" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-11b31e7e-8d19-4ff1-8459-a0aa0c70ce9b" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-4b7e5eb5-8ceb-4550-80ac-85208e655e2c" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-4b7e5eb5-8ceb-4550-80ac-85208e655e2c" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00598006)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-4774587e-f5da-493a-9b40-8ae8a707171f" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-4774587e-f5da-493a-9b40-8ae8a707171f" class="xr-section-summary" title="Expand/collapse section"&gt;Attributes: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Again we sample from the posterior predictive distribution of this model and plot the results.&lt;/p&gt;
&lt;div class="sourceCode" id="cb39"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb39-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb39-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_pooled_loglin_df &lt;span class="op"&gt;=&lt;/span&gt; get_pp_df(pooled_loglin_model, pooled_loglin_trace)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="6000" class max="6000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [6000/6000 00:52&amp;lt;00:00]&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb40"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb40-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb40-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_pooled_loglin_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
age
&lt;/th&gt;
&lt;th&gt;
taxon_id
&lt;/th&gt;
&lt;th&gt;
pp_mean
&lt;/th&gt;
&lt;th&gt;
pp_low
&lt;/th&gt;
&lt;th&gt;
pp_high
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
17.405405
&lt;/td&gt;
&lt;td&gt;
9.378821
&lt;/td&gt;
&lt;td&gt;
30.602004
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
9.940230
&lt;/td&gt;
&lt;td&gt;
3.453810
&lt;/td&gt;
&lt;td&gt;
27.524651
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
9.484354
&lt;/td&gt;
&lt;td&gt;
4.619197
&lt;/td&gt;
&lt;td&gt;
18.747739
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
3
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
8.394668
&lt;/td&gt;
&lt;td&gt;
4.823675
&lt;/td&gt;
&lt;td&gt;
15.338217
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
4
&lt;/th&gt;
&lt;td&gt;
1.071878
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
19.095916
&lt;/td&gt;
&lt;td&gt;
10.369680
&lt;/td&gt;
&lt;td&gt;
33.178229
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb41"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb41-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb41-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_pp_by_taxon(pp_pooled_loglin_df)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/tyrannosaurid/Growth%20Curves%20REPARAM_59_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Visually, each of the credible intervals appears smaller than for the unpooled model, espescially for Daspletosaurus. We can overlay the posterior predictive plots for the unpooled and pooled log-linear models to confirm this observation.&lt;/p&gt;
&lt;div class="sourceCode" id="cb42"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb42-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb42-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plot_pp_by_taxon(pp_loglin_df, plot_data&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, name&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Unpooled log-linear"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb42-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb42-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_pp_by_taxon(pp_pooled_loglin_df,&lt;/span&gt;
&lt;span id="cb42-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb42-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 name&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pooled log-linear"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb42-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb42-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 fig&lt;span class="op"&gt;=&lt;/span&gt;fig, axes&lt;span class="op"&gt;=&lt;/span&gt;axes)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/tyrannosaurid/Growth%20Curves%20REPARAM_61_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;h3 id="unpooled-logistic-model"&gt;Unpooled logistic model&lt;/h3&gt;
&lt;p&gt;While the log-linear models are reasonable given our exploratory data analysis above (and produce visually plausible results), they are physically unrealistic. With a log-linear model, as the dinosaur gets older its mass will increase without bound. In reality, living creatures have a maximum lifespan, so the log-linear model may be reasonable for realistic ages. Nevertheless, we can incorporate upper bounds on mass by using a &lt;a href="https://en.wikipedia.org/wiki/Logistic_function"&gt;logistic function&lt;/a&gt; for &lt;span class="math inline"&gt;\(f_j\)&lt;/span&gt;,&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[f_j(x) = a_j + \frac{b_j}{1 + \exp\left(-(x - c_j)\ /\ d_j\right)}\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb43"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb43-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb43-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; logistic(x, a, b, c, d, tensor&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb43-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb43-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    exp &lt;span class="op"&gt;=&lt;/span&gt; at.exp &lt;span class="cf"&gt;if&lt;/span&gt; tensor &lt;span class="cf"&gt;else&lt;/span&gt; np.exp&lt;/span&gt;
&lt;span id="cb43-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb43-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb43-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb43-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; a &lt;span class="op"&gt;+&lt;/span&gt; b &lt;span class="op"&gt;/&lt;/span&gt; (&lt;span class="fl"&gt;1.&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; exp(&lt;span class="op"&gt;-&lt;/span&gt;(x &lt;span class="op"&gt;-&lt;/span&gt; c) &lt;span class="op"&gt;/&lt;/span&gt; d))&lt;/span&gt;
&lt;span id="cb43-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb43-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb43-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb43-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; inv_logistic(y, a, b, c, d, tensor&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb43-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb43-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    log &lt;span class="op"&gt;=&lt;/span&gt; at.log &lt;span class="cf"&gt;if&lt;/span&gt; tensor &lt;span class="cf"&gt;else&lt;/span&gt; np.log&lt;/span&gt;
&lt;span id="cb43-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb43-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb43-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb43-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; c &lt;span class="op"&gt;-&lt;/span&gt; d &lt;span class="op"&gt;*&lt;/span&gt; log(b &lt;span class="op"&gt;/&lt;/span&gt; (y &lt;span class="op"&gt;-&lt;/span&gt; a) &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that &lt;code&gt;logistic&lt;/code&gt; and its inverse function, &lt;code&gt;inv_logistic&lt;/code&gt;, switch between the &lt;code&gt;aesera&lt;/code&gt; and &lt;code&gt;numpy&lt;/code&gt; implementations of &lt;code&gt;exp&lt;/code&gt; and &lt;code&gt;log&lt;/code&gt; depending on the &lt;code&gt;tensor&lt;/code&gt; parameter.&lt;/p&gt;
&lt;div class="sourceCode" id="cb44"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb44-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb44-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb44-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;A, B, C, D &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;5&lt;/span&gt;, &lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb44-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb44-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;f &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;lambda&lt;/span&gt; x: logistic(x, A, B, C, D)&lt;/span&gt;
&lt;span id="cb44-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;f_inv &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;lambda&lt;/span&gt; y: inv_logistic(y, A, B, C, D)&lt;/span&gt;
&lt;span id="cb44-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb44-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;X_MAX &lt;span class="op"&gt;=&lt;/span&gt; f_inv(A &lt;span class="op"&gt;+&lt;/span&gt; B &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="fl"&gt;0.01&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb44-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;logistic_x &lt;span class="op"&gt;=&lt;/span&gt; np.linspace(&lt;span class="dv"&gt;0&lt;/span&gt;, X_MAX)&lt;/span&gt;
&lt;span id="cb44-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb44-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.plot(logistic_x, f(logistic_x))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb44-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb44-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlim(&lt;span class="dv"&gt;0&lt;/span&gt;, X_MAX)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb44-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb44-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yticks([&lt;span class="dv"&gt;0&lt;/span&gt;, f(&lt;span class="dv"&gt;0&lt;/span&gt;), f(&lt;span class="dv"&gt;2&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; X_MAX)])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb44-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_yticklabels([&lt;span class="st"&gt;"0"&lt;/span&gt;, &lt;span class="vs"&gt;r"$f(0)$"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb44-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    &lt;span class="vs"&gt;r"$\lim_{x \to \infty}\ f(x)$"&lt;/span&gt;])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb44-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb44-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb44-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="ss"&gt;f"Logistic function $f$ with&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="ss"&gt;$a =$&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;A&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;, $b =$&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;B&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;, $c =$&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;C&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;, $d =$&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;D&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/tyrannosaurid/Growth%20Curves%20REPARAM_66_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We require &lt;span class="math inline"&gt;\(a, b, d &amp;gt; 0\)&lt;/span&gt;, so we set&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    a_j
        &amp;amp; = \exp \alpha_j \\
    b_j
        &amp;amp; = \exp \beta_j \\
    d_j
        &amp;amp; = \exp \delta_j.
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For the unpooled logistic model we use &lt;span class="math inline"&gt;\(\alpha_j \sim N(0, 2.5^2)\)&lt;/span&gt; and similarly for &lt;span class="math inline"&gt;\(\beta_j\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(\delta_j\)&lt;/span&gt;. We use the same prior for &lt;span class="math inline"&gt;\(c_j\)&lt;/span&gt; as in the unpooled log-linear model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb45"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb45-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb45-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; logistic_model:&lt;/span&gt;
&lt;span id="cb45-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb45-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    α &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"α"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;n_taxon)&lt;/span&gt;
&lt;span id="cb45-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb45-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    a &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;span class="st"&gt;"a"&lt;/span&gt;, at.exp(α))&lt;/span&gt;
&lt;span id="cb45-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb45-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb45-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb45-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"β"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;n_taxon)&lt;/span&gt;
&lt;span id="cb45-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb45-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    b &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;span class="st"&gt;"b"&lt;/span&gt;, at.exp(β))&lt;/span&gt;
&lt;span id="cb45-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb45-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb45-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb45-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    c &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"c"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;n_taxon)&lt;/span&gt;
&lt;span id="cb45-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb45-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb45-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb45-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    δ &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"δ"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;n_taxon)&lt;/span&gt;
&lt;span id="cb45-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb45-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    d &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;span class="st"&gt;"d"&lt;/span&gt;, at.exp(δ))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The noise variance is also the same as in the unpooled log-linear model. The likelihood is quite similar as well.&lt;/p&gt;
&lt;div class="sourceCode" id="cb46"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb46-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb46-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; logistic_model:&lt;/span&gt;
&lt;span id="cb46-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb46-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"σ"&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;n_taxon)&lt;/span&gt;
&lt;span id="cb46-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb46-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; at.log(&lt;/span&gt;
&lt;span id="cb46-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb46-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            logistic(log_age_,&lt;/span&gt;
&lt;span id="cb46-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb46-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     a[taxon_id_], b[taxon_id_], c[taxon_id_], d[taxon_id_],&lt;/span&gt;
&lt;span id="cb46-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb46-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     tensor&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb46-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb46-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ) &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="fl"&gt;0.5&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; σ[taxon_id_]&lt;span class="op"&gt;**&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb46-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb46-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb46-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb46-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"obs"&lt;/span&gt;, μ, σ[taxon_id_], observed&lt;span class="op"&gt;=&lt;/span&gt;log_mass)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now sample from the unpooled logistic model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb47"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb47-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb47-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; logistic_model:&lt;/span&gt;
&lt;span id="cb47-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb47-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    logistic_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [σ, δ, c, β, α]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="9000" class max="9000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [9000/9000 09:42&amp;lt;00:00 Sampling 3 chains, 13 divergences]&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Sampling 3 chains for 1_000 tune and 2_000 draw iterations (3_000 + 6_000 draws total) took 583 seconds.
There were 2 divergences after tuning. Increase `target_accept` or reparameterize.
The chain reached the maximum tree depth. Increase max_treedepth, increase target_accept or reparameterize.
There were 6 divergences after tuning. Increase `target_accept` or reparameterize.
There were 5 divergences after tuning. Increase `target_accept` or reparameterize.
The estimated number of effective samples is smaller than 200 for some parameters.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again our diagnostics show no obvious cause for concern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb50"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb50-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb50-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_energy(logistic_trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/tyrannosaurid/Growth%20Curves%20REPARAM_74_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb51"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb51-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb51-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.rhat(logistic_trace).&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;svg style="position: absolute; width: 0; height: 0; overflow: hidden"&gt;
&lt;defs&gt; &lt;symbol id="icon-database" viewbox="0 0 32 32"&gt; &lt;path d="M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z"&gt;&lt;/path&gt; &lt;path d="M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;path d="M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;symbol id="icon-file-text2" viewbox="0 0 32 32"&gt; &lt;path d="M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z"&gt;&lt;/path&gt; &lt;path d="M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;/defs&gt;
&lt;/svg&gt;
&lt;style&gt;/* CSS stylesheet for displaying xarray objects in jupyterlab.
 *
 */

:root {
  --xr-font-color0: var(--jp-content-font-color0, rgba(0, 0, 0, 1));
  --xr-font-color2: var(--jp-content-font-color2, rgba(0, 0, 0, 0.54));
  --xr-font-color3: var(--jp-content-font-color3, rgba(0, 0, 0, 0.38));
  --xr-border-color: var(--jp-border-color2, #e0e0e0);
  --xr-disabled-color: var(--jp-layout-color3, #bdbdbd);
  --xr-background-color: var(--jp-layout-color0, white);
  --xr-background-color-row-even: var(--jp-layout-color1, white);
  --xr-background-color-row-odd: var(--jp-layout-color2, #eeeeee);
}

html[theme=dark],
body.vscode-dark {
  --xr-font-color0: rgba(255, 255, 255, 1);
  --xr-font-color2: rgba(255, 255, 255, 0.54);
  --xr-font-color3: rgba(255, 255, 255, 0.38);
  --xr-border-color: #1F1F1F;
  --xr-disabled-color: #515151;
  --xr-background-color: #111111;
  --xr-background-color-row-even: #111111;
  --xr-background-color-row-odd: #313131;
}

.xr-wrap {
  display: block;
  min-width: 300px;
  max-width: 700px;
}

.xr-text-repr-fallback {
  /* fallback to plain text repr when CSS is not injected (untrusted notebook) */
  display: none;
}

.xr-header {
  padding-top: 6px;
  padding-bottom: 6px;
  margin-bottom: 4px;
  border-bottom: solid 1px var(--xr-border-color);
}

.xr-header &gt; div,
.xr-header &gt; ul {
  display: inline;
  margin-top: 0;
  margin-bottom: 0;
}

.xr-obj-type,
.xr-array-name {
  margin-left: 2px;
  margin-right: 10px;
}

.xr-obj-type {
  color: var(--xr-font-color2);
}

.xr-sections {
  padding-left: 0 !important;
  display: grid;
  grid-template-columns: 150px auto auto 1fr 20px 20px;
}

.xr-section-item {
  display: contents;
}

.xr-section-item input {
  display: none;
}

.xr-section-item input + label {
  color: var(--xr-disabled-color);
}

.xr-section-item input:enabled + label {
  cursor: pointer;
  color: var(--xr-font-color2);
}

.xr-section-item input:enabled + label:hover {
  color: var(--xr-font-color0);
}

.xr-section-summary {
  grid-column: 1;
  color: var(--xr-font-color2);
  font-weight: 500;
}

.xr-section-summary &gt; span {
  display: inline-block;
  padding-left: 0.5em;
}

.xr-section-summary-in:disabled + label {
  color: var(--xr-font-color2);
}

.xr-section-summary-in + label:before {
  display: inline-block;
  content: '►';
  font-size: 11px;
  width: 15px;
  text-align: center;
}

.xr-section-summary-in:disabled + label:before {
  color: var(--xr-disabled-color);
}

.xr-section-summary-in:checked + label:before {
  content: '▼';
}

.xr-section-summary-in:checked + label &gt; span {
  display: none;
}

.xr-section-summary,
.xr-section-inline-details {
  padding-top: 4px;
  padding-bottom: 4px;
}

.xr-section-inline-details {
  grid-column: 2 / -1;
}

.xr-section-details {
  display: none;
  grid-column: 1 / -1;
  margin-bottom: 5px;
}

.xr-section-summary-in:checked ~ .xr-section-details {
  display: contents;
}

.xr-array-wrap {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 20px auto;
}

.xr-array-wrap &gt; label {
  grid-column: 1;
  vertical-align: top;
}

.xr-preview {
  color: var(--xr-font-color3);
}

.xr-array-preview,
.xr-array-data {
  padding: 0 5px !important;
  grid-column: 2;
}

.xr-array-data,
.xr-array-in:checked ~ .xr-array-preview {
  display: none;
}

.xr-array-in:checked ~ .xr-array-data,
.xr-array-preview {
  display: inline-block;
}

.xr-dim-list {
  display: inline-block !important;
  list-style: none;
  padding: 0 !important;
  margin: 0;
}

.xr-dim-list li {
  display: inline-block;
  padding: 0;
  margin: 0;
}

.xr-dim-list:before {
  content: '(';
}

.xr-dim-list:after {
  content: ')';
}

.xr-dim-list li:not(:last-child):after {
  content: ',';
  padding-right: 5px;
}

.xr-has-index {
  font-weight: bold;
}

.xr-var-list,
.xr-var-item {
  display: contents;
}

.xr-var-item &gt; div,
.xr-var-item label,
.xr-var-item &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-even);
  margin-bottom: 0;
}

.xr-var-item &gt; .xr-var-name:hover span {
  padding-right: 5px;
}

.xr-var-list &gt; li:nth-child(odd) &gt; div,
.xr-var-list &gt; li:nth-child(odd) &gt; label,
.xr-var-list &gt; li:nth-child(odd) &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-odd);
}

.xr-var-name {
  grid-column: 1;
}

.xr-var-dims {
  grid-column: 2;
}

.xr-var-dtype {
  grid-column: 3;
  text-align: right;
  color: var(--xr-font-color2);
}

.xr-var-preview {
  grid-column: 4;
}

.xr-var-name,
.xr-var-dims,
.xr-var-dtype,
.xr-preview,
.xr-attrs dt {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 10px;
}

.xr-var-name:hover,
.xr-var-dims:hover,
.xr-var-dtype:hover,
.xr-attrs dt:hover {
  overflow: visible;
  width: auto;
  z-index: 1;
}

.xr-var-attrs,
.xr-var-data {
  display: none;
  background-color: var(--xr-background-color) !important;
  padding-bottom: 5px !important;
}

.xr-var-attrs-in:checked ~ .xr-var-attrs,
.xr-var-data-in:checked ~ .xr-var-data {
  display: block;
}

.xr-var-data &gt; table {
  float: right;
}

.xr-var-name span,
.xr-var-data,
.xr-attrs {
  padding-left: 25px !important;
}

.xr-attrs,
.xr-var-attrs,
.xr-var-data {
  grid-column: 1 / -1;
}

dl.xr-attrs {
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 125px auto;
}

.xr-attrs dt,
.xr-attrs dd {
  padding: 0;
  margin: 0;
  float: left;
  padding-right: 10px;
  width: auto;
}

.xr-attrs dt {
  font-weight: normal;
  grid-column: 1;
}

.xr-attrs dt:hover span {
  display: inline-block;
  background: var(--xr-background-color);
  padding-right: 10px;
}

.xr-attrs dd {
  grid-column: 2;
  white-space: pre-wrap;
  word-break: break-all;
}

.xr-icon-database,
.xr-icon-file-text2 {
  display: inline-block;
  vertical-align: middle;
  width: 1em;
  height: 1.5em !important;
  stroke-width: 0;
  stroke: currentColor;
  fill: currentColor;
}
&lt;/style&gt;
&lt;pre class="xr-text-repr-fallback"&gt;&amp;lt;xarray.Dataset&amp;gt;
Dimensions:  ()
Data variables:
    α        float64 1.017
    β        float64 1.02
    c        float64 1.008
    δ        float64 1.008
    a        float64 1.017
    b        float64 1.02
    d        float64 1.014
    σ        float64 1.024&lt;/pre&gt;
&lt;div class="xr-wrap" hidden=""&gt;
&lt;div class="xr-header"&gt;
&lt;div class="xr-obj-type"&gt;
xarray.Dataset
&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="xr-sections"&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-92c50d4a-3728-4dee-b86d-921f41e51842" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-92c50d4a-3728-4dee-b86d-921f41e51842" class="xr-section-summary" title="Expand/collapse section"&gt;Dimensions:&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-ee762fa9-244c-4fa3-bf51-f9dff5859490" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-ee762fa9-244c-4fa3-bf51-f9dff5859490" class="xr-section-summary" title="Expand/collapse section"&gt;Coordinates: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-0d5788e1-87ff-4357-91b2-461f8875535f" class="xr-section-summary-in" type="checkbox" checked&gt;&lt;label for="section-0d5788e1-87ff-4357-91b2-461f8875535f" class="xr-section-summary"&gt;Data variables: &lt;span&gt;(8)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;α&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.017
&lt;/div&gt;
&lt;input id="attrs-11f895d9-4163-4cb1-91fe-987574607f7d" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-11f895d9-4163-4cb1-91fe-987574607f7d" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-9dcf24f0-8bca-423b-9892-e5eef76284d6" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-9dcf24f0-8bca-423b-9892-e5eef76284d6" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.01676666)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;β&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.02
&lt;/div&gt;
&lt;input id="attrs-81740fa3-db8e-43bc-a4df-8492a06cc820" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-81740fa3-db8e-43bc-a4df-8492a06cc820" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-a6cceae8-c040-4867-a643-1f1f71d8c1f2" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-a6cceae8-c040-4867-a643-1f1f71d8c1f2" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.02040336)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;c&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.008
&lt;/div&gt;
&lt;input id="attrs-5e574fb1-167c-4e84-8203-2ff3cc638e12" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-5e574fb1-167c-4e84-8203-2ff3cc638e12" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-426c8dce-acc8-4b49-a211-e5a91d86ba47" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-426c8dce-acc8-4b49-a211-e5a91d86ba47" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00824226)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;δ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.008
&lt;/div&gt;
&lt;input id="attrs-9ba65b39-e61f-4d4b-a8b1-78a641e35086" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-9ba65b39-e61f-4d4b-a8b1-78a641e35086" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-157aad48-b087-4105-911b-516ba3736928" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-157aad48-b087-4105-911b-516ba3736928" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.00846537)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;a&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.017
&lt;/div&gt;
&lt;input id="attrs-898ea623-045b-4a7a-8ba2-d0f8b97cf0a3" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-898ea623-045b-4a7a-8ba2-d0f8b97cf0a3" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-7c6aef96-11d7-4700-bba2-56ff5edee482" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-7c6aef96-11d7-4700-bba2-56ff5edee482" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.01676666)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;b&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.02
&lt;/div&gt;
&lt;input id="attrs-ddaf7588-9c9d-4a94-9894-35483ed94ff6" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-ddaf7588-9c9d-4a94-9894-35483ed94ff6" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-fdd8c4db-f232-4717-92e1-103fe5ba4671" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-fdd8c4db-f232-4717-92e1-103fe5ba4671" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.02040336)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;d&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.014
&lt;/div&gt;
&lt;input id="attrs-7de4b5e7-bddc-4a89-b74a-64c7a7212f7b" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-7de4b5e7-bddc-4a89-b74a-64c7a7212f7b" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-a991c9fa-9195-423f-add5-ae5d7b421e34" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-a991c9fa-9195-423f-add5-ae5d7b421e34" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.0135121)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-var-item"&gt;
&lt;div class="xr-var-name"&gt;
&lt;span&gt;σ&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-var-dims"&gt;
()
&lt;/div&gt;
&lt;div class="xr-var-dtype"&gt;
float64
&lt;/div&gt;
&lt;div class="xr-var-preview xr-preview"&gt;
1.024
&lt;/div&gt;
&lt;input id="attrs-0a712318-2f17-44a5-a643-cb8942b0a1b1" class="xr-var-attrs-in" type="checkbox" disabled&gt;&lt;label for="attrs-0a712318-2f17-44a5-a643-cb8942b0a1b1" title="Show/Hide attributes"&gt;&lt;svg class="icon xr-icon-file-text2"&gt;&lt;use xlink:href="#icon-file-text2"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;&lt;input id="data-8f1c2c9e-03d9-408f-8776-8045ec4ba97f" class="xr-var-data-in" type="checkbox"&gt;&lt;label for="data-8f1c2c9e-03d9-408f-8776-8045ec4ba97f" title="Show/Hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-var-attrs"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;div class="xr-var-data"&gt;
&lt;pre&gt;array(1.02389979)&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-ef8739ea-5e98-491a-8e5a-4c949f786e7e" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-ef8739ea-5e98-491a-8e5a-4c949f786e7e" class="xr-section-summary" title="Expand/collapse section"&gt;Attributes: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Again we sample from the posterior predictive distribution of this model and plot the results.&lt;/p&gt;
&lt;div class="sourceCode" id="cb52"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb52-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb52-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_logistic_df &lt;span class="op"&gt;=&lt;/span&gt; get_pp_df(logistic_model, logistic_trace)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="6000" class max="6000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [6000/6000 00:35&amp;lt;00:00]&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb53"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb53-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb53-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_logistic_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
age
&lt;/th&gt;
&lt;th&gt;
taxon_id
&lt;/th&gt;
&lt;th&gt;
pp_mean
&lt;/th&gt;
&lt;th&gt;
pp_low
&lt;/th&gt;
&lt;th&gt;
pp_high
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
20.229437
&lt;/td&gt;
&lt;td&gt;
0.655100
&lt;/td&gt;
&lt;td&gt;
809.706349
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
372.903045
&lt;/td&gt;
&lt;td&gt;
0.370631
&lt;/td&gt;
&lt;td&gt;
5551.674728
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
60.408886
&lt;/td&gt;
&lt;td&gt;
0.477719
&lt;/td&gt;
&lt;td&gt;
1983.882017
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
3
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
11.421099
&lt;/td&gt;
&lt;td&gt;
1.119319
&lt;/td&gt;
&lt;td&gt;
53.975799
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
4
&lt;/th&gt;
&lt;td&gt;
1.071878
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
21.909702
&lt;/td&gt;
&lt;td&gt;
0.812396
&lt;/td&gt;
&lt;td&gt;
642.989663
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb54"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb54-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb54-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plot_pp_by_taxon(pp_loglin_df, name&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Unpooled log-linear"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb54-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb54-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_pp_by_taxon(pp_logistic_df,&lt;/span&gt;
&lt;span id="cb54-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb54-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 name&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Unpooled logistic"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb54-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb54-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 fig&lt;span class="op"&gt;=&lt;/span&gt;fig, axes&lt;span class="op"&gt;=&lt;/span&gt;axes)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/tyrannosaurid/Growth%20Curves%20REPARAM_79_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Interestingly, the posterior predictive mean for Daspletosaurus doesn’t seem to fit the observed data as well as the log-linear model, and the credible intervals are quite wide. This observation makes sense given that the logistic model has twice as many parameters, but the number of observations has remained the same.&lt;/p&gt;
&lt;h3 id="pooled-logistic"&gt;Pooled logistic&lt;/h3&gt;
&lt;p&gt;We can once again share information across taxa by specifying a pooled logistic model. This model places hierarchical normal priors on &lt;span class="math inline"&gt;\(\alpha\)&lt;/span&gt;, &lt;span class="math inline"&gt;\(\beta\)&lt;/span&gt;, &lt;span class="math inline"&gt;\(c\)&lt;/span&gt;, and &lt;span class="math inline"&gt;\(\delta\)&lt;/span&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb55"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb55-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb55-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; pooled_logistic_model:&lt;/span&gt;
&lt;span id="cb55-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb55-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    α &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal(&lt;span class="st"&gt;"α"&lt;/span&gt;, n_taxon)&lt;/span&gt;
&lt;span id="cb55-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb55-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    a &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;span class="st"&gt;"a"&lt;/span&gt;, at.exp(α))&lt;/span&gt;
&lt;span id="cb55-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb55-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb55-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb55-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal(&lt;span class="st"&gt;"β"&lt;/span&gt;, n_taxon)&lt;/span&gt;
&lt;span id="cb55-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb55-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    b &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;span class="st"&gt;"b"&lt;/span&gt;, at.exp(β))&lt;/span&gt;
&lt;span id="cb55-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb55-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb55-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb55-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    c &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal(&lt;span class="st"&gt;"c"&lt;/span&gt;, n_taxon)&lt;/span&gt;
&lt;span id="cb55-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb55-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb55-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb55-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    δ &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal(&lt;span class="st"&gt;"δ"&lt;/span&gt;, n_taxon)&lt;/span&gt;
&lt;span id="cb55-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb55-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    d &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;span class="st"&gt;"d"&lt;/span&gt;, at.exp(δ))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The noise variance and likelihood are similar to those of the unpooled logistic model, except we constrain all taxa to share the same noise variance, &lt;span class="math inline"&gt;\(\sigma\)&lt;/span&gt;, as in the pooled log-linear model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb56"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb56-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb56-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pooled_logistic_model:&lt;/span&gt;
&lt;span id="cb56-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb56-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;"σ"&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb56-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb56-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; at.log(&lt;/span&gt;
&lt;span id="cb56-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb56-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            logistic(log_age_,&lt;/span&gt;
&lt;span id="cb56-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb56-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     a[taxon_id_], b[taxon_id_], c[taxon_id_], d[taxon_id_],&lt;/span&gt;
&lt;span id="cb56-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb56-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                     tensor&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb56-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb56-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ) &lt;span class="op"&gt;-&lt;/span&gt; &lt;span class="fl"&gt;0.5&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; σ&lt;span class="op"&gt;**&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb56-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb56-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb56-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb56-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    obs &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;"obs"&lt;/span&gt;, μ, σ, observed&lt;span class="op"&gt;=&lt;/span&gt;log_mass)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb57"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb57-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb57-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pooled_logistic_model:&lt;/span&gt;
&lt;span id="cb57-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb57-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    pooled_logistic_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [σ, σ_δ, Δ_δ, μ_δ, σ_c, Δ_c, μ_c, σ_β, Δ_β, μ_β, σ_α, Δ_α, μ_α]&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="9000" class max="9000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [9000/9000 19:02&amp;lt;00:00 Sampling 3 chains, 3 divergences]&lt;/p&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Sampling 3 chains for 1_000 tune and 2_000 draw iterations (3_000 + 6_000 draws total) took 1143 seconds.
There were 2 divergences after tuning. Increase `target_accept` or reparameterize.
There was 1 divergence after tuning. Increase `target_accept` or reparameterize.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Again our diagnostics show no obvious cause for concern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb60"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb60-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb60-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_energy(pooled_logistic_trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/tyrannosaurid/Growth%20Curves%20REPARAM_87_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb61"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb61-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb61-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(az.rhat(pooled_logistic_trace[&lt;span class="st"&gt;'posterior'&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb61-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb61-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   .&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;
&lt;span id="cb61-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb61-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   .to_array()&lt;/span&gt;
&lt;span id="cb61-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb61-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   .&lt;span class="bu"&gt;max&lt;/span&gt;())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;svg style="position: absolute; width: 0; height: 0; overflow: hidden"&gt;
&lt;defs&gt; &lt;symbol id="icon-database" viewbox="0 0 32 32"&gt; &lt;path d="M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z"&gt;&lt;/path&gt; &lt;path d="M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;path d="M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;symbol id="icon-file-text2" viewbox="0 0 32 32"&gt; &lt;path d="M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z"&gt;&lt;/path&gt; &lt;path d="M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;path d="M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z"&gt;&lt;/path&gt; &lt;/symbol&gt; &lt;/defs&gt;
&lt;/svg&gt;
&lt;style&gt;/* CSS stylesheet for displaying xarray objects in jupyterlab.
 *
 */

:root {
  --xr-font-color0: var(--jp-content-font-color0, rgba(0, 0, 0, 1));
  --xr-font-color2: var(--jp-content-font-color2, rgba(0, 0, 0, 0.54));
  --xr-font-color3: var(--jp-content-font-color3, rgba(0, 0, 0, 0.38));
  --xr-border-color: var(--jp-border-color2, #e0e0e0);
  --xr-disabled-color: var(--jp-layout-color3, #bdbdbd);
  --xr-background-color: var(--jp-layout-color0, white);
  --xr-background-color-row-even: var(--jp-layout-color1, white);
  --xr-background-color-row-odd: var(--jp-layout-color2, #eeeeee);
}

html[theme=dark],
body.vscode-dark {
  --xr-font-color0: rgba(255, 255, 255, 1);
  --xr-font-color2: rgba(255, 255, 255, 0.54);
  --xr-font-color3: rgba(255, 255, 255, 0.38);
  --xr-border-color: #1F1F1F;
  --xr-disabled-color: #515151;
  --xr-background-color: #111111;
  --xr-background-color-row-even: #111111;
  --xr-background-color-row-odd: #313131;
}

.xr-wrap {
  display: block;
  min-width: 300px;
  max-width: 700px;
}

.xr-text-repr-fallback {
  /* fallback to plain text repr when CSS is not injected (untrusted notebook) */
  display: none;
}

.xr-header {
  padding-top: 6px;
  padding-bottom: 6px;
  margin-bottom: 4px;
  border-bottom: solid 1px var(--xr-border-color);
}

.xr-header &gt; div,
.xr-header &gt; ul {
  display: inline;
  margin-top: 0;
  margin-bottom: 0;
}

.xr-obj-type,
.xr-array-name {
  margin-left: 2px;
  margin-right: 10px;
}

.xr-obj-type {
  color: var(--xr-font-color2);
}

.xr-sections {
  padding-left: 0 !important;
  display: grid;
  grid-template-columns: 150px auto auto 1fr 20px 20px;
}

.xr-section-item {
  display: contents;
}

.xr-section-item input {
  display: none;
}

.xr-section-item input + label {
  color: var(--xr-disabled-color);
}

.xr-section-item input:enabled + label {
  cursor: pointer;
  color: var(--xr-font-color2);
}

.xr-section-item input:enabled + label:hover {
  color: var(--xr-font-color0);
}

.xr-section-summary {
  grid-column: 1;
  color: var(--xr-font-color2);
  font-weight: 500;
}

.xr-section-summary &gt; span {
  display: inline-block;
  padding-left: 0.5em;
}

.xr-section-summary-in:disabled + label {
  color: var(--xr-font-color2);
}

.xr-section-summary-in + label:before {
  display: inline-block;
  content: '►';
  font-size: 11px;
  width: 15px;
  text-align: center;
}

.xr-section-summary-in:disabled + label:before {
  color: var(--xr-disabled-color);
}

.xr-section-summary-in:checked + label:before {
  content: '▼';
}

.xr-section-summary-in:checked + label &gt; span {
  display: none;
}

.xr-section-summary,
.xr-section-inline-details {
  padding-top: 4px;
  padding-bottom: 4px;
}

.xr-section-inline-details {
  grid-column: 2 / -1;
}

.xr-section-details {
  display: none;
  grid-column: 1 / -1;
  margin-bottom: 5px;
}

.xr-section-summary-in:checked ~ .xr-section-details {
  display: contents;
}

.xr-array-wrap {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 20px auto;
}

.xr-array-wrap &gt; label {
  grid-column: 1;
  vertical-align: top;
}

.xr-preview {
  color: var(--xr-font-color3);
}

.xr-array-preview,
.xr-array-data {
  padding: 0 5px !important;
  grid-column: 2;
}

.xr-array-data,
.xr-array-in:checked ~ .xr-array-preview {
  display: none;
}

.xr-array-in:checked ~ .xr-array-data,
.xr-array-preview {
  display: inline-block;
}

.xr-dim-list {
  display: inline-block !important;
  list-style: none;
  padding: 0 !important;
  margin: 0;
}

.xr-dim-list li {
  display: inline-block;
  padding: 0;
  margin: 0;
}

.xr-dim-list:before {
  content: '(';
}

.xr-dim-list:after {
  content: ')';
}

.xr-dim-list li:not(:last-child):after {
  content: ',';
  padding-right: 5px;
}

.xr-has-index {
  font-weight: bold;
}

.xr-var-list,
.xr-var-item {
  display: contents;
}

.xr-var-item &gt; div,
.xr-var-item label,
.xr-var-item &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-even);
  margin-bottom: 0;
}

.xr-var-item &gt; .xr-var-name:hover span {
  padding-right: 5px;
}

.xr-var-list &gt; li:nth-child(odd) &gt; div,
.xr-var-list &gt; li:nth-child(odd) &gt; label,
.xr-var-list &gt; li:nth-child(odd) &gt; .xr-var-name span {
  background-color: var(--xr-background-color-row-odd);
}

.xr-var-name {
  grid-column: 1;
}

.xr-var-dims {
  grid-column: 2;
}

.xr-var-dtype {
  grid-column: 3;
  text-align: right;
  color: var(--xr-font-color2);
}

.xr-var-preview {
  grid-column: 4;
}

.xr-var-name,
.xr-var-dims,
.xr-var-dtype,
.xr-preview,
.xr-attrs dt {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-right: 10px;
}

.xr-var-name:hover,
.xr-var-dims:hover,
.xr-var-dtype:hover,
.xr-attrs dt:hover {
  overflow: visible;
  width: auto;
  z-index: 1;
}

.xr-var-attrs,
.xr-var-data {
  display: none;
  background-color: var(--xr-background-color) !important;
  padding-bottom: 5px !important;
}

.xr-var-attrs-in:checked ~ .xr-var-attrs,
.xr-var-data-in:checked ~ .xr-var-data {
  display: block;
}

.xr-var-data &gt; table {
  float: right;
}

.xr-var-name span,
.xr-var-data,
.xr-attrs {
  padding-left: 25px !important;
}

.xr-attrs,
.xr-var-attrs,
.xr-var-data {
  grid-column: 1 / -1;
}

dl.xr-attrs {
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 125px auto;
}

.xr-attrs dt,
.xr-attrs dd {
  padding: 0;
  margin: 0;
  float: left;
  padding-right: 10px;
  width: auto;
}

.xr-attrs dt {
  font-weight: normal;
  grid-column: 1;
}

.xr-attrs dt:hover span {
  display: inline-block;
  background: var(--xr-background-color);
  padding-right: 10px;
}

.xr-attrs dd {
  grid-column: 2;
  white-space: pre-wrap;
  word-break: break-all;
}

.xr-icon-database,
.xr-icon-file-text2 {
  display: inline-block;
  vertical-align: middle;
  width: 1em;
  height: 1.5em !important;
  stroke-width: 0;
  stroke: currentColor;
  fill: currentColor;
}
&lt;/style&gt;
&lt;pre class="xr-text-repr-fallback"&gt;&amp;lt;xarray.DataArray ()&amp;gt;
array(1.00208561)&lt;/pre&gt;
&lt;div class="xr-wrap" hidden=""&gt;
&lt;div class="xr-header"&gt;
&lt;div class="xr-obj-type"&gt;
xarray.DataArray
&lt;/div&gt;
&lt;div class="xr-array-name"&gt;

&lt;/div&gt;
&lt;/div&gt;
&lt;ul class="xr-sections"&gt;
&lt;li class="xr-section-item"&gt;
&lt;div class="xr-array-wrap"&gt;
&lt;input id="section-06ec754e-834b-4f15-bc27-676cd22b9335" class="xr-array-in" type="checkbox" checked&gt;&lt;label for="section-06ec754e-834b-4f15-bc27-676cd22b9335" title="Show/hide data repr"&gt;&lt;svg class="icon xr-icon-database"&gt;&lt;use xlink:href="#icon-database"&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/label&gt;
&lt;div class="xr-array-preview xr-preview"&gt;
&lt;span&gt;1.002&lt;/span&gt;
&lt;/div&gt;
&lt;div class="xr-array-data"&gt;
&lt;pre&gt;array(1.00208561)&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-1aca641d-a2c0-4778-8cb0-2dbf0567048b" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-1aca641d-a2c0-4778-8cb0-2dbf0567048b" class="xr-section-summary" title="Expand/collapse section"&gt;Coordinates: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;ul class="xr-var-list"&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li class="xr-section-item"&gt;
&lt;input id="section-d5aedee9-d89e-4f49-9bff-3d8ecceff141" class="xr-section-summary-in" type="checkbox" disabled&gt;&lt;label for="section-d5aedee9-d89e-4f49-9bff-3d8ecceff141" class="xr-section-summary" title="Expand/collapse section"&gt;Attributes: &lt;span&gt;(0)&lt;/span&gt;&lt;/label&gt;
&lt;div class="xr-section-inline-details"&gt;

&lt;/div&gt;
&lt;div class="xr-section-details"&gt;
&lt;dl class="xr-attrs"&gt;
&lt;/dl&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Again we sample from the posterior predictive distribution of this model and plot the results.&lt;/p&gt;
&lt;div class="sourceCode" id="cb62"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb62-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb62-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_pooled_logistic_df &lt;span class="op"&gt;=&lt;/span&gt; get_pp_df(pooled_logistic_model, pooled_logistic_trace)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style&gt;
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
&lt;/style&gt;
&lt;progress value="6000" class max="6000" style="width:300px; height:20px; vertical-align: middle;"&gt;
&lt;/progress&gt;
&lt;p&gt;100.00% [6000/6000 01:08&amp;lt;00:00]&lt;/p&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb63"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb63-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb63-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_pooled_logistic_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;div&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
age
&lt;/th&gt;
&lt;th&gt;
taxon_id
&lt;/th&gt;
&lt;th&gt;
pp_mean
&lt;/th&gt;
&lt;th&gt;
pp_low
&lt;/th&gt;
&lt;th&gt;
pp_high
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
22.852762
&lt;/td&gt;
&lt;td&gt;
10.267422
&lt;/td&gt;
&lt;td&gt;
56.497339
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
9.839328
&lt;/td&gt;
&lt;td&gt;
0.906120
&lt;/td&gt;
&lt;td&gt;
125.299677
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
12.589540
&lt;/td&gt;
&lt;td&gt;
3.182979
&lt;/td&gt;
&lt;td&gt;
91.279583
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
3
&lt;/th&gt;
&lt;td&gt;
1.000000
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
11.080350
&lt;/td&gt;
&lt;td&gt;
4.344195
&lt;/td&gt;
&lt;td&gt;
36.627854
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
4
&lt;/th&gt;
&lt;td&gt;
1.071878
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
24.465512
&lt;/td&gt;
&lt;td&gt;
11.729286
&lt;/td&gt;
&lt;td&gt;
56.373575
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/center&gt;
&lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb64"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb64-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb64-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plot_pp_by_taxon(pp_logistic_df, plot_data&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, name&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Unpooled logistic"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb64-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb64-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_pp_by_taxon(pp_pooled_logistic_df,&lt;/span&gt;
&lt;span id="cb64-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb64-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 name&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pooled logistic"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb64-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb64-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 fig&lt;span class="op"&gt;=&lt;/span&gt;fig, axes&lt;span class="op"&gt;=&lt;/span&gt;axes)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/tyrannosaurid/Growth%20Curves%20REPARAM_92_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that the posterior predictive means for the pooled logistic model fit better than those from the unpooled model, and that the credible intervals are again significantly smaller.&lt;/p&gt;
&lt;p&gt;We now compare the posterior predictions for the pooled log-linear and logistic models.&lt;/p&gt;
&lt;div class="sourceCode" id="cb65"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb65-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb65-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plot_pp_by_taxon(pp_pooled_loglin_df, plot_data&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, name&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pooled log-linear"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb65-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb65-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_pp_by_taxon(pp_pooled_logistic_df,&lt;/span&gt;
&lt;span id="cb65-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb65-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 name&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Pooled logistic"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb65-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb65-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 fig&lt;span class="op"&gt;=&lt;/span&gt;fig, axes&lt;span class="op"&gt;=&lt;/span&gt;axes)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/tyrannosaurid/Growth%20Curves%20REPARAM_94_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;These models agree with each other fairly well, espescially in age ranges where the taxon data is concentrated, with the logistic model making slightly more plausible predictions as age increases.&lt;/p&gt;
&lt;h3 id="model-comparison"&gt;Model comparison&lt;/h3&gt;
&lt;p&gt;We now compare these four models using two of the information criteria available in &lt;code&gt;arviz&lt;/code&gt;. While &lt;em&gt;BSM&lt;/em&gt; uses the &lt;a href="https://en.wikipedia.org/wiki/Deviance_information_criterion"&gt;deviance information criterion&lt;/a&gt; (DIC) to compare models, DIC is no longer supported in &lt;code&gt;pymc3&lt;/code&gt; or &lt;code&gt;arviz&lt;/code&gt;, so we use Pareto-smoothed importance sampling leave-one-out cross validation (PSIS-LOO) and the widely applicable information criterion (WAIC) to compare models. These information criteria are available in &lt;code&gt;arviz&lt;/code&gt;. For details on these methods, consult the &lt;a href="https://docs.pymc.io/notebooks/model_comparison.html"&gt;&lt;code&gt;pymc3&lt;/code&gt; documentation&lt;/a&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb66"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb66-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb66-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;traces &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb66-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb66-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'Unpooled log-linear'&lt;/span&gt;: loglin_trace,&lt;/span&gt;
&lt;span id="cb66-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb66-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'Pooled log-linear'&lt;/span&gt;: pooled_loglin_trace,&lt;/span&gt;
&lt;span id="cb66-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb66-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'Unpooled logistic'&lt;/span&gt;: logistic_trace,&lt;/span&gt;
&lt;span id="cb66-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb66-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'Pooled logistic'&lt;/span&gt;: pooled_logistic_trace&lt;/span&gt;
&lt;span id="cb66-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb66-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb67"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb67-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; plot_compare(comp_df, ic, height&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;6&lt;/span&gt;, fig&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, axes&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb67-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; fig &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt; &lt;span class="kw"&gt;or&lt;/span&gt; axes &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb67-3"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(&lt;/span&gt;
&lt;span id="cb67-4"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;16&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; (height &lt;span class="op"&gt;/&lt;/span&gt; &lt;span class="dv"&gt;6&lt;/span&gt;), height)&lt;/span&gt;
&lt;span id="cb67-5"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        )&lt;/span&gt;
&lt;span id="cb67-6"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb67-7"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    score_ax, weight_ax &lt;span class="op"&gt;=&lt;/span&gt; axes&lt;/span&gt;
&lt;span id="cb67-8"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb67-9"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    az.plot_compare(comp_df, insample_dev&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, plot_ic_diff&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;score_ax)&lt;/span&gt;
&lt;span id="cb67-10"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb67-11"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    score_ax.set_xlabel(&lt;span class="st"&gt;"Log score"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb67-12"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    score_ax.set_ylabel(&lt;span class="st"&gt;"Model"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb67-13"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb67-14"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    comp_df[&lt;span class="st"&gt;'weight'&lt;/span&gt;].plot.barh(ax&lt;span class="op"&gt;=&lt;/span&gt;weight_ax)&lt;/span&gt;
&lt;span id="cb67-15"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb67-16"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    weight_ax.set_xscale(&lt;span class="st"&gt;'log'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb67-17"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    weight_ax.set_xlim(right&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb67-18"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    weight_ax.set_xlabel(&lt;span class="st"&gt;"Stacking weight"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb67-19"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb67-20"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    weight_ax.set_yticklabels([])&lt;/span&gt;
&lt;span id="cb67-21"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    weight_ax.invert_yaxis()&lt;/span&gt;
&lt;span id="cb67-22"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb67-23"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    fig.suptitle(&lt;span class="ss"&gt;f"&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;ic&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt; comparison"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb67-24"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    fig.tight_layout()&lt;/span&gt;
&lt;span id="cb67-25"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb67-26"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb67-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; fig, axes&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The following plots show the PSIS-LOO comparison for these models.&lt;/p&gt;
&lt;div class="sourceCode" id="cb68"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb68-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb68-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;loo_df &lt;span class="op"&gt;=&lt;/span&gt; az.compare(traces, ic&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'loo'&lt;/span&gt;, seed&lt;span class="op"&gt;=&lt;/span&gt;SEED)&lt;/span&gt;
&lt;span id="cb68-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb68-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_compare(loo_df, &lt;span class="st"&gt;"LOO"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/tyrannosaurid/Growth%20Curves%20REPARAM_100_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Note that larger scores are better, so PSIS-LOO favors the pooled models over the unpooled models and favors the pooled logistic model most highly of all.&lt;/p&gt;
&lt;div class="sourceCode" id="cb69"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb69-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb69-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;waic_df &lt;span class="op"&gt;=&lt;/span&gt; az.compare(traces, ic&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'waic'&lt;/span&gt;, seed&lt;span class="op"&gt;=&lt;/span&gt;SEED)&lt;/span&gt;
&lt;span id="cb69-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb69-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plot_compare(waic_df, &lt;span class="st"&gt;"WAIC"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/tyrannosaurid/Growth%20Curves%20REPARAM_102_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Using WAIC produces quite similar results.&lt;/p&gt;
&lt;p&gt;Interestingly, the results in &lt;em&gt;BSM&lt;/em&gt; using DIC favor the logistic model slightly.&lt;/p&gt;
&lt;p&gt;Many thanks to Reich and Ghosh for their excellent textbook which brought this fun dataset to my attention and to &lt;a href="https://kirilzvezdarov.com/about.html"&gt;Kiril Zvezdarov&lt;/a&gt; for his comments on early drafts.&lt;/p&gt;
&lt;p&gt;The notebook this post was generated from is available &lt;a href="https://nbviewer.jupyter.org/gist/AustinRochford/0baa4147c879556ee7cf3d9b0a663fb8"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb70"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb70-1"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb70-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;load_ext watermark&lt;/span&gt;
&lt;span id="cb70-2"&gt;&lt;a href="https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html#cb70-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;watermark &lt;span class="op"&gt;-&lt;/span&gt;n &lt;span class="op"&gt;-&lt;/span&gt;u &lt;span class="op"&gt;-&lt;/span&gt;v &lt;span class="op"&gt;-&lt;/span&gt;iv&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Last updated: Sun May 16 2021

Python implementation: CPython
Python version       : 3.8.8
IPython version      : 7.22.0

pymc3     : 3.11.1
seaborn   : 0.11.1
pandas    : 1.2.3
arviz     : 0.11.2
matplotlib: 3.4.1
numpy     : 1.20.2
aesara    : 2.0.6&lt;/code&gt;&lt;/pre&gt;</description><category>Bayesian Statistics</category><category>Examples</category><category>PyMC3</category><guid>https://austinrochford.com/posts/2021-05-17-tyrannosaurid-pymc3.html</guid><pubDate>Mon, 17 May 2021 04:00:00 GMT</pubDate></item><item><title>Evaluating Precision in Sports Analytics</title><link>https://austinrochford.com/posts/2018-12-20-sports-precision.html</link><dc:creator>Austin Rochford</dc:creator><description>&lt;p&gt;One of my data anaylsis pet peeves is &lt;a href="https://en.wikipedia.org/wiki/False_precision"&gt;false precision&lt;/a&gt;. Just because it is possible calculate a quantity to three decimal places doesn’t mean all of those decimal places are meaningful. This post explores how much precision is justified in the context of two common sports statistics: batting average in Major League Baseball and save percentage in the National Hockey League. Using Bayesian hierarchical models, we find that though these quantities are conventionally calculated to three decimal places, only the first two decimal places of precision are justified.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb1-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;matplotlib inline&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb2-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; arviz &lt;span class="im"&gt;as&lt;/span&gt; az&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib &lt;span class="im"&gt;import&lt;/span&gt; pyplot &lt;span class="im"&gt;as&lt;/span&gt; plt&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib.ticker &lt;span class="im"&gt;import&lt;/span&gt; StrMethodFormatter&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; numpy &lt;span class="im"&gt;as&lt;/span&gt; np&lt;/span&gt;
&lt;span id="cb2-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb2-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pandas &lt;span class="im"&gt;as&lt;/span&gt; pd&lt;/span&gt;
&lt;span id="cb2-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb2-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pymc3 &lt;span class="im"&gt;as&lt;/span&gt; pm&lt;/span&gt;
&lt;span id="cb2-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb2-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; scipy &lt;span class="im"&gt;as&lt;/span&gt; sp&lt;/span&gt;
&lt;span id="cb2-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb2-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; seaborn &lt;span class="im"&gt;as&lt;/span&gt; sns&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb3-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.&lt;span class="bu"&gt;set&lt;/span&gt;(color_codes&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;svpct_formatter &lt;span class="op"&gt;=&lt;/span&gt; ba_formatter &lt;span class="op"&gt;=&lt;/span&gt; StrMethodFormatter(&lt;span class="st"&gt;"&lt;/span&gt;&lt;span class="sc"&gt;{x:.3f}&lt;/span&gt;&lt;span class="st"&gt;"&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="batting-average"&gt;Batting average&lt;/h2&gt;
&lt;p&gt;We begin by loading hitting data for the 2018 MLB season from &lt;a href="https://www.baseball-reference.com/leagues/MLB/2018-standard-batting.shtml#players_standard_batting::none"&gt;Baseball Reference&lt;/a&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb4-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; get_data_url(filename):&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb4-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="ss"&gt;f"https://www.austinrochford.com/resources/sports_precision/&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;filename&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb5-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; load_data(filepath, player_col, usecols):&lt;/span&gt;
&lt;span id="cb5-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb5-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    df &lt;span class="op"&gt;=&lt;/span&gt; pd.read_csv(filepath, usecols&lt;span class="op"&gt;=&lt;/span&gt;[player_col] &lt;span class="op"&gt;+&lt;/span&gt; usecols)&lt;/span&gt;
&lt;span id="cb5-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb5-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb5-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb5-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; (pd.concat((df[player_col]&lt;/span&gt;
&lt;span id="cb5-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb5-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         .&lt;span class="bu"&gt;str&lt;/span&gt;.split(&lt;span class="st"&gt;'&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="st"&gt;'&lt;/span&gt;, expand&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb5-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb5-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         .rename(columns&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="dv"&gt;0&lt;/span&gt;: &lt;span class="st"&gt;'name'&lt;/span&gt;, &lt;span class="dv"&gt;1&lt;/span&gt;: &lt;span class="st"&gt;'player_id'&lt;/span&gt;}),&lt;/span&gt;
&lt;span id="cb5-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb5-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                       df.drop(player_col, axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)),&lt;/span&gt;
&lt;span id="cb5-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb5-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb5-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb5-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .rename(columns&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="bu"&gt;str&lt;/span&gt;.lower)&lt;/span&gt;
&lt;span id="cb5-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb5-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .groupby([&lt;span class="st"&gt;'player_id'&lt;/span&gt;, &lt;span class="st"&gt;'name'&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb5-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb5-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .first() &lt;span class="co"&gt;# players that switched teams have their entire season stats listed once per team&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb5-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .reset_index(&lt;span class="st"&gt;'name'&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb6-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;mlb_df &lt;span class="op"&gt;=&lt;/span&gt; load_data(get_data_url(&lt;span class="st"&gt;'2018_batting.csv'&lt;/span&gt;), &lt;span class="st"&gt;'Name'&lt;/span&gt;, [&lt;span class="st"&gt;'AB'&lt;/span&gt;, &lt;span class="st"&gt;'H'&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb7-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb7-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;mlb_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;center&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
name
&lt;/th&gt;
&lt;th&gt;
ab
&lt;/th&gt;
&lt;th&gt;
h
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
player_id
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
abreujo02
&lt;/th&gt;
&lt;td&gt;
Jose Abreu
&lt;/td&gt;
&lt;td&gt;
499
&lt;/td&gt;
&lt;td&gt;
132
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
acunaro01
&lt;/th&gt;
&lt;td&gt;
Ronald Acuna
&lt;/td&gt;
&lt;td&gt;
433
&lt;/td&gt;
&lt;td&gt;
127
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
adamewi01
&lt;/th&gt;
&lt;td&gt;
Willy Adames
&lt;/td&gt;
&lt;td&gt;
288
&lt;/td&gt;
&lt;td&gt;
80
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
adamja01
&lt;/th&gt;
&lt;td&gt;
Jason Adam
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
adamsau02
&lt;/th&gt;
&lt;td&gt;
Austin L. Adams
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb8-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;batter_df &lt;span class="op"&gt;=&lt;/span&gt; mlb_df[mlb_df[&lt;span class="st"&gt;'ab'&lt;/span&gt;] &lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="dv"&gt;0&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb8-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_player, _ &lt;span class="op"&gt;=&lt;/span&gt; batter_df.shape&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This data set covers nearly 1,000 MLB players.&lt;/p&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb9-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_player&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;984&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#batting-average"&gt;Batting average&lt;/a&gt;(https://en.wikipedia.org/wiki/Batting_average_(baseball%29) is the most basic summary of a player’s batting performance and is defined as their number of hits divided by their number of at bats. In order to assess the amount of precision that is justified when calculating batting average, we build a hierarchical logistic model. Let &lt;span class="math inline"&gt;\(n_i\)&lt;/span&gt; be the number of at bats for the &lt;span class="math inline"&gt;\(i\)&lt;/span&gt;-th player and let &lt;span class="math inline"&gt;\(y_i\)&lt;/span&gt; be their number of hits. Our model is&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \mu_{\eta}
        &amp;amp; \sim N(0, 5^2) \\
    \sigma_{\eta}
        &amp;amp; \sim \textrm{Half-}N(2.5^2) \\
    \eta_i
        &amp;amp; \sim N(\mu, \sigma_{\eta}^2) \\
    \textrm{ba}_i
        &amp;amp; = \textrm{sigm}(\eta_i) \\
    y_i\ |\ n_i
        &amp;amp; \sim \textrm{Binomial}(n_i, \textrm{ba}_i).
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We specify this model in &lt;a href="https://docs.pymc.io/"&gt;&lt;code&gt;pymc3&lt;/code&gt;&lt;/a&gt; below using a &lt;a href="https://twiecki.github.io/blog/2017/02/08/bayesian-hierchical-non-centered/"&gt;non-centered parametrization&lt;/a&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb11"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb11-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb11-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; hierarchical_normal(name, shape, μ&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb11-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb11-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; μ &lt;span class="kw"&gt;is&lt;/span&gt; &lt;span class="va"&gt;None&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb11-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb11-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        μ &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="ss"&gt;f"μ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb11-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb11-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb11-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb11-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    Δ &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="ss"&gt;f"Δ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;shape)&lt;/span&gt;
&lt;span id="cb11-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb11-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="ss"&gt;f"σ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;, &lt;span class="fl"&gt;2.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb11-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb11-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb11-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb11-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; pm.Deterministic(name, μ &lt;span class="op"&gt;+&lt;/span&gt; Δ &lt;span class="op"&gt;*&lt;/span&gt; σ)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb12"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb12-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb12-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; mlb_model:&lt;/span&gt;
&lt;span id="cb12-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb12-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    η &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal(&lt;span class="st"&gt;"η"&lt;/span&gt;, n_player)&lt;/span&gt;
&lt;span id="cb12-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb12-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ba &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;span class="st"&gt;"ba"&lt;/span&gt;, pm.math.sigmoid(η))&lt;/span&gt;
&lt;span id="cb12-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb12-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb12-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb12-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    hits &lt;span class="op"&gt;=&lt;/span&gt; pm.Binomial(&lt;span class="st"&gt;"hits"&lt;/span&gt;, batter_df[&lt;span class="st"&gt;'ab'&lt;/span&gt;], ba, observed&lt;span class="op"&gt;=&lt;/span&gt;batter_df[&lt;span class="st"&gt;'h'&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We proceeed to sample from the model’s posterior distribution.&lt;/p&gt;
&lt;div class="sourceCode" id="cb13"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb13-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb13-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;CHAINS &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb13-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SEED &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;88564&lt;/span&gt; &lt;span class="co"&gt;# from random.org, for reproducibility&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb13-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb13-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SAMPLE_KWARGS &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb13-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb13-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'draws'&lt;/span&gt;: &lt;span class="dv"&gt;1000&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb13-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb13-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'tune'&lt;/span&gt;: &lt;span class="dv"&gt;1000&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb13-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb13-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'chains'&lt;/span&gt;: CHAINS,&lt;/span&gt;
&lt;span id="cb13-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb13-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'cores'&lt;/span&gt;: CHAINS,&lt;/span&gt;
&lt;span id="cb13-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb13-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'random_seed'&lt;/span&gt;: &lt;span class="bu"&gt;list&lt;/span&gt;(SEED &lt;span class="op"&gt;+&lt;/span&gt; np.arange(CHAINS))&lt;/span&gt;
&lt;span id="cb13-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb13-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb14"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb14-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb14-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; mlb_model:&lt;/span&gt;
&lt;span id="cb14-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb14-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    mlb_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [σ_η, Δ_η, μ_η]
Sampling 3 chains: 100%|██████████| 6000/6000 [00:44&amp;lt;00:00, 133.94draws/s]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Before drawing conclusions from the posterior samples, we use &lt;a href="https://arviz-devs.github.io/arviz/index.html"&gt;&lt;code&gt;arviz&lt;/code&gt;&lt;/a&gt; to verify that there are no obvious problems with the sampler diagnostics.&lt;/p&gt;
&lt;div class="sourceCode" id="cb16"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb16-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb16-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_energy(mlb_trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sports_precision/sports_precision_21_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb17"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb17-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb17-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.gelman_rubin(mlb_trace).&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;xarray.Dataset&amp;gt;
Dimensions:  ()
Data variables:
    μ_η      float64 1.01
    Δ_η      float64 1.0
    σ_η      float64 1.0
    η        float64 1.0
    ba       float64 1.0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First we’ll examine the posterior distribution of &lt;a href="https://www.baseball-reference.com/players/t/troutmi01.shtml"&gt;Mike Trout&lt;/a&gt;’s batting average.&lt;/p&gt;
&lt;div class="sourceCode" id="cb19"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb19-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb19-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb19-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;trout_ix &lt;span class="op"&gt;=&lt;/span&gt; (batter_df.index &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="st"&gt;'troutmi01'&lt;/span&gt;).argmax()&lt;/span&gt;
&lt;span id="cb19-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.hist(mlb_trace[&lt;span class="st"&gt;'ba'&lt;/span&gt;][:, trout_ix], bins&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;30&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb19-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.vlines(batter_df[&lt;span class="st"&gt;'h'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb19-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   .div(batter_df[&lt;span class="st"&gt;'ab'&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb19-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   .loc[&lt;span class="st"&gt;'troutmi01'&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb19-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          &lt;span class="dv"&gt;0&lt;/span&gt;, &lt;span class="dv"&gt;275&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb19-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          linestyles&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'--'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb19-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Actual batting average"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb19-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.xaxis.set_major_formatter(ba_formatter)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Batting average"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb19-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Posterior density"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-17"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb19-18"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-19"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb19-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Mike Trout"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sports_precision/sports_precision_24_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that the posterior places significant mass between .260 and .320, quite a wide range of batting averages. This range roughly corresponds to the 95% credible interval for his 2018 batting average.&lt;/p&gt;
&lt;div class="sourceCode" id="cb20"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb20-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb20-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;np.percentile(mlb_trace[&lt;span class="st"&gt;'ba'&lt;/span&gt;][:, trout_ix], [&lt;span class="fl"&gt;2.5&lt;/span&gt;, &lt;span class="fl"&gt;97.5&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;array([ 0.25516468,  0.32704036])&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We will use the width of the 95% credible interval for each player’s batting average to determine how many digits of precision are justified.&lt;/p&gt;
&lt;div class="sourceCode" id="cb22"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb22-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb22-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;mlb_df &lt;span class="op"&gt;=&lt;/span&gt; batter_df.assign(&lt;/span&gt;
&lt;span id="cb22-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb22-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    width_95&lt;span class="op"&gt;=&lt;/span&gt;sp.stats.iqr(mlb_trace[&lt;span class="st"&gt;"ba"&lt;/span&gt;], axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;, rng&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="fl"&gt;2.5&lt;/span&gt;, &lt;span class="fl"&gt;97.5&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb22-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb22-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The following plot shows the width of these intervals, grouped by the number of at bats the player had in 2018.&lt;/p&gt;
&lt;div class="sourceCode" id="cb23"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb23-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb23-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; plot_ci_width(grouped, width):&lt;/span&gt;
&lt;span id="cb23-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb23-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb23-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb23-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb23-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb23-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    low &lt;span class="op"&gt;=&lt;/span&gt; grouped.quantile(&lt;span class="fl"&gt;0.025&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb23-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb23-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    high &lt;span class="op"&gt;=&lt;/span&gt; grouped.quantile(&lt;span class="fl"&gt;0.975&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb23-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb23-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb23-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb23-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.fill_between(low.index, low, high,&lt;/span&gt;
&lt;span id="cb23-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb23-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.25&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb23-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb23-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;f"&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;width&lt;span class="sc"&gt;:.0%}&lt;/span&gt;&lt;span class="ss"&gt; interval"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb23-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb23-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb23-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    grouped.mean().plot(ax&lt;span class="op"&gt;=&lt;/span&gt;ax, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Average"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb23-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb23-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb23-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb23-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_ylabel(&lt;span class="st"&gt;"Width of 95&lt;/span&gt;&lt;span class="sc"&gt;% c&lt;/span&gt;&lt;span class="st"&gt;redible interval"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb23-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb23-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb23-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb23-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb23-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; ax&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb24"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb24-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb24-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_ci_width(mlb_df[&lt;span class="st"&gt;'width_95'&lt;/span&gt;].groupby(mlb_df[&lt;span class="st"&gt;'ab'&lt;/span&gt;].&lt;span class="bu"&gt;round&lt;/span&gt;(&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;)), &lt;span class="fl"&gt;0.95&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb24-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb24-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb24-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb24-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlim(&lt;span class="dv"&gt;0&lt;/span&gt;, mlb_df[&lt;span class="st"&gt;'ab'&lt;/span&gt;].&lt;span class="bu"&gt;max&lt;/span&gt;())&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb24-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"At bats"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb24-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb24-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb24-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylim(bottom&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb24-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.yaxis.set_major_formatter(ba_formatter)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb24-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb24-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb24-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb24-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Batting average"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sports_precision/sports_precision_31_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that, on average, about 100 at bats are required to justify a single digit of precision in a player’s batting average. Even in the limit of very many at bats (600 at bats corresponds to just under four at bats per game across a 162 game season) the 95% credible interval has an average width approaching 0.060. This limit indicates that batting average is at most meaningful to the second digit, and even the second digit has a fair bit of uncertainty. This result is not surprising; calculating batting average to three decimal places is a historical convention, but I don’t think many analysts rely on the third digit for their decisions/arguments. While intuitive, it is pleasant to have a somewhat rigorous justification for this practice.&lt;/p&gt;
&lt;h2 id="save-percentage"&gt;Save percentage&lt;/h2&gt;
&lt;p&gt;We apply a similar analysis to save percentage in the NHL. First we load 2018 goaltending data from &lt;a href="https://www.hockey-reference.com/leagues/NHL_2018_goalies.html#stats::none"&gt;Hockey Reference&lt;/a&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb25"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb25-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb25-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;nhl_df &lt;span class="op"&gt;=&lt;/span&gt; load_data(get_data_url(&lt;span class="st"&gt;'2017_2018_goalies.csv'&lt;/span&gt;), &lt;span class="st"&gt;'Player'&lt;/span&gt;, [&lt;span class="st"&gt;'SA'&lt;/span&gt;, &lt;span class="st"&gt;'SV'&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb26"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb26-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb26-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;nhl_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;center&gt;
&lt;style scoped&gt;
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
vertical-align: top;
}

.dataframe thead th {
text-align: right;
}
&lt;/style&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
name
&lt;/th&gt;
&lt;th&gt;
sa
&lt;/th&gt;
&lt;th&gt;
sv
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
player_id
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
allenja01
&lt;/th&gt;
&lt;td&gt;
Jake Allen
&lt;/td&gt;
&lt;td&gt;
1614
&lt;/td&gt;
&lt;td&gt;
1462
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
andercr01
&lt;/th&gt;
&lt;td&gt;
Craig Anderson
&lt;/td&gt;
&lt;td&gt;
1768
&lt;/td&gt;
&lt;td&gt;
1588
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
anderfr01
&lt;/th&gt;
&lt;td&gt;
Frederik Andersen
&lt;/td&gt;
&lt;td&gt;
2211
&lt;/td&gt;
&lt;td&gt;
2029
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
appleke01
&lt;/th&gt;
&lt;td&gt;
Ken Appleby
&lt;/td&gt;
&lt;td&gt;
55
&lt;/td&gt;
&lt;td&gt;
52
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
bernijo01
&lt;/th&gt;
&lt;td&gt;
Jonathan Bernier
&lt;/td&gt;
&lt;td&gt;
1092
&lt;/td&gt;
&lt;td&gt;
997
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb27"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb27-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb27-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_goalie, _ &lt;span class="op"&gt;=&lt;/span&gt; nhl_df.shape&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This data set consists of the goaltending performance of just under 100 players.&lt;/p&gt;
&lt;div class="sourceCode" id="cb28"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb28-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb28-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_goalie&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;95&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our &lt;a href="https://en.wikipedia.org/wiki/Save_percentage"&gt;save percentage&lt;/a&gt; model is almost identical to the batting average model. Let &lt;span class="math inline"&gt;\(n_i\)&lt;/span&gt; be the number of at shots the &lt;span class="math inline"&gt;\(i\)&lt;/span&gt;-th goalie faced and let &lt;span class="math inline"&gt;\(y_i\)&lt;/span&gt; be the number of saves they made. The model is&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \mu_{\eta}
        &amp;amp; \sim N(0, 5^2) \\
    \sigma_{\eta}
        &amp;amp; \sim \textrm{Half-}N(2.5^2) \\
    \eta_i
        &amp;amp; \sim N(\mu, \sigma_{\eta}^2) \\
    \textrm{svp}_i
        &amp;amp; = \textrm{sigm}(\eta_i) \\
    y_i\ |\ n_i
        &amp;amp; \sim \textrm{Binomial}(n_i, \textrm{svp}_i).
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb30"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb30-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb30-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; nhl_model:&lt;/span&gt;
&lt;span id="cb30-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb30-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    η &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal(&lt;span class="st"&gt;"η"&lt;/span&gt;, n_goalie)&lt;/span&gt;
&lt;span id="cb30-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb30-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    svp &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;span class="st"&gt;"svp"&lt;/span&gt;, pm.math.sigmoid(η))&lt;/span&gt;
&lt;span id="cb30-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb30-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb30-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb30-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    saves &lt;span class="op"&gt;=&lt;/span&gt; pm.Binomial(&lt;span class="st"&gt;"saves"&lt;/span&gt;, nhl_df[&lt;span class="st"&gt;'sa'&lt;/span&gt;], svp, observed&lt;span class="op"&gt;=&lt;/span&gt;nhl_df[&lt;span class="st"&gt;'sv'&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb31"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb31-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb31-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; nhl_model:&lt;/span&gt;
&lt;span id="cb31-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb31-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    nhl_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(nuts_kwargs&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;'target_accept'&lt;/span&gt;: &lt;span class="fl"&gt;0.9&lt;/span&gt;}, &lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [σ_η, Δ_η, μ_η]
Sampling 3 chains: 100%|██████████| 6000/6000 [00:17&amp;lt;00:00, 338.38draws/s]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once again, the convergence diagnostics show no cause for concern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb33"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb33-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb33-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_energy(nhl_trace)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sports_precision/sports_precision_44_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb34"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb34-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb34-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.gelman_rubin(nhl_trace).&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;xarray.Dataset&amp;gt;
Dimensions:  ()
Data variables:
    μ_η      float64 1.0
    Δ_η      float64 1.0
    σ_η      float64 1.0
    η        float64 1.0
    svp      float64 1.0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We examine the posterior distribution of &lt;a href="https://www.hockey-reference.com/players/b/bobrose01.html"&gt;Sergei Bobrovsky&lt;/a&gt;’s save percentage.&lt;/p&gt;
&lt;div class="sourceCode" id="cb36"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb36-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb36-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb36-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;bobs_ix &lt;span class="op"&gt;=&lt;/span&gt; (nhl_df.index &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="st"&gt;'bobrose01'&lt;/span&gt;).argmax()&lt;/span&gt;
&lt;span id="cb36-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.hist(nhl_trace[&lt;span class="st"&gt;'svp'&lt;/span&gt;][:, bobs_ix], bins&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;30&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb36-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.vlines(nhl_df[&lt;span class="st"&gt;'sv'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb36-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .div(nhl_df[&lt;span class="st"&gt;'sa'&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb36-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .loc[&lt;span class="st"&gt;'bobrose01'&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb36-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          &lt;span class="dv"&gt;0&lt;/span&gt;, &lt;span class="dv"&gt;325&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb36-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          linestyles&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'--'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb36-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Actual save percentage"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb36-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.xaxis.set_major_formatter(ba_formatter)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Save percentage"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb36-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"Posterior density"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-17"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb36-18"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.legend(loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb36-19"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb36-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Sergei Bobrovsky"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sports_precision/sports_precision_47_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We see that the posterior places significant mass between .905 and .925. We see below that the best and worst save percentages (for goalies that faced at least 200 shots in 2018) are separated by about 0.070.&lt;/p&gt;
&lt;div class="sourceCode" id="cb37"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb37-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb37-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(nhl_df[&lt;span class="st"&gt;'sv'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb37-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb37-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .div(nhl_df[&lt;span class="st"&gt;'sa'&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb37-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb37-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       [nhl_df[&lt;span class="st"&gt;'sa'&lt;/span&gt;] &lt;span class="op"&gt;&amp;gt;&lt;/span&gt; &lt;span class="dv"&gt;200&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb37-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb37-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .quantile([&lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;1.&lt;/span&gt;]))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;0.0    0.866995
1.0    0.933712
dtype: float64&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sergei Bobrovsky’s 0.020-wide credible interval is a significant proportion of this 0.070 total range.&lt;/p&gt;
&lt;div class="sourceCode" id="cb39"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb39-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb39-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;np.percentile(nhl_trace[&lt;span class="st"&gt;'svp'&lt;/span&gt;][:, bobs_ix], [&lt;span class="fl"&gt;2.5&lt;/span&gt;, &lt;span class="fl"&gt;97.5&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;array([ 0.90683748,  0.92526507])&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As with batting average, we plot the width of each goalie’s interval, grouped by the number of shots they faced.&lt;/p&gt;
&lt;div class="sourceCode" id="cb41"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb41-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb41-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;nhl_df &lt;span class="op"&gt;=&lt;/span&gt; nhl_df.assign(&lt;/span&gt;
&lt;span id="cb41-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb41-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    width_95&lt;span class="op"&gt;=&lt;/span&gt;sp.stats.iqr(nhl_trace[&lt;span class="st"&gt;"svp"&lt;/span&gt;], axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;, rng&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="fl"&gt;2.5&lt;/span&gt;, &lt;span class="fl"&gt;97.5&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb41-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb41-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb42"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb42-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb42-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; plot_ci_width(nhl_df[&lt;span class="st"&gt;'width_95'&lt;/span&gt;].groupby(nhl_df[&lt;span class="st"&gt;'sa'&lt;/span&gt;].&lt;span class="bu"&gt;round&lt;/span&gt;(&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;)), &lt;span class="fl"&gt;0.95&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb42-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb42-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb42-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlim(&lt;span class="dv"&gt;0&lt;/span&gt;, nhl_df[&lt;span class="st"&gt;'sa'&lt;/span&gt;].&lt;span class="bu"&gt;max&lt;/span&gt;())&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb42-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Shots against"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb42-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb42-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylim(bottom&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb42-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.yaxis.set_major_formatter(svpct_formatter)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb42-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb42-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb42-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-12-20-sports-precision.html#cb42-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Save percentage"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/sports_precision/sports_precision_54_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;This plot shows that even goalies that face many (2000+) shots have credible intervals wider that 0.010, a signifcant proportion of the total variation between goalies.&lt;/p&gt;
&lt;p&gt;This post is available as a Jupyter notebook &lt;a href="https://nbviewer.jupyter.org/gist/AustinRochford/36f072aedb7df368fdcf7d98998728e4/sports_precision.ipynb"&gt;here&lt;/a&gt;.&lt;/p&gt;</description><category>Bayesian Statistics</category><category>MLB</category><category>NHL</category><category>PyMC3</category><guid>https://austinrochford.com/posts/2018-12-20-sports-precision.html</guid><pubDate>Thu, 20 Dec 2018 05:00:00 GMT</pubDate></item><item><title>Monotonic Effects in PyMC3</title><link>https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html</link><dc:creator>Austin Rochford</dc:creator><description>&lt;p&gt;Last week I came across the following tweet from &lt;a href="https://www.uni-muenster.de/PsyIFP/AEHolling/de/personen/buerkner.html"&gt;Paul Bürkner&lt;/a&gt; about a paper he coauthored about including ordinal predictors in Bayesian regression models, and I thought the approach was very clever.&lt;/p&gt;
&lt;center&gt;
&lt;blockquote class="twitter-tweet" data-lang="en"&gt;
&lt;p lang="en" dir="ltr"&gt;
Have you ever wondered how to handle ordinal predictors in your regression models? We propose a simple and intuitive method that is readily available via &lt;a href="https://twitter.com/hashtag/brms?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#brms&lt;/a&gt; and &lt;a href="https://twitter.com/mcmc_stan?ref_src=twsrc%5Etfw"&gt;&lt;span class="citation" data-cites="mcmc_stan"&gt;@mcmc_stan&lt;/span&gt;&lt;/a&gt;: &lt;a href="https://t.co/dKg4AphvsG"&gt;https://t.co/dKg4AphvsG&lt;/a&gt;
&lt;/p&gt;
— Paul Bürkner (&lt;span class="citation" data-cites="paulbuerkner"&gt;@paulbuerkner&lt;/span&gt;) &lt;a href="https://twitter.com/paulbuerkner/status/1058394076863754240?ref_src=twsrc%5Etfw"&gt;November 2, 2018&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;/center&gt;
&lt;p&gt;The code in the paper uses &lt;a href="https://github.com/paul-buerkner/brms"&gt;&lt;code&gt;brms&lt;/code&gt;&lt;/a&gt; and &lt;a href="http://mc-stan.org/"&gt;Stan&lt;/a&gt; to illustrate these concepts. In this post I’ll be replicating some of the paper’s analysis in Python and &lt;a href="https://docs.pymc.io/"&gt;PyMC3&lt;/a&gt;, mostly for my own edification.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb1-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;matplotlib inline&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb2-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; itertools &lt;span class="im"&gt;import&lt;/span&gt; product&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb3-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; arviz &lt;span class="im"&gt;as&lt;/span&gt; az&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib &lt;span class="im"&gt;import&lt;/span&gt; pyplot &lt;span class="im"&gt;as&lt;/span&gt; plt&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; numpy &lt;span class="im"&gt;as&lt;/span&gt; np&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pandas &lt;span class="im"&gt;as&lt;/span&gt; pd&lt;/span&gt;
&lt;span id="cb3-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb3-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pymc3 &lt;span class="im"&gt;as&lt;/span&gt; pm&lt;/span&gt;
&lt;span id="cb3-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb3-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; rpy2.robjects &lt;span class="im"&gt;import&lt;/span&gt; pandas2ri, r&lt;/span&gt;
&lt;span id="cb3-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb3-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; seaborn &lt;span class="im"&gt;as&lt;/span&gt; sns&lt;/span&gt;
&lt;span id="cb3-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb3-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; theano &lt;span class="im"&gt;import&lt;/span&gt; shared&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb4-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.&lt;span class="bu"&gt;set&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The paper uses data from the &lt;a href="https://cran.r-project.org/web/packages/ordPens/index.html"&gt;&lt;code&gt;ordPens&lt;/code&gt;&lt;/a&gt; R package, which we download and load into a Pandas &lt;code&gt;DataFrame&lt;/code&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb5-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%%&lt;/span&gt;bash&lt;/span&gt;
&lt;span id="cb5-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb5-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;if&lt;/span&gt; [[ &lt;span class="op"&gt;!&lt;/span&gt; &lt;span class="op"&gt;-&lt;/span&gt;e &lt;span class="op"&gt;~/&lt;/span&gt;data&lt;span class="op"&gt;/&lt;/span&gt;ordPens ]]&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb5-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb5-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;then&lt;/span&gt;
&lt;span id="cb5-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb5-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    mkdir &lt;span class="op"&gt;-&lt;/span&gt;p data&lt;/span&gt;
&lt;span id="cb5-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb5-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wget &lt;span class="op"&gt;-&lt;/span&gt;q &lt;span class="op"&gt;-&lt;/span&gt;O data&lt;span class="op"&gt;/&lt;/span&gt;ordPens_0&lt;span class="fl"&gt;.3&lt;/span&gt;&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="fl"&gt;1.&lt;/span&gt;&lt;span class="er"&gt;tar&lt;/span&gt;.gz &lt;span class="op"&gt;~/&lt;/span&gt;data&lt;span class="op"&gt;/&lt;/span&gt; https:&lt;span class="op"&gt;//&lt;/span&gt;cran.r&lt;span class="op"&gt;-&lt;/span&gt;project.org&lt;span class="op"&gt;/&lt;/span&gt;src&lt;span class="op"&gt;/&lt;/span&gt;contrib&lt;span class="op"&gt;/&lt;/span&gt;ordPens_0&lt;span class="fl"&gt;.3&lt;/span&gt;&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="fl"&gt;1.&lt;/span&gt;&lt;span class="er"&gt;tar&lt;/span&gt;.gz&lt;/span&gt;
&lt;span id="cb5-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb5-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    tar xzf data&lt;span class="op"&gt;/&lt;/span&gt;ordPens_0&lt;span class="fl"&gt;.3&lt;/span&gt;&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="fl"&gt;1.&lt;/span&gt;&lt;span class="er"&gt;tar&lt;/span&gt;.gz &lt;span class="op"&gt;-&lt;/span&gt;C data&lt;/span&gt;
&lt;span id="cb5-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb5-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fi&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb6-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;!&lt;/span&gt;ls data&lt;span class="op"&gt;/&lt;/span&gt;ordPens&lt;span class="op"&gt;/&lt;/span&gt;data&lt;span class="op"&gt;/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;ICFCoreSetCWP.RData&lt;/code&gt;&lt;/pre&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb8-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pandas2ri.activate()&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb8-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb8-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb8-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;r.load(&lt;span class="st"&gt;'data/ordPens/data/ICFCoreSetCWP.RData'&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb8-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;all_df &lt;span class="op"&gt;=&lt;/span&gt; r[&lt;span class="st"&gt;'ICFCoreSetCWP'&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb9-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;all_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style scoped&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;center&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
b1602
&lt;/th&gt;
&lt;th&gt;
b122
&lt;/th&gt;
&lt;th&gt;
b126
&lt;/th&gt;
&lt;th&gt;
b130
&lt;/th&gt;
&lt;th&gt;
b134
&lt;/th&gt;
&lt;th&gt;
b140
&lt;/th&gt;
&lt;th&gt;
b147
&lt;/th&gt;
&lt;th&gt;
b152
&lt;/th&gt;
&lt;th&gt;
b164
&lt;/th&gt;
&lt;th&gt;
b180
&lt;/th&gt;
&lt;th&gt;
…
&lt;/th&gt;
&lt;th&gt;
e450
&lt;/th&gt;
&lt;th&gt;
e455
&lt;/th&gt;
&lt;th&gt;
e460
&lt;/th&gt;
&lt;th&gt;
e465
&lt;/th&gt;
&lt;th&gt;
e570
&lt;/th&gt;
&lt;th&gt;
e575
&lt;/th&gt;
&lt;th&gt;
e580
&lt;/th&gt;
&lt;th&gt;
e590
&lt;/th&gt;
&lt;th&gt;
s770
&lt;/th&gt;
&lt;th&gt;
phcs
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
1
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
…
&lt;/td&gt;
&lt;td&gt;
4
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
4
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
44.33
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2
&lt;/th&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
…
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
21.09
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
3
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
…
&lt;/td&gt;
&lt;td&gt;
4
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
4
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
41.74
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
4
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
…
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
-1
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
33.96
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
5
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
…
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
46.29
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
5 rows × 68 columns
&lt;/p&gt;
&lt;/center&gt;
&lt;/div&gt;
&lt;p&gt;The variable of interest here is &lt;code&gt;phcs&lt;/code&gt;, which is a subjective physical health score. The predictors we are interested in are &lt;code&gt;d450&lt;/code&gt; and &lt;code&gt;d455&lt;/code&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb10"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb10-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb10-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df &lt;span class="op"&gt;=&lt;/span&gt; all_df[[&lt;span class="st"&gt;'d450'&lt;/span&gt;, &lt;span class="st"&gt;'d455'&lt;/span&gt;, &lt;span class="st"&gt;'phcs'&lt;/span&gt;]]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb11"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb11-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb11-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style scoped&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;center&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
d450
&lt;/th&gt;
&lt;th&gt;
d455
&lt;/th&gt;
&lt;th&gt;
phcs
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
1
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
44.33
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2
&lt;/th&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
21.09
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
3
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
41.74
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
4
&lt;/th&gt;
&lt;td&gt;
3
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
33.96
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
5
&lt;/th&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
46.29
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;
&lt;/div&gt;
&lt;p&gt;These predictors are ratings on a five-point scale (0-4) of the patient’s impairment while walking (&lt;code&gt;d450&lt;/code&gt;) and moving around (&lt;code&gt;d455&lt;/code&gt;). For more information on this data, consult the &lt;a href="https://cran.r-project.org/web/packages/ordPens/ordPens.pdf"&gt;&lt;code&gt;ordPens&lt;/code&gt; documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The following plots show a fairly strong monotonic relationship between &lt;code&gt;d450&lt;/code&gt;, &lt;code&gt;d455&lt;/code&gt;, and &lt;code&gt;phcs&lt;/code&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb12"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb12-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb12-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, (d450_ax, d455_ax) &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;16&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb12-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb12-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb12-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb12-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.stripplot(&lt;span class="st"&gt;'d450'&lt;/span&gt;, &lt;span class="st"&gt;'phcs'&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df,&lt;/span&gt;
&lt;span id="cb12-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb12-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              jitter&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.1&lt;/span&gt;, color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.75&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb12-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb12-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              ax&lt;span class="op"&gt;=&lt;/span&gt;d450_ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb12-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.stripplot(&lt;span class="st"&gt;'d455'&lt;/span&gt;, &lt;span class="st"&gt;'phcs'&lt;/span&gt;, data&lt;span class="op"&gt;=&lt;/span&gt;df,&lt;/span&gt;
&lt;span id="cb12-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb12-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              jitter&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.1&lt;/span&gt;, color&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'C0'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.75&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb12-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb12-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              ax&lt;span class="op"&gt;=&lt;/span&gt;d455_ax)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb12-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb12-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb12-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d455_ax.set_ylabel(&lt;span class="st"&gt;""&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb12-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/monotonic/Monotonic%20Effects%20in%20PyMC3_15_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The big idea of the paper is to include monotonic effects due to these ordinal predictors as follows. A scalar &lt;span class="math inline"&gt;\(b \sim N(0, 10^2)\)&lt;/span&gt; parameterizes the overall strength and direction of the relationship, and a Dirichlet vector &lt;span class="math inline"&gt;\(\xi \sim \textrm{Dirichlet}(1, \ldots, 1)\)&lt;/span&gt; encodes how much of &lt;span class="math inline"&gt;\(b\)&lt;/span&gt; is gained at each level. The parameters &lt;span class="math inline"&gt;\(b\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(\xi\)&lt;/span&gt; are combined into&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[mo(i) = b \sum_{k = 0}^i \xi_k\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;which can be included as a term in a regression model. It is evident that if &lt;span class="math inline"&gt;\(i &amp;lt; j\)&lt;/span&gt; then &lt;span class="math inline"&gt;\(mo(i) \leq mo(j)\)&lt;/span&gt; since&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[mo(j) - mo(i) = b \sum_{k = i + 1}^j \xi_k \geq 0\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;and therefore the effect of this term will be monotonic as desired.&lt;/p&gt;
&lt;p&gt;The following function constructs this distribution in PyMC3.&lt;/p&gt;
&lt;div class="sourceCode" id="cb13"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb13-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb13-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; monotonic_prior(name, n_cat):&lt;/span&gt;
&lt;span id="cb13-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb13-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    b &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="ss"&gt;f'b_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;'&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;10.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb13-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb13-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ξ &lt;span class="op"&gt;=&lt;/span&gt; pm.Dirichlet(&lt;span class="ss"&gt;f'ξ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;'&lt;/span&gt;, np.ones(n_cat))&lt;/span&gt;
&lt;span id="cb13-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb13-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb13-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; pm.Deterministic(&lt;span class="ss"&gt;f'mo_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;'&lt;/span&gt;, b &lt;span class="op"&gt;*&lt;/span&gt; ξ.cumsum())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With this notation in hand, our model is&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \mu_i
        &amp;amp; = \beta_0 + mo_{\textrm{d450}}(j_i) + mo_{\textrm{d455}}(k_i) \\
    \beta_0
        &amp;amp; \sim N(0, 10^2) \\
    y_i
        &amp;amp; \sim N(\mu_i, \sigma^2) \\
    \sigma
        &amp;amp; \sim \textrm{HalfNormal}(5^2)
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;where &lt;span class="math inline"&gt;\(j_i\)&lt;/span&gt; and &lt;span class="math inline"&gt;\(k_i\)&lt;/span&gt; are the level of &lt;code&gt;d450&lt;/code&gt; and &lt;code&gt;d455&lt;/code&gt; for the &lt;span class="math inline"&gt;\(i\)&lt;/span&gt;-th patient respectively and &lt;span class="math inline"&gt;\(y_i\)&lt;/span&gt; is that patient’s &lt;code&gt;phcs&lt;/code&gt; score.&lt;/p&gt;
&lt;p&gt;We now express this model in PyMC3.&lt;/p&gt;
&lt;div class="sourceCode" id="cb14"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb14-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb14-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d450 &lt;span class="op"&gt;=&lt;/span&gt; df[&lt;span class="st"&gt;'d450'&lt;/span&gt;].values&lt;/span&gt;
&lt;span id="cb14-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb14-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d450_cats &lt;span class="op"&gt;=&lt;/span&gt; np.unique(d450)&lt;/span&gt;
&lt;span id="cb14-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb14-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d450_n_cat &lt;span class="op"&gt;=&lt;/span&gt; d450_cats.size&lt;/span&gt;
&lt;span id="cb14-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb14-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d450_ &lt;span class="op"&gt;=&lt;/span&gt; shared(d450)&lt;/span&gt;
&lt;span id="cb14-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb14-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb14-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb14-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d455 &lt;span class="op"&gt;=&lt;/span&gt; df[&lt;span class="st"&gt;'d455'&lt;/span&gt;].values&lt;/span&gt;
&lt;span id="cb14-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb14-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d455_cats &lt;span class="op"&gt;=&lt;/span&gt; np.unique(d455)&lt;/span&gt;
&lt;span id="cb14-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb14-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d455_n_cat &lt;span class="op"&gt;=&lt;/span&gt; d455_cats.size&lt;/span&gt;
&lt;span id="cb14-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb14-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d455_ &lt;span class="op"&gt;=&lt;/span&gt; shared(d455)&lt;/span&gt;
&lt;span id="cb14-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb14-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb14-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb14-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;phcs &lt;span class="op"&gt;=&lt;/span&gt; df[&lt;span class="st"&gt;'phcs'&lt;/span&gt;].values&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb15"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb15-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb15-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb15-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb15-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;'β0'&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;10.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb15-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb15-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb15-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb15-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    mo_d450 &lt;span class="op"&gt;=&lt;/span&gt; monotonic_prior(&lt;span class="st"&gt;'d450'&lt;/span&gt;, d450_n_cat)&lt;/span&gt;
&lt;span id="cb15-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb15-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    mo_d455 &lt;span class="op"&gt;=&lt;/span&gt; monotonic_prior(&lt;span class="st"&gt;'d455'&lt;/span&gt;, d455_n_cat)&lt;/span&gt;
&lt;span id="cb15-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb15-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb15-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb15-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; mo_d450[d450_] &lt;span class="op"&gt;+&lt;/span&gt; mo_d455[d455_]&lt;/span&gt;
&lt;span id="cb15-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb15-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;'σ'&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb15-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb15-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    phcs_obs &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;'phcs'&lt;/span&gt;, μ, σ, observed&lt;span class="op"&gt;=&lt;/span&gt;phcs)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We now sample from the model’s posterior distribution.&lt;/p&gt;
&lt;div class="sourceCode" id="cb16"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb16-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb16-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;CHAINS &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb16-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SEED &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;934520&lt;/span&gt; &lt;span class="co"&gt;# from random.org&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb16-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb16-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb16-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb16-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SAMPLE_KWARGS &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb16-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb16-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'draws'&lt;/span&gt;: &lt;span class="dv"&gt;1000&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb16-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb16-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'tune'&lt;/span&gt;: &lt;span class="dv"&gt;1000&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb16-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb16-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'chains'&lt;/span&gt;: CHAINS,&lt;/span&gt;
&lt;span id="cb16-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb16-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'random_seed'&lt;/span&gt;: &lt;span class="bu"&gt;list&lt;/span&gt;(SEED &lt;span class="op"&gt;+&lt;/span&gt; np.arange(CHAINS))&lt;/span&gt;
&lt;span id="cb16-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb16-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb17"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb17-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb17-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb17-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb17-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 2 jobs)
NUTS: [σ, ξ_d455, b_d455, ξ_d450, b_d450, β0]
Sampling 3 chains: 100%|██████████| 6000/6000 [00:41&amp;lt;00:00, 145.59draws/s]
The number of effective samples is smaller than 25% for some parameters.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We use &lt;a href="https://arviz-devs.github.io/arviz/index.html"&gt;&lt;code&gt;arviz&lt;/code&gt;&lt;/a&gt; to check the performance of our sampler.&lt;/p&gt;
&lt;div class="sourceCode" id="cb19"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb19-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb19-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;inf_data &lt;span class="op"&gt;=&lt;/span&gt; az.convert_to_inference_data(trace)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The energy plot, BFMI, and Gelman-Rubin statistics show no cause for concern.&lt;/p&gt;
&lt;div class="sourceCode" id="cb20"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb20-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb20-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.plot_energy(inf_data)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/monotonic/Monotonic%20Effects%20in%20PyMC3_27_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb21"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb21-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb21-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;az.gelman_rubin(inf_data).&lt;span class="bu"&gt;max&lt;/span&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;xarray.Dataset&amp;gt;
Dimensions:  ()
Data variables:
    β0       float64 1.0
    b_d450   float64 1.0
    b_d455   float64 1.0
    ξ_d450   float64 1.0
    mo_d450  float64 1.0
    ξ_d455   float64 1.0
    mo_d455  float64 1.0
    σ        float64 1.0&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We now sample from the model’s posterior predictive distribution and visualize the results.&lt;/p&gt;
&lt;div class="sourceCode" id="cb23"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb23-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb23-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_d450, pp_d455 &lt;span class="op"&gt;=&lt;/span&gt; np.asarray(&lt;span class="bu"&gt;list&lt;/span&gt;(&lt;span class="bu"&gt;zip&lt;/span&gt;(&lt;span class="op"&gt;*&lt;/span&gt;product(d450_cats, d455_cats))))&lt;/span&gt;
&lt;span id="cb23-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb23-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb23-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb23-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d450_.set_value(pp_d450)&lt;/span&gt;
&lt;span id="cb23-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb23-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d455_.set_value(pp_d455)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb24"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb24-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb24-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; model:&lt;/span&gt;
&lt;span id="cb24-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb24-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    pp_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample_posterior_predictive(trace)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;100%|██████████| 3000/3000 [00:07&amp;lt;00:00, 388.49it/s]&lt;/code&gt;&lt;/pre&gt;
&lt;div class="sourceCode" id="cb26"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb26-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb26-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pp_df &lt;span class="op"&gt;=&lt;/span&gt; pd.DataFrame({&lt;/span&gt;
&lt;span id="cb26-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb26-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'d450'&lt;/span&gt;: pp_d450,&lt;/span&gt;
&lt;span id="cb26-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb26-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'d455'&lt;/span&gt;: pp_d455,&lt;/span&gt;
&lt;span id="cb26-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb26-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'pp_phcs_mean'&lt;/span&gt;: pp_trace[&lt;span class="st"&gt;'phcs'&lt;/span&gt;].mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb26-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb26-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The important feature of this encoding of ordinal predictors is that the &lt;span class="math inline"&gt;\(\xi\)&lt;/span&gt; parameters allow different levels of the predictor to contribute to result in a different change in the effect, which is in contrast to what happens when these are included as linear predictors, which is quite common in the literature.&lt;/p&gt;
&lt;div class="sourceCode" id="cb27"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb27-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb27-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;REF_CAT &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb28"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb28-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb28-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, (d450_ax, d455_ax) &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;16&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb28-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb28-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb28-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(pp_df.pivot_table(&lt;span class="st"&gt;'pp_phcs_mean'&lt;/span&gt;, &lt;span class="st"&gt;'d450'&lt;/span&gt;, &lt;span class="st"&gt;'d455'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb28-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb28-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .plot(marker&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'o'&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;d450_ax))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb28-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb28-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d450_ax.set_xticks(d450_cats)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb28-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d450_ax.set_ylabel(&lt;span class="st"&gt;"Posterior predictive phcs"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb28-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb28-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(pp_df.pivot_table(&lt;span class="st"&gt;'pp_phcs_mean'&lt;/span&gt;, &lt;span class="st"&gt;'d455'&lt;/span&gt;, &lt;span class="st"&gt;'d450'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb28-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb28-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .plot(marker&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'o'&lt;/span&gt;, ax&lt;span class="op"&gt;=&lt;/span&gt;d455_ax))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb28-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb28-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d455_ax.set_xticks(d455_cats)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb28-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb28-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/monotonic/Monotonic%20Effects%20in%20PyMC3_35_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The following plot corresponds to Figure 3 in the original paper, and the dark lines agree with the mean in that figure quite well.&lt;/p&gt;
&lt;div class="sourceCode" id="cb29"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb29-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, (d450_ax, d455_ax) &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharey&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;16&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb29-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(pp_df[pp_df[&lt;span class="st"&gt;'d455'&lt;/span&gt;] &lt;span class="op"&gt;!=&lt;/span&gt; REF_CAT]&lt;/span&gt;
&lt;span id="cb29-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .pivot_table(&lt;span class="st"&gt;'pp_phcs_mean'&lt;/span&gt;, &lt;span class="st"&gt;'d450'&lt;/span&gt;, &lt;span class="st"&gt;'d455'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb29-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .plot(marker&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'o'&lt;/span&gt;, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;, legend&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb29-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ax&lt;span class="op"&gt;=&lt;/span&gt;d450_ax))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(pp_df[pp_df[&lt;span class="st"&gt;'d455'&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; REF_CAT]&lt;/span&gt;
&lt;span id="cb29-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .plot(&lt;span class="st"&gt;'d450'&lt;/span&gt;, &lt;span class="st"&gt;'pp_phcs_mean'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb29-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            marker&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'o'&lt;/span&gt;, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb29-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;f"Refernce category (d455 = &lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;REF_CAT&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;)"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb29-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ax&lt;span class="op"&gt;=&lt;/span&gt;d450_ax))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d450_ax.set_xticks(d450_cats)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d450_ax.set_ylabel(&lt;span class="st"&gt;"Posterior excpected phcs"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(pp_df[pp_df[&lt;span class="st"&gt;'d450'&lt;/span&gt;] &lt;span class="op"&gt;!=&lt;/span&gt; REF_CAT]&lt;/span&gt;
&lt;span id="cb29-17"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .pivot_table(&lt;span class="st"&gt;'pp_phcs_mean'&lt;/span&gt;, &lt;span class="st"&gt;'d455'&lt;/span&gt;, &lt;span class="st"&gt;'d450'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb29-18"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .plot(marker&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'o'&lt;/span&gt;, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;, legend&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb29-19"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ax&lt;span class="op"&gt;=&lt;/span&gt;d455_ax))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-20"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(pp_df[pp_df[&lt;span class="st"&gt;'d450'&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; REF_CAT]&lt;/span&gt;
&lt;span id="cb29-21"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .plot(&lt;span class="st"&gt;'d455'&lt;/span&gt;, &lt;span class="st"&gt;'pp_phcs_mean'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb29-22"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            marker&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'o'&lt;/span&gt;, c&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'k'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb29-23"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="ss"&gt;f"Refernce category (d450 = &lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;REF_CAT&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;)"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb29-24"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ax&lt;span class="op"&gt;=&lt;/span&gt;d455_ax))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-25"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-26"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d455_ax.set_xticks(d455_cats)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb29-27"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-28"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb29-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/monotonic/Monotonic%20Effects%20in%20PyMC3_37_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;For reference, we compare this model to a model that includes &lt;code&gt;d450&lt;/code&gt; and &lt;code&gt;d455&lt;/code&gt; as linear predictors. This model is given by&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \mu_i
        &amp;amp; = \beta_0 + \beta_{\textrm{d450}} \cdot j(i) + \beta_{\textrm{d455}} \cdot k(i) \\
    \beta_0, \beta_{\textrm{d450}}, \beta_{\textrm{d455}}
        &amp;amp; \sim N(0, 10^2) \\
    y_i
        &amp;amp; \sim N(\mu_i, \sigma^2) \\
    \sigma
        &amp;amp; \sim \textrm{HalfNormal}(5^2)
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb30"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb30-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb30-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d450_.set_value(d450)&lt;/span&gt;
&lt;span id="cb30-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb30-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;d455_.set_value(d455)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb31"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb31-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb31-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; linear_model:&lt;/span&gt;
&lt;span id="cb31-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb31-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;'β0'&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;10.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb31-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_d450 &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;'β_d450'&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;10.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb31-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_d455 &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;'β_d455'&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;10.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb31-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb31-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb31-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    μ &lt;span class="op"&gt;=&lt;/span&gt; β&lt;span class="dv"&gt;0&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; β_d450 &lt;span class="op"&gt;*&lt;/span&gt; d450_ &lt;span class="op"&gt;+&lt;/span&gt; β_d455 &lt;span class="op"&gt;*&lt;/span&gt; d455_&lt;/span&gt;
&lt;span id="cb31-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb31-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="st"&gt;'σ'&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb31-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    phcs_obs &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;'phcs'&lt;/span&gt;, μ, σ, observed&lt;span class="op"&gt;=&lt;/span&gt;phcs)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb32"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb32-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb32-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; linear_model:&lt;/span&gt;
&lt;span id="cb32-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb32-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    linear_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 2 jobs)
NUTS: [σ, β_d455, β_d450, β0]
Sampling 3 chains: 100%|██████████| 6000/6000 [00:07&amp;lt;00:00, 771.92draws/s] &lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As in the paper, compare these models by stacking their posterioir predictive distributions.&lt;/p&gt;
&lt;div class="sourceCode" id="cb34"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb34-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb34-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;comp_df &lt;span class="op"&gt;=&lt;/span&gt; (pm.compare({&lt;/span&gt;
&lt;span id="cb34-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb34-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                model: trace,&lt;/span&gt;
&lt;span id="cb34-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb34-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                linear_model: linear_trace&lt;/span&gt;
&lt;span id="cb34-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb34-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             })&lt;/span&gt;
&lt;span id="cb34-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb34-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             .rename({&lt;/span&gt;
&lt;span id="cb34-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb34-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 &lt;span class="dv"&gt;0&lt;/span&gt;: &lt;span class="st"&gt;"Paper"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb34-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb34-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 &lt;span class="dv"&gt;1&lt;/span&gt;: &lt;span class="st"&gt;"Linear"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb34-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb34-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             }))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb35"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb35-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html#cb35-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;comp_df&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style scoped&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;center&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
WAIC
&lt;/th&gt;
&lt;th&gt;
pWAIC
&lt;/th&gt;
&lt;th&gt;
dWAIC
&lt;/th&gt;
&lt;th&gt;
weight
&lt;/th&gt;
&lt;th&gt;
SE
&lt;/th&gt;
&lt;th&gt;
dSE
&lt;/th&gt;
&lt;th&gt;
var_warn
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
Paper
&lt;/th&gt;
&lt;td&gt;
2825.24
&lt;/td&gt;
&lt;td&gt;
6.22
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
29.01
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Linear
&lt;/th&gt;
&lt;td&gt;
2830.2
&lt;/td&gt;
&lt;td&gt;
3.7
&lt;/td&gt;
&lt;td&gt;
4.97
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
29.09
&lt;/td&gt;
&lt;td&gt;
4.42
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;
&lt;/div&gt;
&lt;p&gt;We see that the model from the paper has a lower WAIC and gets 100% of the weight, a strong sign that it is surperior to the linear model.&lt;/p&gt;
&lt;p&gt;This post is available as a Jupyter notebook &lt;a href="https://nbviewer.jupyter.org/gist/AustinRochford/166c01cd24979c27ffb5b106904cd802"&gt;here&lt;/a&gt;.&lt;/p&gt;</description><category>Bayesian Statistics</category><category>Papers</category><category>PyMC3</category><guid>https://austinrochford.com/posts/2018-11-10-monotonic-predictors.html</guid><pubDate>Sat, 10 Nov 2018 05:00:00 GMT</pubDate></item><item><title>An Improved Analysis of NBA Foul Calls with Python</title><link>https://austinrochford.com/posts/2018-02-04-nba-irt-2.html</link><dc:creator>Austin Rochford</dc:creator><description>&lt;p&gt;Last April, I wrote a &lt;a href="https://austinrochford.com/posts/2017-04-04-nba-irt.html"&gt;post&lt;/a&gt; that used Bayesian item-response theory models to analyze NBA foul call data. Last November, I &lt;a href="http://austinrochford.com/talks.html#pydata-nyc"&gt;spoke&lt;/a&gt; about a greatly improved version of these models at &lt;a href="https://pydata.org/nyc2017/"&gt;PyData NYC&lt;/a&gt;. This post is a write-up of the models from that talk.&lt;/p&gt;
&lt;h2 id="last-two-minute-report"&gt;Last Two-minute Report&lt;/h2&gt;
&lt;p&gt;Since late in the 2014-2015 season, the NBA has issued &lt;a href="http://official.nba.com/2017-18-nba-officiating-last-two-minute-reports/"&gt;last two minute reports&lt;/a&gt;. These reports give the league’s assessment of the correctness of foul calls and non-calls in the last two minutes of any game where the score difference was three or fewer points at any point in the last two minutes.&lt;/p&gt;
&lt;p&gt;These reports are notably different from play-by-play logs, in that they include information on non-calls for notable on-court interactions. This non-call information presents a unique opportunity to study the factors that impact foul calls. There is a level of subjectivity inherent in the the NBA’s definition of notable on-court interactions which we attempt to mitigate later using season-specific factors.&lt;/p&gt;
&lt;h3 id="loading-the-data"&gt;Loading the data&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://russellgoldenberg.com/"&gt;Russel Goldenberg&lt;/a&gt; of &lt;a href="https://pudding.cool/"&gt;The Pudding&lt;/a&gt; has been scraping the PDFs that the NBA publishes and transforming them into a CSV for some time. I am grateful for his work, which has enabled this analysis.&lt;/p&gt;
&lt;p&gt;We download the data locally to be kind to GitHub.&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb1-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%&lt;/span&gt;matplotlib inline&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb2-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; datetime&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; itertools &lt;span class="im"&gt;import&lt;/span&gt; product&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; logging&lt;/span&gt;
&lt;span id="cb2-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb2-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pickle&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb3-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib &lt;span class="im"&gt;import&lt;/span&gt; pyplot &lt;span class="im"&gt;as&lt;/span&gt; plt&lt;/span&gt;
&lt;span id="cb3-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb3-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib.offsetbox &lt;span class="im"&gt;import&lt;/span&gt; AnchoredText&lt;/span&gt;
&lt;span id="cb3-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb3-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; matplotlib.ticker &lt;span class="im"&gt;import&lt;/span&gt; FuncFormatter, StrMethodFormatter&lt;/span&gt;
&lt;span id="cb3-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb3-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; numpy &lt;span class="im"&gt;as&lt;/span&gt; np&lt;/span&gt;
&lt;span id="cb3-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb3-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pandas &lt;span class="im"&gt;as&lt;/span&gt; pd&lt;/span&gt;
&lt;span id="cb3-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb3-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; scipy &lt;span class="im"&gt;as&lt;/span&gt; sp&lt;/span&gt;
&lt;span id="cb3-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb3-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; seaborn &lt;span class="im"&gt;as&lt;/span&gt; sns&lt;/span&gt;
&lt;span id="cb3-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb3-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; sklearn.preprocessing &lt;span class="im"&gt;import&lt;/span&gt; LabelEncoder&lt;/span&gt;
&lt;span id="cb3-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb3-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;from&lt;/span&gt; theano &lt;span class="im"&gt;import&lt;/span&gt; tensor &lt;span class="im"&gt;as&lt;/span&gt; tt&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb4-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;pct_formatter &lt;span class="op"&gt;=&lt;/span&gt; StrMethodFormatter(&lt;span class="st"&gt;'&lt;/span&gt;&lt;span class="sc"&gt;{x:.1%}&lt;/span&gt;&lt;span class="st"&gt;'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb4-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb4-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb4-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb4-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;sns.&lt;span class="bu"&gt;set&lt;/span&gt;()&lt;/span&gt;
&lt;span id="cb4-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb4-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;blue, green, &lt;span class="op"&gt;*&lt;/span&gt;_ &lt;span class="op"&gt;=&lt;/span&gt; sns.color_palette()&lt;/span&gt;
&lt;span id="cb4-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb4-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb4-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb4-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plt.rc(&lt;span class="st"&gt;'figure'&lt;/span&gt;, figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;8&lt;/span&gt;, &lt;span class="dv"&gt;6&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb4-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb4-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb4-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb4-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;LABELSIZE &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;14&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb4-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb4-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plt.rc(&lt;span class="st"&gt;'axes'&lt;/span&gt;, labelsize&lt;span class="op"&gt;=&lt;/span&gt;LABELSIZE)&lt;/span&gt;
&lt;span id="cb4-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb4-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plt.rc(&lt;span class="st"&gt;'axes'&lt;/span&gt;, titlesize&lt;span class="op"&gt;=&lt;/span&gt;LABELSIZE)&lt;/span&gt;
&lt;span id="cb4-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb4-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plt.rc(&lt;span class="st"&gt;'figure'&lt;/span&gt;, titlesize&lt;span class="op"&gt;=&lt;/span&gt;LABELSIZE)&lt;/span&gt;
&lt;span id="cb4-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb4-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plt.rc(&lt;span class="st"&gt;'legend'&lt;/span&gt;, fontsize&lt;span class="op"&gt;=&lt;/span&gt;LABELSIZE)&lt;/span&gt;
&lt;span id="cb4-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb4-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plt.rc(&lt;span class="st"&gt;'xtick'&lt;/span&gt;, labelsize&lt;span class="op"&gt;=&lt;/span&gt;LABELSIZE)&lt;/span&gt;
&lt;span id="cb4-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb4-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;plt.rc(&lt;span class="st"&gt;'ytick'&lt;/span&gt;, labelsize&lt;span class="op"&gt;=&lt;/span&gt;LABELSIZE)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb5-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SEED &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;207183&lt;/span&gt; &lt;span class="co"&gt;# from random.org, for reproducibility&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb6-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="co"&gt;# keep theano from complaining about compile locks for small models&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb6-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(logging.getLogger(&lt;span class="st"&gt;'theano.gof.compilelock'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb6-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb6-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .setLevel(logging.CRITICAL))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb7-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb7-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;%%&lt;/span&gt;bash&lt;/span&gt;
&lt;span id="cb7-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb7-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;DATA_URI&lt;span class="op"&gt;=&lt;/span&gt;https:&lt;span class="op"&gt;//&lt;/span&gt;raw.githubusercontent.com&lt;span class="op"&gt;/&lt;/span&gt;polygraph&lt;span class="op"&gt;-&lt;/span&gt;cool&lt;span class="op"&gt;/&lt;/span&gt;last&lt;span class="op"&gt;-&lt;/span&gt;two&lt;span class="op"&gt;-&lt;/span&gt;minute&lt;span class="op"&gt;-&lt;/span&gt;report&lt;span class="op"&gt;/&lt;/span&gt;&lt;span class="dv"&gt;32&lt;/span&gt;&lt;span class="er"&gt;f1c43dfa06c2e7652cc51ea65758007f2a1a01&lt;/span&gt;&lt;span class="op"&gt;/&lt;/span&gt;output&lt;span class="op"&gt;/&lt;/span&gt;all_games.csv&lt;/span&gt;
&lt;span id="cb7-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb7-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;DATA_DEST&lt;span class="op"&gt;=/&lt;/span&gt;tmp&lt;span class="op"&gt;/&lt;/span&gt;all_games.csv&lt;/span&gt;
&lt;span id="cb7-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb7-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb7-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb7-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;if&lt;/span&gt; [[ &lt;span class="op"&gt;!&lt;/span&gt; &lt;span class="op"&gt;-&lt;/span&gt;e $DATA_DEST ]]&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb7-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb7-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;then&lt;/span&gt;
&lt;span id="cb7-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb7-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    wget &lt;span class="op"&gt;-&lt;/span&gt;q &lt;span class="op"&gt;-&lt;/span&gt;O $DATA_DEST $DATA_URI&lt;/span&gt;
&lt;span id="cb7-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb7-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fi&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We use only a subset of the columns in the source data set.&lt;/p&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb8-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;USECOLS &lt;span class="op"&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb8-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'period'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb8-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'seconds_left'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb8-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'call_type'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb8-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'committing_player'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb8-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'disadvantaged_player'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb8-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'review_decision'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb8-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'play_id'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb8-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'away'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb8-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'home'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb8-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'date'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb8-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'score_away'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb8-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'score_home'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb8-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'disadvantaged_team'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb8-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb8-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'committing_team'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb8-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb9-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;orig_df &lt;span class="op"&gt;=&lt;/span&gt; pd.read_csv(&lt;/span&gt;
&lt;span id="cb9-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb9-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'/tmp/all_games.csv'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb9-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb9-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    usecols&lt;span class="op"&gt;=&lt;/span&gt;USECOLS,&lt;/span&gt;
&lt;span id="cb9-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb9-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    index_col&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'play_id'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb9-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb9-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    parse_dates&lt;span class="op"&gt;=&lt;/span&gt;[&lt;span class="st"&gt;'date'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb9-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb9-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The data set contains more than 16,000 plays.&lt;/p&gt;
&lt;div class="sourceCode" id="cb10"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb10-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb10-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;orig_df.shape[&lt;span class="dv"&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;16300&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each row of the &lt;code&gt;DataFrame&lt;/code&gt; represents a play and each column describes an attrbiute of the play:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;period&lt;/code&gt; is the period of the game,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;seconds_left&lt;/code&gt; is the number of seconds remaining in the game,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;call_type&lt;/code&gt; is the type of call,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;committing_player&lt;/code&gt; and &lt;code&gt;disadvantaged_player&lt;/code&gt; are the names of the players involved in the play,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;review_decision&lt;/code&gt; is the opinion of the league reviewer on whether or not the play was called correctly:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;review_decision = "INC"&lt;/code&gt; means the call was an incorrect noncall,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;review_decision = "CNC"&lt;/code&gt; means the call was an correct noncall,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;review_decision = "IC"&lt;/code&gt; means the call was an incorrect call, and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;review_decision = "CC"&lt;/code&gt; means the call was an correct call,&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;away&lt;/code&gt; and &lt;code&gt;home&lt;/code&gt; are the abbreviations of the teams involved in the game,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;date&lt;/code&gt; is the date on which the game was played,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;score_away&lt;/code&gt; and &lt;code&gt;score_home&lt;/code&gt; are the scores of the &lt;code&gt;away&lt;/code&gt; and &lt;code&gt;home&lt;/code&gt; team during the play, respectively, and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;disadvantaged_team&lt;/code&gt; and &lt;code&gt;committing_team&lt;/code&gt; indicate how each team is involved in the play.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="sourceCode" id="cb12"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb12-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb12-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;orig_df.head(n&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;).T&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style scoped&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;center&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
play_id
&lt;/th&gt;
&lt;th&gt;
20150301CLEHOU-0
&lt;/th&gt;
&lt;th&gt;
20150301CLEHOU-1
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
period
&lt;/th&gt;
&lt;td&gt;
Q4
&lt;/td&gt;
&lt;td&gt;
Q4
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
seconds_left
&lt;/th&gt;
&lt;td&gt;
112
&lt;/td&gt;
&lt;td&gt;
103
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
call_type
&lt;/th&gt;
&lt;td&gt;
Foul: Shooting
&lt;/td&gt;
&lt;td&gt;
Foul: Shooting
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
committing_player
&lt;/th&gt;
&lt;td&gt;
Josh Smith
&lt;/td&gt;
&lt;td&gt;
J.R. Smith
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
disadvantaged_player
&lt;/th&gt;
&lt;td&gt;
Kevin Love
&lt;/td&gt;
&lt;td&gt;
James Harden
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
review_decision
&lt;/th&gt;
&lt;td&gt;
CNC
&lt;/td&gt;
&lt;td&gt;
CC
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
away
&lt;/th&gt;
&lt;td&gt;
CLE
&lt;/td&gt;
&lt;td&gt;
CLE
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
home
&lt;/th&gt;
&lt;td&gt;
HOU
&lt;/td&gt;
&lt;td&gt;
HOU
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
date
&lt;/th&gt;
&lt;td&gt;
2015-03-01 00:00:00
&lt;/td&gt;
&lt;td&gt;
2015-03-01 00:00:00
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
score_away
&lt;/th&gt;
&lt;td&gt;
103
&lt;/td&gt;
&lt;td&gt;
103
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
score_home
&lt;/th&gt;
&lt;td&gt;
105
&lt;/td&gt;
&lt;td&gt;
105
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
disadvantaged_team
&lt;/th&gt;
&lt;td&gt;
CLE
&lt;/td&gt;
&lt;td&gt;
HOU
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
committing_team
&lt;/th&gt;
&lt;td&gt;
HOU
&lt;/td&gt;
&lt;td&gt;
CLE
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;&lt;/div&gt;

&lt;h3 id="research-questions"&gt;Research questions&lt;/h3&gt;
&lt;p&gt;In this post, we answer two questions:&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;How does game context impact foul calls?&lt;/li&gt;
&lt;li&gt;Is (not) committing and/or drawing fouls a measurable player skill?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The previous post focused on the second question, and gave the first question only a cursory treatment. This post enhances our treatment of the first question, in order to control for non-skill factors influencing foul calls (namely intentional fouls). Controlling for these factors makes our estimates of player skill more realistic.&lt;/p&gt;
&lt;h2 id="exploratory-data-analysis"&gt;Exploratory Data Analysis&lt;/h2&gt;
&lt;p&gt;First we examine the types of calls present in the data set.&lt;/p&gt;
&lt;div class="sourceCode" id="cb13"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb13-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb13-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(orig_df[&lt;span class="st"&gt;'call_type'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb13-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb13-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .value_counts()&lt;/span&gt;
&lt;span id="cb13-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb13-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .head(n&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;15&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Foul: Personal                     4736
Foul: Shooting                     4201
Foul: Offensive                    2846
Foul: Loose Ball                   1316
Turnover: Traveling                 779
Instant Replay: Support Ruling      607
Foul: Defense 3 Second              277
Instant Replay: Overturn Ruling     191
Foul: Personal Take                 172
Turnover: 3 Second Violation        139
Turnover: 24 Second Violation       126
Turnover: 5 Second Inbound           99
Stoppage: Out-of-Bounds              96
Violation: Lane                      84
Foul: Away from Play                 82
Name: call_type, dtype: int64&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The portion of &lt;code&gt;call_type&lt;/code&gt; before the colon is the general category of the call. We count the occurence of these categories below.&lt;/p&gt;
&lt;div class="sourceCode" id="cb15"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb15-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb15-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(orig_df[&lt;span class="st"&gt;'call_type'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb15-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb15-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .&lt;span class="bu"&gt;str&lt;/span&gt;.split(&lt;span class="st"&gt;':'&lt;/span&gt;, expand&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb15-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb15-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .iloc[:, &lt;span class="dv"&gt;0&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb15-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb15-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .value_counts()&lt;/span&gt;
&lt;span id="cb15-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb15-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .plot(&lt;/span&gt;
&lt;span id="cb15-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb15-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'bar'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb15-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb15-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            color&lt;span class="op"&gt;=&lt;/span&gt;blue, logy&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, &lt;/span&gt;
&lt;span id="cb15-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb15-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            title&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Call types"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb15-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb15-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        )&lt;/span&gt;
&lt;span id="cb15-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb15-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .set_ylabel(&lt;span class="st"&gt;"Frequency"&lt;/span&gt;))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_21_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We restrict our attention to foul calls, though other call types would be interesting to study in the future.&lt;/p&gt;
&lt;div class="sourceCode" id="cb16"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb16-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb16-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;foul_df &lt;span class="op"&gt;=&lt;/span&gt; orig_df[&lt;/span&gt;
&lt;span id="cb16-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb16-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    orig_df[&lt;span class="st"&gt;'call_type'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb16-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb16-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           .fillna(&lt;span class="st"&gt;"UNKNOWN"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb16-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb16-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;           .&lt;span class="bu"&gt;str&lt;/span&gt;.startswith(&lt;span class="st"&gt;"Foul"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb16-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb16-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We count the foul call types below.&lt;/p&gt;
&lt;div class="sourceCode" id="cb17"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb17-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb17-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(foul_df[&lt;span class="st"&gt;'call_type'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb17-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb17-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .&lt;span class="bu"&gt;str&lt;/span&gt;.split(&lt;span class="st"&gt;': '&lt;/span&gt;, expand&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb17-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb17-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .iloc[:, &lt;span class="dv"&gt;1&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb17-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb17-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .value_counts()&lt;/span&gt;
&lt;span id="cb17-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb17-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .plot(&lt;/span&gt;
&lt;span id="cb17-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb17-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'bar'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb17-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb17-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            color&lt;span class="op"&gt;=&lt;/span&gt;blue, logy&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb17-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb17-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            title&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Foul Types"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb17-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb17-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        )&lt;/span&gt;
&lt;span id="cb17-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb17-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .set_ylabel(&lt;span class="st"&gt;"Frequency"&lt;/span&gt;))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_25_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We restrict our attention to the five foul types below, which generally involve two players. This subset of fouls allows us to pursue our second research question in the most direct manner.&lt;/p&gt;
&lt;div class="sourceCode" id="cb18"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb18-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb18-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;FOULS &lt;span class="op"&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb18-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb18-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="ss"&gt;f"Foul: &lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;foul_type&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb18-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;for&lt;/span&gt; foul_type &lt;span class="kw"&gt;in&lt;/span&gt; [&lt;/span&gt;
&lt;span id="cb18-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb18-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="st"&gt;"Personal"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb18-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb18-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="st"&gt;"Shooting"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb18-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb18-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="st"&gt;"Offensive"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb18-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb18-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="st"&gt;"Loose Ball"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb18-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb18-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="st"&gt;"Away from Play"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb18-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb18-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ]&lt;/span&gt;
&lt;span id="cb18-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb18-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="data-transformation"&gt;Data transformation&lt;/h3&gt;
&lt;p&gt;There are a number of misspelled team names in the data, which we correct.&lt;/p&gt;
&lt;div class="sourceCode" id="cb19"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb19-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb19-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;TEAM_MAP &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb19-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb19-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"NKY"&lt;/span&gt;: &lt;span class="st"&gt;"NYK"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb19-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb19-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"COS"&lt;/span&gt;: &lt;span class="st"&gt;"BOS"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb19-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb19-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"SAT"&lt;/span&gt;: &lt;span class="st"&gt;"SAS"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb19-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb19-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"CHi"&lt;/span&gt;: &lt;span class="st"&gt;"CHI"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb19-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb19-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"LA)"&lt;/span&gt;: &lt;span class="st"&gt;"LAC"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb19-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb19-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"AT)"&lt;/span&gt;: &lt;span class="st"&gt;"ATL"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb19-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb19-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;"ARL"&lt;/span&gt;: &lt;span class="st"&gt;"ATL"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb19-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;
&lt;span id="cb19-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb19-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb19-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb19-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; correct_team_name(col):&lt;/span&gt;
&lt;span id="cb19-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb19-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="kw"&gt;def&lt;/span&gt; _correct_team_name(df):&lt;/span&gt;
&lt;span id="cb19-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb19-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; df[col].&lt;span class="bu"&gt;apply&lt;/span&gt;(&lt;span class="kw"&gt;lambda&lt;/span&gt; team_name: TEAM_MAP.get(team_name, team_name))&lt;/span&gt;
&lt;span id="cb19-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb19-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb19-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb19-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; _correct_team_name&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We also convert each game date to an NBA season.&lt;/p&gt;
&lt;div class="sourceCode" id="cb20"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb20-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb20-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; date_to_season(date):&lt;/span&gt;
&lt;span id="cb20-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb20-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; date &lt;span class="op"&gt;&amp;gt;=&lt;/span&gt; datetime.datetime(&lt;span class="dv"&gt;2017&lt;/span&gt;, &lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;17&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb20-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb20-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="st"&gt;'2017-2018'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb20-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;elif&lt;/span&gt; date &lt;span class="op"&gt;&amp;gt;=&lt;/span&gt; datetime.datetime(&lt;span class="dv"&gt;2016&lt;/span&gt;, &lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;25&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb20-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb20-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="st"&gt;'2016-2017'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb20-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;elif&lt;/span&gt; date &lt;span class="op"&gt;&amp;gt;=&lt;/span&gt; datetime.datetime(&lt;span class="dv"&gt;2015&lt;/span&gt;, &lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;27&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb20-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb20-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="st"&gt;'2015-2016'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb20-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb20-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb20-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb20-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="st"&gt;'2014-2015'&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We clean the data by&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;restricting to plays that occured during the last two minutes of regulation,&lt;/li&gt;
&lt;li&gt;imputing incorrect noncalls when &lt;code&gt;review_decision&lt;/code&gt; is missing,&lt;/li&gt;
&lt;li&gt;correcting team names,&lt;/li&gt;
&lt;li&gt;converting game dates to seasons,&lt;/li&gt;
&lt;li&gt;restricting to the foul types discussed above,&lt;/li&gt;
&lt;li&gt;restricting to the plays that happened during the &lt;a href="https://en.wikipedia.org/wiki/2015%E2%80%9316_NBA_season"&gt;2015-2016&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/2016%E2%80%9317_NBA_season"&gt;2016-2017&lt;/a&gt; regular seasons (those are the only full seasons in the data set as of February 2018), and&lt;/li&gt;
&lt;li&gt;dropping unneeded rows and columns.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="sourceCode" id="cb21"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb21-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;clean_df &lt;span class="op"&gt;=&lt;/span&gt; (foul_df.where(&lt;span class="kw"&gt;lambda&lt;/span&gt; df: df[&lt;span class="st"&gt;'period'&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="st"&gt;"Q4"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb21-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   .where(&lt;span class="kw"&gt;lambda&lt;/span&gt; df: (df[&lt;span class="st"&gt;'date'&lt;/span&gt;].between(datetime.datetime(&lt;span class="dv"&gt;2016&lt;/span&gt;, &lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;25&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb21-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                         datetime.datetime(&lt;span class="dv"&gt;2017&lt;/span&gt;, &lt;span class="dv"&gt;4&lt;/span&gt;, &lt;span class="dv"&gt;12&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb21-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                     &lt;span class="op"&gt;|&lt;/span&gt; df[&lt;span class="st"&gt;'date'&lt;/span&gt;].between(datetime.datetime(&lt;span class="dv"&gt;2015&lt;/span&gt;, &lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="dv"&gt;27&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb21-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                          datetime.datetime(&lt;span class="dv"&gt;2016&lt;/span&gt;, &lt;span class="dv"&gt;5&lt;/span&gt;, &lt;span class="dv"&gt;30&lt;/span&gt;)))&lt;/span&gt;
&lt;span id="cb21-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   )&lt;/span&gt;
&lt;span id="cb21-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   .assign(&lt;/span&gt;
&lt;span id="cb21-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                       review_decision&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="kw"&gt;lambda&lt;/span&gt; df: df[&lt;span class="st"&gt;'review_decision'&lt;/span&gt;].fillna(&lt;span class="st"&gt;"INC"&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb21-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                       committing_team&lt;span class="op"&gt;=&lt;/span&gt;correct_team_name(&lt;span class="st"&gt;'committing_team'&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb21-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                       disadvantged_team&lt;span class="op"&gt;=&lt;/span&gt;correct_team_name(&lt;span class="st"&gt;'disadvantaged_team'&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb21-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                       away&lt;span class="op"&gt;=&lt;/span&gt;correct_team_name(&lt;span class="st"&gt;'away'&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb21-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                       home&lt;span class="op"&gt;=&lt;/span&gt;correct_team_name(&lt;span class="st"&gt;'home'&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb21-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                       season&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="kw"&gt;lambda&lt;/span&gt; df: df[&lt;span class="st"&gt;'date'&lt;/span&gt;].&lt;span class="bu"&gt;apply&lt;/span&gt;(date_to_season)&lt;/span&gt;
&lt;span id="cb21-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   )&lt;/span&gt;
&lt;span id="cb21-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   .where(&lt;span class="kw"&gt;lambda&lt;/span&gt; df: df[&lt;span class="st"&gt;'call_type'&lt;/span&gt;].isin(FOULS))&lt;/span&gt;
&lt;span id="cb21-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   .dropna()&lt;/span&gt;
&lt;span id="cb21-17"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   .drop(&lt;span class="st"&gt;'period'&lt;/span&gt;, axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb21-18"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   .assign(call_type&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="kw"&gt;lambda&lt;/span&gt; df: (df[&lt;span class="st"&gt;'call_type'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb21-19"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                   .&lt;span class="bu"&gt;str&lt;/span&gt;.split(&lt;span class="st"&gt;': '&lt;/span&gt;, expand&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;)  &lt;/span&gt;
&lt;span id="cb21-20"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb21-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                   .iloc[:, &lt;span class="dv"&gt;1&lt;/span&gt;])))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;About 55% of the rows in the original data set remain.&lt;/p&gt;
&lt;div class="sourceCode" id="cb22"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb22-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb22-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;clean_df.shape[&lt;span class="dv"&gt;0&lt;/span&gt;] &lt;span class="op"&gt;/&lt;/span&gt; orig_df.shape[&lt;span class="dv"&gt;0&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;0.5516564417177914&lt;/code&gt;&lt;/pre&gt;
&lt;div class="sourceCode" id="cb24"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb24-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb24-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;clean_df.head(n&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;).T&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style scoped&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;center&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
play_id
&lt;/th&gt;
&lt;th&gt;
20151028INDTOR-1
&lt;/th&gt;
&lt;th&gt;
20151028INDTOR-2
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
seconds_left
&lt;/th&gt;
&lt;td&gt;
89
&lt;/td&gt;
&lt;td&gt;
73
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
call_type
&lt;/th&gt;
&lt;td&gt;
Shooting
&lt;/td&gt;
&lt;td&gt;
Shooting
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
committing_player
&lt;/th&gt;
&lt;td&gt;
Ian Mahinmi
&lt;/td&gt;
&lt;td&gt;
Bismack Biyombo
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
disadvantaged_player
&lt;/th&gt;
&lt;td&gt;
DeMar DeRozan
&lt;/td&gt;
&lt;td&gt;
Paul George
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
review_decision
&lt;/th&gt;
&lt;td&gt;
CC
&lt;/td&gt;
&lt;td&gt;
IC
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
away
&lt;/th&gt;
&lt;td&gt;
IND
&lt;/td&gt;
&lt;td&gt;
IND
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
home
&lt;/th&gt;
&lt;td&gt;
TOR
&lt;/td&gt;
&lt;td&gt;
TOR
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
date
&lt;/th&gt;
&lt;td&gt;
2015-10-28 00:00:00
&lt;/td&gt;
&lt;td&gt;
2015-10-28 00:00:00
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
score_away
&lt;/th&gt;
&lt;td&gt;
99
&lt;/td&gt;
&lt;td&gt;
99
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
score_home
&lt;/th&gt;
&lt;td&gt;
106
&lt;/td&gt;
&lt;td&gt;
106
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
disadvantaged_team
&lt;/th&gt;
&lt;td&gt;
TOR
&lt;/td&gt;
&lt;td&gt;
IND
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
committing_team
&lt;/th&gt;
&lt;td&gt;
IND
&lt;/td&gt;
&lt;td&gt;
TOR
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
disadvantged_team
&lt;/th&gt;
&lt;td&gt;
TOR
&lt;/td&gt;
&lt;td&gt;
IND
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
season
&lt;/th&gt;
&lt;td&gt;
2015-2016
&lt;/td&gt;
&lt;td&gt;
2015-2016
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;&lt;/div&gt;

&lt;p&gt;We use &lt;code&gt;scikit-learn&lt;/code&gt;’s &lt;a href="http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.LabelEncoder.html"&gt;&lt;code&gt;LabelEncoder&lt;/code&gt;&lt;/a&gt; to transform categorical features (call type, player, and season) to integers.&lt;/p&gt;
&lt;div class="sourceCode" id="cb25"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb25-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;call_type_enc &lt;span class="op"&gt;=&lt;/span&gt; LabelEncoder().fit(&lt;/span&gt;
&lt;span id="cb25-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    clean_df[&lt;span class="st"&gt;'call_type'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb25-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb25-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_call_type &lt;span class="op"&gt;=&lt;/span&gt; call_type_enc.classes_.size&lt;/span&gt;
&lt;span id="cb25-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb25-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;player_enc &lt;span class="op"&gt;=&lt;/span&gt; LabelEncoder().fit(&lt;/span&gt;
&lt;span id="cb25-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    np.concatenate((&lt;/span&gt;
&lt;span id="cb25-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        clean_df[&lt;span class="st"&gt;'committing_player'&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb25-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        clean_df[&lt;span class="st"&gt;'disadvantaged_player'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb25-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ))&lt;/span&gt;
&lt;span id="cb25-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb25-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_player &lt;span class="op"&gt;=&lt;/span&gt; player_enc.classes_.size&lt;/span&gt;
&lt;span id="cb25-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb25-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;season_enc &lt;span class="op"&gt;=&lt;/span&gt; LabelEncoder().fit(&lt;/span&gt;
&lt;span id="cb25-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    clean_df[&lt;span class="st"&gt;'season'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb25-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb25-17"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb25-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_season &lt;span class="op"&gt;=&lt;/span&gt; season_enc.classes_.size&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We transform the data by&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rounding &lt;code&gt;seconds_left&lt;/code&gt; to the nearest second (purely for convenience),&lt;/li&gt;
&lt;li&gt;transforming categorical features to integer ids,&lt;/li&gt;
&lt;li&gt;setting &lt;code&gt;foul_called&lt;/code&gt; equal to one or zero depending on whether or not a foul was called, and&lt;/li&gt;
&lt;li&gt;setting &lt;code&gt;score_committing&lt;/code&gt; and &lt;code&gt;score_disadvantaged&lt;/code&gt; to the score of the committing and disadvantaged teams, respectively.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="sourceCode" id="cb26"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb26-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df &lt;span class="op"&gt;=&lt;/span&gt; (clean_df[[&lt;span class="st"&gt;'seconds_left'&lt;/span&gt;]]&lt;/span&gt;
&lt;span id="cb26-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .&lt;span class="bu"&gt;round&lt;/span&gt;(&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb26-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .assign(&lt;/span&gt;
&lt;span id="cb26-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                call_type&lt;span class="op"&gt;=&lt;/span&gt;call_type_enc.transform(clean_df[&lt;span class="st"&gt;'call_type'&lt;/span&gt;]),&lt;/span&gt;
&lt;span id="cb26-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                foul_called&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;1.&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; clean_df[&lt;span class="st"&gt;'review_decision'&lt;/span&gt;].isin([&lt;span class="st"&gt;'CC'&lt;/span&gt;, &lt;span class="st"&gt;'INC'&lt;/span&gt;]),&lt;/span&gt;
&lt;span id="cb26-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                player_committing&lt;span class="op"&gt;=&lt;/span&gt;player_enc.transform(clean_df[&lt;span class="st"&gt;'committing_player'&lt;/span&gt;]),&lt;/span&gt;
&lt;span id="cb26-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                player_disadvantaged&lt;span class="op"&gt;=&lt;/span&gt;player_enc.transform(clean_df[&lt;span class="st"&gt;'disadvantaged_player'&lt;/span&gt;]),&lt;/span&gt;
&lt;span id="cb26-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                score_committing&lt;span class="op"&gt;=&lt;/span&gt;clean_df[&lt;span class="st"&gt;'score_home'&lt;/span&gt;].where(&lt;/span&gt;
&lt;span id="cb26-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    clean_df[&lt;span class="st"&gt;'committing_team'&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; clean_df[&lt;span class="st"&gt;'home'&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb26-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    clean_df[&lt;span class="st"&gt;'score_away'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb26-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                ),&lt;/span&gt;
&lt;span id="cb26-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                score_disadvantaged&lt;span class="op"&gt;=&lt;/span&gt;clean_df[&lt;span class="st"&gt;'score_home'&lt;/span&gt;].where(&lt;/span&gt;
&lt;span id="cb26-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    clean_df[&lt;span class="st"&gt;'disadvantaged_team'&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; clean_df[&lt;span class="st"&gt;'home'&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb26-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    clean_df[&lt;span class="st"&gt;'score_away'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb26-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                ),&lt;/span&gt;
&lt;span id="cb26-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                season&lt;span class="op"&gt;=&lt;/span&gt;season_enc.transform(clean_df[&lt;span class="st"&gt;'season'&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb26-17"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb26-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              ))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The resulting data is ready for analysis.&lt;/p&gt;
&lt;div class="sourceCode" id="cb27"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb27-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb27-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df.head(n&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;).T&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style scoped&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;center&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
play_id
&lt;/th&gt;
&lt;th&gt;
20151028INDTOR-1
&lt;/th&gt;
&lt;th&gt;
20151028INDTOR-2
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
seconds_left
&lt;/th&gt;
&lt;td&gt;
89.0
&lt;/td&gt;
&lt;td&gt;
73.0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
call_type
&lt;/th&gt;
&lt;td&gt;
4.0
&lt;/td&gt;
&lt;td&gt;
4.0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
foul_called
&lt;/th&gt;
&lt;td&gt;
1.0
&lt;/td&gt;
&lt;td&gt;
0.0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
player_committing
&lt;/th&gt;
&lt;td&gt;
162.0
&lt;/td&gt;
&lt;td&gt;
36.0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
player_disadvantaged
&lt;/th&gt;
&lt;td&gt;
98.0
&lt;/td&gt;
&lt;td&gt;
358.0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
score_committing
&lt;/th&gt;
&lt;td&gt;
99.0
&lt;/td&gt;
&lt;td&gt;
106.0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
score_disadvantaged
&lt;/th&gt;
&lt;td&gt;
106.0
&lt;/td&gt;
&lt;td&gt;
99.0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
season
&lt;/th&gt;
&lt;td&gt;
0.0
&lt;/td&gt;
&lt;td&gt;
0.0
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;&lt;/div&gt;

&lt;h2 id="modeling"&gt;Modeling&lt;/h2&gt;
&lt;p&gt;We follow George Box’s modeling workflow, as &lt;a href="http://dustintran.com/talks/Tran_Edward.pdf"&gt;summarized&lt;/a&gt; by Dustin Tran:&lt;/p&gt;
&lt;ol type="1"&gt;
&lt;li&gt;build a model of the science,&lt;/li&gt;
&lt;li&gt;infer the model given data, and&lt;/li&gt;
&lt;li&gt;criticize the model given data.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="baseline-model"&gt;Baseline model&lt;/h3&gt;
&lt;h4 id="build-a-model-of-the-science"&gt;Build a model of the science&lt;/h4&gt;
&lt;p&gt;Below we examine the foul call rate by season.&lt;/p&gt;
&lt;div class="sourceCode" id="cb28"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb28-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb28-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; make_foul_rate_yaxis(ax, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Observed foul call rate"&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb28-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb28-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.yaxis.set_major_formatter(pct_formatter)&lt;/span&gt;
&lt;span id="cb28-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb28-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_ylabel(label)&lt;/span&gt;
&lt;span id="cb28-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb28-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb28-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb28-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; ax&lt;/span&gt;
&lt;span id="cb28-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb28-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb28-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb28-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_foul_rate_yaxis(&lt;/span&gt;
&lt;span id="cb28-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb28-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    df.pivot_table(&lt;span class="st"&gt;'foul_called'&lt;/span&gt;, &lt;span class="st"&gt;'season'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb28-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb28-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .rename(index&lt;span class="op"&gt;=&lt;/span&gt;season_enc.inverse_transform)&lt;/span&gt;
&lt;span id="cb28-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb28-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .rename_axis(&lt;span class="st"&gt;"Season"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb28-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb28-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .plot(kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'bar'&lt;/span&gt;, rot&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;, legend&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb28-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb28-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_45_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;There is a pronounced difference between the foul call rate in the 2015-2016 and 2016-2017 NBA seasons; our first model accounts for this difference.&lt;/p&gt;
&lt;p&gt;We use &lt;a href="http://docs.pymc.io/"&gt;&lt;code&gt;pymc3&lt;/code&gt;&lt;/a&gt; to specify our models. Our first model is given by&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \beta^{\textrm{season}}_s 
        &amp;amp; \sim N(0, 5) \\
    \eta^{\textrm{game}}_k
        &amp;amp; = \beta^{\textrm{season}}_{s(k)} \\
    p_k
        &amp;amp; = \textrm{sigm}\left(\eta^{\textrm{game}}_k\right).
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;We use a logistic regression model with different factors for each season.&lt;/p&gt;
&lt;div class="sourceCode" id="cb29"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb29-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb29-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="im"&gt;import&lt;/span&gt; pymc3 &lt;span class="im"&gt;as&lt;/span&gt; pm&lt;/span&gt;
&lt;span id="cb29-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb29-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb29-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb29-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; base_model:&lt;/span&gt;
&lt;span id="cb29-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb29-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_season &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;'β_season'&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;n_season)&lt;/span&gt;
&lt;span id="cb29-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb29-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    p &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;span class="st"&gt;'p'&lt;/span&gt;, pm.math.sigmoid(β_season))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Foul calls are Bernoulli trials, &lt;span class="math inline"&gt;\(y_k \sim \textrm{Bernoulli}(p_k).\)&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb30"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb30-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb30-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;season &lt;span class="op"&gt;=&lt;/span&gt; df[&lt;span class="st"&gt;'season'&lt;/span&gt;].values&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb31"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb31-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb31-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; base_model:&lt;/span&gt;
&lt;span id="cb31-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb31-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    y &lt;span class="op"&gt;=&lt;/span&gt; pm.Bernoulli(&lt;/span&gt;
&lt;span id="cb31-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb31-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'y'&lt;/span&gt;, p[season],&lt;/span&gt;
&lt;span id="cb31-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb31-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        observed&lt;span class="op"&gt;=&lt;/span&gt;df[&lt;span class="st"&gt;'foul_called'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb31-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb31-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="infer-the-model-given-data"&gt;Infer the model given data&lt;/h4&gt;
&lt;p&gt;We now sample from the model’s posterior distribution.&lt;/p&gt;
&lt;div class="sourceCode" id="cb32"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb32-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb32-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;NJOBS &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb32-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb32-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb32-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;SAMPLE_KWARGS &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb32-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb32-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'draws'&lt;/span&gt;: &lt;span class="dv"&gt;1000&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb32-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb32-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'njobs'&lt;/span&gt;: NJOBS,&lt;/span&gt;
&lt;span id="cb32-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb32-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'random_seed'&lt;/span&gt;: [&lt;/span&gt;
&lt;span id="cb32-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb32-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        SEED &lt;span class="op"&gt;+&lt;/span&gt; i &lt;span class="cf"&gt;for&lt;/span&gt; i &lt;span class="kw"&gt;in&lt;/span&gt; &lt;span class="bu"&gt;range&lt;/span&gt;(NJOBS)&lt;/span&gt;
&lt;span id="cb32-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb32-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ],&lt;/span&gt;
&lt;span id="cb32-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb32-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'nuts_kwargs'&lt;/span&gt;: {&lt;/span&gt;
&lt;span id="cb32-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb32-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'target_accept'&lt;/span&gt;: &lt;span class="fl"&gt;0.9&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb32-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb32-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    }&lt;/span&gt;
&lt;span id="cb32-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb32-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb33"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb33-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb33-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; base_model:&lt;/span&gt;
&lt;span id="cb33-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb33-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    base_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [β_season]
100%|██████████| 1500/1500 [00:07&amp;lt;00:00, 198.65it/s]&lt;/code&gt;&lt;/pre&gt;
&lt;h5 id="convergence-diagnostics"&gt;Convergence diagnostics&lt;/h5&gt;
&lt;p&gt;We rely on three diagnostics to ensure that our samples have converged to the posterior distribution:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Energy plots: if the two distributions in the energy plot differ significantly (espescially in the tails), the sampling was not very efficient.&lt;/li&gt;
&lt;li&gt;Bayesian fraction of missing information (BFMI): BFMI quantifies this difference with a number between zero and one. A BFMI close to (or exceeding) one is preferable, and a BFMI lower than 0.2 is indicative of efficiency issues.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.stata.com/2016/05/26/gelman-rubin-convergence-diagnostic-using-multiple-chains/"&gt;Gelman-Rubin statistics&lt;/a&gt;: Gelman-Rubin statistics near one are preferable, and values less than 1.1 are generally taken to indicate convergence.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more information on energy plots and BFMI consult &lt;a href="http://mc-stan.org/users/documentation/case-studies/pystan_workflow.html"&gt;&lt;em&gt;Robust Statistical Workflow with PyStan&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb35"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb35-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb35-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;bfmi &lt;span class="op"&gt;=&lt;/span&gt; pm.bfmi(base_trace)&lt;/span&gt;
&lt;span id="cb35-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb35-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb35-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb35-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;max_gr &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="bu"&gt;max&lt;/span&gt;(&lt;/span&gt;
&lt;span id="cb35-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb35-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    np.&lt;span class="bu"&gt;max&lt;/span&gt;(gr_stats) &lt;span class="cf"&gt;for&lt;/span&gt; gr_stats &lt;span class="kw"&gt;in&lt;/span&gt; pm.gelman_rubin(base_trace).values()&lt;/span&gt;
&lt;span id="cb35-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb35-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb36"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb36-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb36-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;CONVERGENCE_TITLE &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="kw"&gt;lambda&lt;/span&gt;: &lt;span class="ss"&gt;f"BFMI = &lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;bfmi&lt;span class="sc"&gt;:.2f}&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="ss"&gt;Gelman-Rubin = &lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;max_gr&lt;span class="sc"&gt;:.3f}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb37"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb37-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb37-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(pm.energyplot(base_trace, legend&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;6&lt;/span&gt;, &lt;span class="dv"&gt;4&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb37-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb37-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   .set_title(CONVERGENCE_TITLE()))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_57_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;h4 id="criticize-the-model-given-data"&gt;Criticize the model given data&lt;/h4&gt;
&lt;p&gt;We use the samples from &lt;code&gt;p&lt;/code&gt;’s posterior distribution to calculate &lt;a href="https://en.wikipedia.org/wiki/Errors_and_residuals"&gt;residuals&lt;/a&gt;, which we use to criticize our models. These residuals allow us to assess how well our model describes the data-generation process and to discover unmodeled sources of variation.&lt;/p&gt;
&lt;div class="sourceCode" id="cb38"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb38-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb38-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;base_trace[&lt;span class="st"&gt;'p'&lt;/span&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;array([[ 0.4052151 ,  0.30696232],
       [ 0.3937377 ,  0.30995026],
       [ 0.39881138,  0.29866616],
       ..., 
       [ 0.40279887,  0.31166828],
       [ 0.4077945 ,  0.30299785],
       [ 0.40207901,  0.29991789]])&lt;/code&gt;&lt;/pre&gt;
&lt;div class="sourceCode" id="cb40"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb40-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb40-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;resid_df &lt;span class="op"&gt;=&lt;/span&gt; (df.assign(p_hat&lt;span class="op"&gt;=&lt;/span&gt;base_trace[&lt;span class="st"&gt;'p'&lt;/span&gt;][:, df[&lt;span class="st"&gt;'season'&lt;/span&gt;]].mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb40-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb40-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .assign(resid&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="kw"&gt;lambda&lt;/span&gt; df: df[&lt;span class="st"&gt;'foul_called'&lt;/span&gt;] &lt;span class="op"&gt;-&lt;/span&gt; df[&lt;span class="st"&gt;'p_hat'&lt;/span&gt;]))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb41"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb41-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb41-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;resid_df[[&lt;span class="st"&gt;'foul_called'&lt;/span&gt;, &lt;span class="st"&gt;'p_hat'&lt;/span&gt;, &lt;span class="st"&gt;'resid'&lt;/span&gt;]].head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style scoped&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;center&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
foul_called
&lt;/th&gt;
&lt;th&gt;
p_hat
&lt;/th&gt;
&lt;th&gt;
resid
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
play_id
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
20151028INDTOR-1
&lt;/th&gt;
&lt;td&gt;
1.0
&lt;/td&gt;
&lt;td&gt;
0.403875
&lt;/td&gt;
&lt;td&gt;
0.596125
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
20151028INDTOR-2
&lt;/th&gt;
&lt;td&gt;
0.0
&lt;/td&gt;
&lt;td&gt;
0.403875
&lt;/td&gt;
&lt;td&gt;
-0.403875
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
20151028INDTOR-3
&lt;/th&gt;
&lt;td&gt;
1.0
&lt;/td&gt;
&lt;td&gt;
0.403875
&lt;/td&gt;
&lt;td&gt;
0.596125
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
20151028INDTOR-4
&lt;/th&gt;
&lt;td&gt;
0.0
&lt;/td&gt;
&lt;td&gt;
0.403875
&lt;/td&gt;
&lt;td&gt;
-0.403875
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
20151028INDTOR-6
&lt;/th&gt;
&lt;td&gt;
0.0
&lt;/td&gt;
&lt;td&gt;
0.403875
&lt;/td&gt;
&lt;td&gt;
-0.403875
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;&lt;/div&gt;

&lt;p&gt;The per-season residuals are quite small, which is to be expected.&lt;/p&gt;
&lt;div class="sourceCode" id="cb42"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb42-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb42-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(resid_df.pivot_table(&lt;span class="st"&gt;'resid'&lt;/span&gt;, &lt;span class="st"&gt;'season'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb42-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb42-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;         .rename(index&lt;span class="op"&gt;=&lt;/span&gt;season_enc.inverse_transform))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style scoped&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;center&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
resid
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
season
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
2015-2016
&lt;/th&gt;
&lt;td&gt;
-0.000162
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2016-2017
&lt;/th&gt;
&lt;td&gt;
-0.000219
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;&lt;/div&gt;

&lt;p&gt;Anyone who has watched a close basketball game will realize that we have neglected an important factor in late game foul calls — &lt;a href="https://en.wikipedia.org/wiki/Flagrant_foul#Game_tactics"&gt;intentional fouls&lt;/a&gt;. Near the end of the game, intentional fouls are used by the losing team when they are on defense to end the leading team’s possession as quickly as possible.&lt;/p&gt;
&lt;p&gt;The influence of intentional fouls in the plot below is shown by the rapidly increasing of the residuals as the number of seconds left in the game decreases.&lt;/p&gt;
&lt;div class="sourceCode" id="cb43"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb43-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb43-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; make_time_axes(ax,&lt;/span&gt;
&lt;span id="cb43-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb43-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   xlabel&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Seconds remaining in game"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb43-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb43-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   ylabel&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Observed foul call rate"&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb43-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb43-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.invert_xaxis()&lt;/span&gt;
&lt;span id="cb43-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb43-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_xlabel(xlabel)&lt;/span&gt;
&lt;span id="cb43-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb43-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb43-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb43-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; make_foul_rate_yaxis(ax, label&lt;span class="op"&gt;=&lt;/span&gt;ylabel)&lt;/span&gt;
&lt;span id="cb43-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb43-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb43-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb43-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_time_axes(&lt;/span&gt;
&lt;span id="cb43-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb43-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    resid_df.pivot_table(&lt;span class="st"&gt;'resid'&lt;/span&gt;, &lt;span class="st"&gt;'seconds_left'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb43-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb43-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .reset_index()&lt;/span&gt;
&lt;span id="cb43-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb43-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .plot(&lt;span class="st"&gt;'seconds_left'&lt;/span&gt;, &lt;span class="st"&gt;'resid'&lt;/span&gt;, kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'scatter'&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb43-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb43-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ylabel&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Residual"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb43-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb43-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_65_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;h3 id="possession-model"&gt;Possession model&lt;/h3&gt;
&lt;h4 id="build-a-model-of-the-science-1"&gt;Build a model of the science&lt;/h4&gt;
&lt;p&gt;The following plot illustrates the fact that only the trailing team has any incentive to committ intentional fouls.&lt;/p&gt;
&lt;div class="sourceCode" id="cb44"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb44-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb44-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df[&lt;span class="st"&gt;'trailing_committing'&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (df[&lt;span class="st"&gt;'score_committing'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb44-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb44-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               .lt(df[&lt;span class="st"&gt;'score_disadvantaged'&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb44-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb44-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               .mul(&lt;span class="fl"&gt;1.&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb44-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb44-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                               .astype(np.int64))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb45"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb45-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_time_axes(&lt;/span&gt;
&lt;span id="cb45-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    df.pivot_table(&lt;/span&gt;
&lt;span id="cb45-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'foul_called'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb45-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'seconds_left'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb45-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'trailing_committing'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      )&lt;/span&gt;
&lt;span id="cb45-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .rolling(&lt;span class="dv"&gt;20&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb45-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .mean()&lt;/span&gt;
&lt;span id="cb45-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .rename(columns&lt;span class="op"&gt;=&lt;/span&gt;{&lt;/span&gt;
&lt;span id="cb45-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          &lt;span class="dv"&gt;0&lt;/span&gt;: &lt;span class="st"&gt;"No"&lt;/span&gt;, &lt;span class="dv"&gt;1&lt;/span&gt;: &lt;span class="st"&gt;"Yes"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      })&lt;/span&gt;
&lt;span id="cb45-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .rename_axis(&lt;/span&gt;
&lt;span id="cb45-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          &lt;span class="st"&gt;"Committing team is trailing"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb45-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb45-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      )&lt;/span&gt;
&lt;span id="cb45-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .plot()&lt;/span&gt;
&lt;span id="cb45-17"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb45-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_68_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Intentional fouls are only useful when the trailing (and committing) team is on defense. The plot below reflects this fact; shooting and personal fouls are almost always called against the defensive player; we see that they are called at a much higher rate than offensive fouls.&lt;/p&gt;
&lt;div class="sourceCode" id="cb46"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb46-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb46-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; (df.pivot_table(&lt;span class="st"&gt;'foul_called'&lt;/span&gt;, &lt;span class="st"&gt;'call_type'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb46-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb46-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .rename(index&lt;span class="op"&gt;=&lt;/span&gt;call_type_enc.inverse_transform)&lt;/span&gt;
&lt;span id="cb46-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb46-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .rename_axis(&lt;span class="st"&gt;"Call type"&lt;/span&gt;, axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb46-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb46-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        .plot(kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'barh'&lt;/span&gt;, legend&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb46-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb46-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb46-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb46-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.xaxis.set_major_formatter(pct_formatter)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb46-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb46-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Observed foul call rate"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_70_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We continue to model the differnce in foul call rates between seasons.&lt;/p&gt;
&lt;div class="sourceCode" id="cb47"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb47-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb47-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; poss_model:&lt;/span&gt;
&lt;span id="cb47-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb47-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_season &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;'β_season'&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Throughout this post, we will use &lt;a href="https://en.wikipedia.org/wiki/Multilevel_model"&gt;hierarchical distributions&lt;/a&gt; to model the variation of foul call rates. For much more information on hierarchical models, consult &lt;a href="http://www.stat.columbia.edu/~gelman/arm/"&gt;&lt;em&gt;Data Analysis Using Regression and Multilevel/Hierarchical Models&lt;/em&gt;&lt;/a&gt;. We use the priors&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \sigma_{\textrm{call}}
        &amp;amp; \sim \operatorname{HalfNormal}(5) \\
    \beta^{\textrm{call}}_{c}
        &amp;amp; \sim \operatorname{Hierarchical-Normal}(0, \sigma_{\textrm{call}}^2).
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;For sampling efficiency, we use an [non-centered parametrization](http://twiecki.github.io/blog/2017/02/08/bayesian-hierchical-non-centered/#The-Funnel-of-Hell-(and-how-to-escape-it%29) of the hierarchical normal distribution.&lt;/p&gt;
&lt;div class="sourceCode" id="cb48"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb48-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb48-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; hierarchical_normal(name, shape, σ_shape&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;):&lt;/span&gt;
&lt;span id="cb48-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb48-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    Δ &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="ss"&gt;f'Δ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;'&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;1.&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;shape)&lt;/span&gt;
&lt;span id="cb48-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb48-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    σ &lt;span class="op"&gt;=&lt;/span&gt; pm.HalfNormal(&lt;span class="ss"&gt;f'σ_&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;name&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;'&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;σ_shape)&lt;/span&gt;
&lt;span id="cb48-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb48-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb48-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb48-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; pm.Deterministic(name, Δ &lt;span class="op"&gt;*&lt;/span&gt; σ)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Each call type has a different foul call rate.&lt;/p&gt;
&lt;div class="sourceCode" id="cb49"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb49-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb49-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; poss_model:&lt;/span&gt;
&lt;span id="cb49-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb49-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_call &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal(&lt;span class="st"&gt;'β_call'&lt;/span&gt;, n_call_type)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We add score difference and the number of possessions by which the committing team is trailing to the &lt;code&gt;DataFrame&lt;/code&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb50"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb50-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb50-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df[&lt;span class="st"&gt;'score_diff'&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (df[&lt;span class="st"&gt;'score_disadvantaged'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb50-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb50-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                      .sub(df[&lt;span class="st"&gt;'score_committing'&lt;/span&gt;]))&lt;/span&gt;
&lt;span id="cb50-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb50-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb50-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb50-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df[&lt;span class="st"&gt;'trailing_poss'&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (df[&lt;span class="st"&gt;'score_diff'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb50-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb50-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         .div(&lt;span class="dv"&gt;3&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb50-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb50-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                         .&lt;span class="bu"&gt;apply&lt;/span&gt;(np.ceil))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb51"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb51-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb51-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;trailing_poss_enc &lt;span class="op"&gt;=&lt;/span&gt; LabelEncoder().fit(df[&lt;span class="st"&gt;'trailing_poss'&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb51-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb51-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;trailing_poss &lt;span class="op"&gt;=&lt;/span&gt; trailing_poss_enc.transform(df[&lt;span class="st"&gt;'trailing_poss'&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb51-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb51-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_trailing_poss &lt;span class="op"&gt;=&lt;/span&gt; trailing_poss_enc.classes_.size&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The plot below shows that the foul call rate (over time) varies based on the score difference (quantized into possessions) between the disadvanted team and the committing team. We assume that at most three points can be scored in a single possession (while this is not quite correct, &lt;a href="https://en.wikipedia.org/wiki/Four-point_play"&gt;four-point plays&lt;/a&gt; are rare enough that we do not account for them in our analysis).&lt;/p&gt;
&lt;div class="sourceCode" id="cb52"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb52-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb52-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_time_axes(&lt;/span&gt;
&lt;span id="cb52-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb52-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    df.pivot_table(&lt;/span&gt;
&lt;span id="cb52-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb52-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'foul_called'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb52-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb52-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'seconds_left'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb52-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb52-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'trailing_poss'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb52-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      )&lt;/span&gt;
&lt;span id="cb52-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb52-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .loc[:, &lt;span class="dv"&gt;1&lt;/span&gt;:&lt;span class="dv"&gt;3&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb52-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb52-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .rolling(&lt;span class="dv"&gt;20&lt;/span&gt;).mean()&lt;/span&gt;
&lt;span id="cb52-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb52-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .rename_axis(&lt;/span&gt;
&lt;span id="cb52-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb52-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          &lt;span class="st"&gt;"Trailing possessions&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;(committing team)"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb52-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb52-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb52-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb52-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      )&lt;/span&gt;
&lt;span id="cb52-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb52-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .plot()&lt;/span&gt;
&lt;span id="cb52-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb52-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_81_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The plot below reflects the fact that intentional fouls are disproportionately personal fouls; the rate at which personal fouls are called increases drastically as the game nears its end.&lt;/p&gt;
&lt;div class="sourceCode" id="cb53"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb53-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb53-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_time_axes(&lt;/span&gt;
&lt;span id="cb53-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb53-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    df.pivot_table(&lt;span class="st"&gt;'foul_called'&lt;/span&gt;, &lt;span class="st"&gt;'seconds_left'&lt;/span&gt;, &lt;span class="st"&gt;'call_type'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb53-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb53-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .rolling(&lt;span class="dv"&gt;20&lt;/span&gt;).mean()&lt;/span&gt;
&lt;span id="cb53-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb53-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .rename(columns&lt;span class="op"&gt;=&lt;/span&gt;call_type_enc.inverse_transform)&lt;/span&gt;
&lt;span id="cb53-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb53-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .rename_axis(&lt;span class="va"&gt;None&lt;/span&gt;, axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb53-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb53-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .plot()&lt;/span&gt;
&lt;span id="cb53-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb53-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_83_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Due to the NBA’s &lt;a href="https://en.wikipedia.org/wiki/Shot_clock"&gt;shot clock&lt;/a&gt;, the natural timescale of a basketball game is possessions, not seconds, remaining.&lt;/p&gt;
&lt;div class="sourceCode" id="cb54"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb54-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb54-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;df[&lt;span class="st"&gt;'remaining_poss'&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; (df[&lt;span class="st"&gt;'seconds_left'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb54-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb54-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                          .floordiv(&lt;span class="dv"&gt;25&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb54-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb54-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                          .add(&lt;span class="dv"&gt;1&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb55"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb55-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb55-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;remaining_poss_enc &lt;span class="op"&gt;=&lt;/span&gt; LabelEncoder().fit(df[&lt;span class="st"&gt;'remaining_poss'&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb55-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb55-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;remaining_poss &lt;span class="op"&gt;=&lt;/span&gt; remaining_poss_enc.transform(df[&lt;span class="st"&gt;'remaining_poss'&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb55-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb55-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_remaining_poss &lt;span class="op"&gt;=&lt;/span&gt; remaining_poss_enc.classes_.size&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Below we plot the foul call rate across trailing possession/remaining posession pairs. Note that we always calculate trailing possessions (&lt;code&gt;trailing_poss&lt;/code&gt;) from the perspective of the committing team. For instance, &lt;code&gt;trailing_poss = 1&lt;/code&gt; indicates that the committing team is trailing by 1-3 points, whereas &lt;code&gt;trailing_poss = -1&lt;/code&gt; indicates that the committing team is leading by 1-3 points.&lt;/p&gt;
&lt;div class="sourceCode" id="cb56"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb56-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; sns.heatmap(&lt;/span&gt;
&lt;span id="cb56-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    df.pivot_table(&lt;/span&gt;
&lt;span id="cb56-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'foul_called'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb56-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'trailing_poss'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb56-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'remaining_poss'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb56-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      )&lt;/span&gt;
&lt;span id="cb56-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .rename_axis(&lt;/span&gt;
&lt;span id="cb56-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          &lt;span class="st"&gt;"Trailing possessions&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;(committing team)"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb56-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;          axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb56-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      )&lt;/span&gt;
&lt;span id="cb56-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;      .rename_axis(&lt;span class="st"&gt;"Remaining possessions"&lt;/span&gt;, axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb56-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    cmap&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'seismic'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb56-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    cbar_kws&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;'format'&lt;/span&gt;: pct_formatter}&lt;/span&gt;
&lt;span id="cb56-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb56-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb56-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.invert_yaxis()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb56-17"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb56-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Observed foul call rate"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_88_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The heatmap above shows that the foul call rate increases significantly when the committing team is trailing by more than the number of possessions remaining in the game. That is, teams resort to intentional fouls only when the opposing team can run out the clock and guarantee a win. (Since we have quantized the score difference and time into posessions, this conclusion is not entirely correct; it is, however, correct enough for our purposes.)&lt;/p&gt;
&lt;div class="sourceCode" id="cb57"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb57-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb57-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;call_name_df &lt;span class="op"&gt;=&lt;/span&gt; df.assign(&lt;/span&gt;
&lt;span id="cb57-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb57-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    call_type&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="kw"&gt;lambda&lt;/span&gt; df: call_type_enc.inverse_transform(&lt;/span&gt;
&lt;span id="cb57-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb57-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        df[&lt;span class="st"&gt;'call_type'&lt;/span&gt;].values&lt;/span&gt;
&lt;span id="cb57-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb57-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb57-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb57-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb57-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb57-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb57-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb57-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;diff_df &lt;span class="op"&gt;=&lt;/span&gt; (pd.merge(&lt;/span&gt;
&lt;span id="cb57-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb57-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                call_name_df,&lt;/span&gt;
&lt;span id="cb57-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb57-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                call_name_df.groupby(&lt;span class="st"&gt;'call_type'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb57-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb57-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                            [&lt;span class="st"&gt;'foul_called'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb57-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb57-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                            .mean()&lt;/span&gt;
&lt;span id="cb57-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb57-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                            .rename(&lt;span class="st"&gt;'avg_foul_called'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb57-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb57-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                            .reset_index()&lt;/span&gt;
&lt;span id="cb57-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb57-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             )&lt;/span&gt;
&lt;span id="cb57-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb57-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             .assign(diff&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="kw"&gt;lambda&lt;/span&gt; df: df[&lt;span class="st"&gt;'foul_called'&lt;/span&gt;] &lt;span class="op"&gt;-&lt;/span&gt; df[&lt;span class="st"&gt;'avg_foul_called'&lt;/span&gt;]))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The heatmaps below are broken out by call type, and show the difference between the foul call rate for each trailing/remaining possession combination and the overall foul call rate for the call type in question&lt;/p&gt;
&lt;div class="sourceCode" id="cb58"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb58-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; plot_foul_diff_heatmap(&lt;span class="op"&gt;*&lt;/span&gt;_, data&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;None&lt;/span&gt;, &lt;span class="op"&gt;**&lt;/span&gt;kwargs):&lt;/span&gt;
&lt;span id="cb58-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax &lt;span class="op"&gt;=&lt;/span&gt; plt.gca()&lt;/span&gt;
&lt;span id="cb58-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb58-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    sns.heatmap(&lt;/span&gt;
&lt;span id="cb58-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        data.pivot_table(&lt;/span&gt;
&lt;span id="cb58-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="st"&gt;'diff'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb58-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="st"&gt;'trailing_poss'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb58-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;span class="st"&gt;'remaining_poss'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb58-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ),&lt;/span&gt;
&lt;span id="cb58-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        cmap&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'seismic'&lt;/span&gt;, robust&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb58-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        cbar_kws&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;'format'&lt;/span&gt;: pct_formatter}&lt;/span&gt;
&lt;span id="cb58-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb58-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb58-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.invert_yaxis()&lt;/span&gt;
&lt;span id="cb58-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_title(&lt;span class="st"&gt;"Observed foul call rate"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb58-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb58-17"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(sns.FacetGrid(diff_df, col&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'call_type'&lt;/span&gt;, col_wrap&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;3&lt;/span&gt;, aspect&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;1.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb58-18"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    .map_dataframe(plot_foul_diff_heatmap)&lt;/span&gt;
&lt;span id="cb58-19"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    .set_axis_labels(&lt;/span&gt;
&lt;span id="cb58-20"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;"Remaining possessions"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb58-21"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;"Trailing possessions&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;(committing team)"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb58-22"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb58-23"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb58-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    .set_titles(&lt;span class="st"&gt;"&lt;/span&gt;&lt;span class="sc"&gt;{col_name}&lt;/span&gt;&lt;span class="st"&gt;"&lt;/span&gt;))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_92_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;These plots confirm that most intentional fouls are personal fouls. They also show that the three-way interaction between trailing possesions, remaining possessions, and call type are important to model foul call rates.&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \sigma_{\textrm{poss}, c}
            &amp;amp; \sim \operatorname{HalfNormal}(5) \\
    \beta^{\textrm{poss}}_{t, r, c}
        &amp;amp; \sim \operatorname{Hierarchical-Normal}(0, \sigma_{\textrm{poss}, c}^2)
\end{align*}    
\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb59"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb59-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb59-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; poss_model:&lt;/span&gt;
&lt;span id="cb59-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb59-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_poss &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal(&lt;/span&gt;
&lt;span id="cb59-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb59-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'β_poss'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb59-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb59-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        (n_trailing_poss, n_remaining_poss, n_call_type),&lt;/span&gt;
&lt;span id="cb59-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb59-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        σ_shape&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;1&lt;/span&gt;, n_call_type)&lt;/span&gt;
&lt;span id="cb59-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb59-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The foul call rate is a combination of season, call type, and possession factors.&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[\eta^{\textrm{game}}_k = \beta^{\textrm{season}}_{s(k)} + \beta^{\textrm{call}}_{c(k)} + \beta^{\textrm{poss}}_{t(k),r(k),c(k)}\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb60"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb60-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb60-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;call_type &lt;span class="op"&gt;=&lt;/span&gt; df[&lt;span class="st"&gt;'call_type'&lt;/span&gt;].values&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb61"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb61-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb61-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; poss_model:&lt;/span&gt;
&lt;span id="cb61-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb61-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    η_game &lt;span class="op"&gt;=&lt;/span&gt; β_season[season] &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb61-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb61-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="op"&gt;+&lt;/span&gt; β_call[call_type] &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb61-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb61-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="op"&gt;+&lt;/span&gt; β_poss[&lt;/span&gt;
&lt;span id="cb61-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb61-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    trailing_poss,&lt;/span&gt;
&lt;span id="cb61-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb61-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    remaining_poss,&lt;/span&gt;
&lt;span id="cb61-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb61-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    call_type&lt;/span&gt;
&lt;span id="cb61-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb61-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
p_k
    &amp;amp; = \operatorname{sigm}\left(\eta^{\textrm{game}}_k\right)
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb62"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb62-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb62-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; poss_model:&lt;/span&gt;
&lt;span id="cb62-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb62-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    p &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;span class="st"&gt;'p'&lt;/span&gt;, pm.math.sigmoid(η_game))&lt;/span&gt;
&lt;span id="cb62-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb62-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    y &lt;span class="op"&gt;=&lt;/span&gt; pm.Bernoulli(&lt;span class="st"&gt;'y'&lt;/span&gt;, p, observed&lt;span class="op"&gt;=&lt;/span&gt;df[&lt;span class="st"&gt;'foul_called'&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="infer-the-model-given-data-1"&gt;Infer the model given data&lt;/h4&gt;
&lt;p&gt;Again, we sample from the model’s posterior distribution.&lt;/p&gt;
&lt;div class="sourceCode" id="cb63"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb63-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb63-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; poss_model:&lt;/span&gt;
&lt;span id="cb63-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb63-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    poss_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [σ_β_poss_log__, Δ_β_poss, σ_β_call_log__, Δ_β_call, β_season]
100%|██████████| 1500/1500 [07:56&amp;lt;00:00,  3.15it/s]
There were 5 divergences after tuning. Increase `target_accept` or reparameterize.
There were 10 divergences after tuning. Increase `target_accept` or reparameterize.
There were 9 divergences after tuning. Increase `target_accept` or reparameterize.
The number of effective samples is smaller than 25% for some parameters.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The BFMI and Gelman-Rubin statistics for this model indicate no problems with sampling and good convergence.&lt;/p&gt;
&lt;div class="sourceCode" id="cb65"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb65-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb65-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;bfmi &lt;span class="op"&gt;=&lt;/span&gt; pm.bfmi(poss_trace)&lt;/span&gt;
&lt;span id="cb65-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb65-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb65-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb65-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;max_gr &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="bu"&gt;max&lt;/span&gt;(&lt;/span&gt;
&lt;span id="cb65-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb65-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    np.&lt;span class="bu"&gt;max&lt;/span&gt;(gr_stats) &lt;span class="cf"&gt;for&lt;/span&gt; gr_stats &lt;span class="kw"&gt;in&lt;/span&gt; pm.gelman_rubin(poss_trace).values()&lt;/span&gt;
&lt;span id="cb65-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb65-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb66"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb66-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb66-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(pm.energyplot(poss_trace, legend&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;6&lt;/span&gt;, &lt;span class="dv"&gt;4&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb66-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb66-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   .set_title(CONVERGENCE_TITLE()))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_105_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;h4 id="criticize-the-model-given-data-1"&gt;Criticize the model given data&lt;/h4&gt;
&lt;p&gt;Again, we calculate residuals.&lt;/p&gt;
&lt;div class="sourceCode" id="cb67"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb67-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb67-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;resid_df &lt;span class="op"&gt;=&lt;/span&gt; (df.assign(p_hat&lt;span class="op"&gt;=&lt;/span&gt;poss_trace[&lt;span class="st"&gt;'p'&lt;/span&gt;].mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb67-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb67-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .assign(resid&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="kw"&gt;lambda&lt;/span&gt; df: df.foul_called &lt;span class="op"&gt;-&lt;/span&gt; df.p_hat))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The following plots show that, grouped various ways, the residuals for this model are relatively well-distributed.&lt;/p&gt;
&lt;div class="sourceCode" id="cb68"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb68-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; sns.heatmap(&lt;/span&gt;
&lt;span id="cb68-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    resid_df.pivot_table(&lt;/span&gt;
&lt;span id="cb68-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="st"&gt;'resid'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb68-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="st"&gt;'trailing_poss'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb68-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="st"&gt;'remaining_poss'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb68-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            )&lt;/span&gt;
&lt;span id="cb68-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .rename_axis(&lt;/span&gt;
&lt;span id="cb68-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="st"&gt;"Trailing possessions&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;(committing team)"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb68-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb68-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            )&lt;/span&gt;
&lt;span id="cb68-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .rename_axis(&lt;/span&gt;
&lt;span id="cb68-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="st"&gt;"Remaining possessions"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb68-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb68-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            )&lt;/span&gt;
&lt;span id="cb68-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .loc[&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;3&lt;/span&gt;:&lt;span class="dv"&gt;3&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb68-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    cmap&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'seismic'&lt;/span&gt;, &lt;/span&gt;
&lt;span id="cb68-17"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    cbar_kws&lt;span class="op"&gt;=&lt;/span&gt;{&lt;span class="st"&gt;'format'&lt;/span&gt;: pct_formatter}&lt;/span&gt;
&lt;span id="cb68-18"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb68-19"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb68-20"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.invert_yaxis()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb68-21"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb68-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Observed foul call rate"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_109_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb69"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb69-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb69-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;N_BIN &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;20&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb69-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb69-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb69-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb69-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;bin_ix, bins &lt;span class="op"&gt;=&lt;/span&gt; pd.qcut(&lt;/span&gt;
&lt;span id="cb69-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb69-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    resid_df.p_hat, N_BIN,&lt;/span&gt;
&lt;span id="cb69-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb69-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    labels&lt;span class="op"&gt;=&lt;/span&gt;np.arange(N_BIN),&lt;/span&gt;
&lt;span id="cb69-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb69-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    retbins&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb69-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb69-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb70"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb70-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb70-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; (resid_df.groupby(bins[bin_ix])&lt;/span&gt;
&lt;span id="cb70-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb70-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .resid.mean()&lt;/span&gt;
&lt;span id="cb70-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb70-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .rename_axis(&lt;span class="st"&gt;'p_hat'&lt;/span&gt;, axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb70-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb70-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .reset_index()&lt;/span&gt;
&lt;span id="cb70-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb70-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .plot(&lt;span class="st"&gt;'p_hat'&lt;/span&gt;, &lt;span class="st"&gt;'resid'&lt;/span&gt;, kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'scatter'&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb70-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb70-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb70-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb70-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.xaxis.set_major_formatter(pct_formatter)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb70-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb70-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="vs"&gt;r"Binned $\hat&lt;/span&gt;&lt;span class="sc"&gt;{p}&lt;/span&gt;&lt;span class="vs"&gt;$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb70-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb70-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb70-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb70-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_foul_rate_yaxis(ax, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Residual"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_111_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb71"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb71-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb71-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; (resid_df.groupby(&lt;span class="st"&gt;'seconds_left'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb71-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb71-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .resid.mean()&lt;/span&gt;
&lt;span id="cb71-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb71-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .reset_index()&lt;/span&gt;
&lt;span id="cb71-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb71-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .plot(&lt;span class="st"&gt;'seconds_left'&lt;/span&gt;, &lt;span class="st"&gt;'resid'&lt;/span&gt;, kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'scatter'&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb71-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb71-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_time_axes(ax, ylabel&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Residual"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_112_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;h4 id="model-selection"&gt;Model selection&lt;/h4&gt;
&lt;p&gt;Now that we have two models, we can engage in &lt;a href="https://en.wikipedia.org/wiki/Model_selection"&gt;model selection&lt;/a&gt;. We use the &lt;a href="http://www.jmlr.org/papers/volume14/watanabe13a/watanabe13a.pdf"&gt;widely applicable Bayesian information criterion&lt;/a&gt; (&lt;a href="http://www.stat.columbia.edu/~gelman/research/published/waic_understand3.pdf"&gt;WAIC&lt;/a&gt;) for model selection.&lt;/p&gt;
&lt;div class="sourceCode" id="cb72"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb72-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb72-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;MODEL_NAME_MAP &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb72-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb72-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dv"&gt;0&lt;/span&gt;: &lt;span class="st"&gt;"Base"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb72-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb72-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dv"&gt;1&lt;/span&gt;: &lt;span class="st"&gt;"Possession"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb72-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb72-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb73"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb73-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb73-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;comp_df &lt;span class="op"&gt;=&lt;/span&gt; (pm.compare(&lt;/span&gt;
&lt;span id="cb73-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb73-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                (base_trace, poss_trace),&lt;/span&gt;
&lt;span id="cb73-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb73-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                (base_model, poss_model)&lt;/span&gt;
&lt;span id="cb73-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb73-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             )&lt;/span&gt;
&lt;span id="cb73-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb73-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             .rename(index&lt;span class="op"&gt;=&lt;/span&gt;MODEL_NAME_MAP)&lt;/span&gt;
&lt;span id="cb73-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb73-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             .loc[MODEL_NAME_MAP.values()])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since smaller WAICs are better, the possession model clearly outperforms the base model.&lt;/p&gt;
&lt;div class="sourceCode" id="cb74"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb74-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb74-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;comp_df&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style scoped&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;center&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
WAIC
&lt;/th&gt;
&lt;th&gt;
pWAIC
&lt;/th&gt;
&lt;th&gt;
dWAIC
&lt;/th&gt;
&lt;th&gt;
weight
&lt;/th&gt;
&lt;th&gt;
SE
&lt;/th&gt;
&lt;th&gt;
dSE
&lt;/th&gt;
&lt;th&gt;
var_warn
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
Base
&lt;/th&gt;
&lt;td&gt;
11610.1
&lt;/td&gt;
&lt;td&gt;
2.11
&lt;/td&gt;
&lt;td&gt;
1541.98
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
56.9
&lt;/td&gt;
&lt;td&gt;
73.43
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Possession
&lt;/th&gt;
&lt;td&gt;
10068.1
&lt;/td&gt;
&lt;td&gt;
82.93
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
88.05
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb75"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb75-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb75-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots()&lt;/span&gt;
&lt;span id="cb75-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb75-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb75-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb75-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.errorbar(&lt;/span&gt;
&lt;span id="cb75-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb75-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    np.arange(&lt;span class="bu"&gt;len&lt;/span&gt;(MODEL_NAME_MAP)),&lt;/span&gt;
&lt;span id="cb75-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb75-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    comp_df.WAIC,&lt;/span&gt;
&lt;span id="cb75-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb75-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    yerr&lt;span class="op"&gt;=&lt;/span&gt;comp_df.SE, fmt&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'o'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb75-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb75-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb75-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb75-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb75-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb75-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xticks(np.arange(&lt;span class="bu"&gt;len&lt;/span&gt;(MODEL_NAME_MAP)))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb75-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb75-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xticklabels(comp_df.index)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb75-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb75-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Model"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb75-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb75-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb75-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb75-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"WAIC"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_118_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;h3 id="player-item-response-theory-model"&gt;Player item-response theory model&lt;/h3&gt;
&lt;h4 id="build-a-model-of-the-science-2"&gt;Build a model of the science&lt;/h4&gt;
&lt;p&gt;We now turn to the question of whether or not committing and/or drawing fouls is a measurable skill. We use an &lt;a href="https://en.wikipedia.org/wiki/Item_response_theory"&gt;item-response theory&lt;/a&gt; (IRT) model to study this question. For more information on Bayesian item-response models, consult the following references.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.stat.columbia.edu/~gelman/research/published/171.pdf"&gt;&lt;em&gt;Practical Issues in Implementing and Understanding Bayesian Ideal Point Estimation&lt;/em&gt;&lt;/a&gt; is an excellent introduction to applied Bayesian IRT models and has inspired much of this work.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.springer.com/us/book/9781441907417"&gt;&lt;em&gt;Bayesian Item Response Modeling — Theory and Applications&lt;/em&gt;&lt;/a&gt; is a comprehensive mathematical overview of Bayesien IRT modeling.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The item-response theory model includes the season, call type, and possession terms of the previous models.&lt;/p&gt;
&lt;div class="sourceCode" id="cb76"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb76-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb76-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; pm.Model() &lt;span class="im"&gt;as&lt;/span&gt; irt_model:&lt;/span&gt;
&lt;span id="cb76-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb76-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_season &lt;span class="op"&gt;=&lt;/span&gt; pm.Normal(&lt;span class="st"&gt;'β_season'&lt;/span&gt;, &lt;span class="fl"&gt;0.&lt;/span&gt;, &lt;span class="fl"&gt;5.&lt;/span&gt;, shape&lt;span class="op"&gt;=&lt;/span&gt;n_season)&lt;/span&gt;
&lt;span id="cb76-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb76-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_call &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal(&lt;span class="st"&gt;'β_call'&lt;/span&gt;, n_call_type)&lt;/span&gt;
&lt;span id="cb76-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb76-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    β_poss &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal(&lt;/span&gt;
&lt;span id="cb76-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb76-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'β_poss'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb76-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb76-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        (n_trailing_poss, n_remaining_poss, n_call_type),&lt;/span&gt;
&lt;span id="cb76-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb76-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        σ_shape&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;1&lt;/span&gt;, &lt;span class="dv"&gt;1&lt;/span&gt;, n_call_type)&lt;/span&gt;
&lt;span id="cb76-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb76-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb76-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb76-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb76-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb76-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    η_game &lt;span class="op"&gt;=&lt;/span&gt; β_season[season] &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb76-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb76-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="op"&gt;+&lt;/span&gt; β_call[call_type] &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb76-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb76-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                &lt;span class="op"&gt;+&lt;/span&gt; β_poss[&lt;/span&gt;
&lt;span id="cb76-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb76-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    trailing_poss,&lt;/span&gt;
&lt;span id="cb76-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb76-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    remaining_poss,&lt;/span&gt;
&lt;span id="cb76-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb76-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    call_type&lt;/span&gt;
&lt;span id="cb76-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb76-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                ]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Each disadvantaged player has an ideal point (per season).&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \sigma_{\theta}
        &amp;amp; \sim \operatorname{HalfNormal}(5) \\
    \theta^{\textrm{player}}_{i, s}
        &amp;amp; \sim \operatorname{Hierarchical-Normal}(0, \sigma_{\theta}^2)
\end{align*}
\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb77"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb77-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb77-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;player_disadvantaged &lt;span class="op"&gt;=&lt;/span&gt; df[&lt;span class="st"&gt;'player_disadvantaged'&lt;/span&gt;].values&lt;/span&gt;
&lt;span id="cb77-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb77-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;n_player &lt;span class="op"&gt;=&lt;/span&gt; player_enc.classes_.size&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb78"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb78-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb78-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; irt_model:&lt;/span&gt;
&lt;span id="cb78-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb78-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    θ_player &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal(&lt;/span&gt;
&lt;span id="cb78-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb78-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'θ_player'&lt;/span&gt;, (n_player, n_season)&lt;/span&gt;
&lt;span id="cb78-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb78-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb78-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb78-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    θ &lt;span class="op"&gt;=&lt;/span&gt; θ_player[player_disadvantaged, season]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Each committing player has an ideal point (per season).&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[
\begin{align*}
    \sigma_{b}
        &amp;amp; \sim \operatorname{HalfNormal}(5) \\
    b^{\textrm{player}}_{j, s}
        &amp;amp; \sim \operatorname{Hierarchical-Normal}(0, \sigma_{b}^2)
\end{align*}    
\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb79"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb79-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb79-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;player_committing &lt;span class="op"&gt;=&lt;/span&gt; df[&lt;span class="st"&gt;'player_committing'&lt;/span&gt;].values&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb80"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb80-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb80-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; irt_model:&lt;/span&gt;
&lt;span id="cb80-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb80-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    b_player &lt;span class="op"&gt;=&lt;/span&gt; hierarchical_normal(&lt;/span&gt;
&lt;span id="cb80-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb80-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'b_player'&lt;/span&gt;, (n_player, n_season)&lt;/span&gt;
&lt;span id="cb80-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb80-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb80-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb80-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    b &lt;span class="op"&gt;=&lt;/span&gt; b_player[player_committing, season]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Players affect the foul call rate through the difference in their ideal points.&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[\eta^{\textrm{player}}_k = \theta_k - b_k\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb81"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb81-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb81-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; irt_model:&lt;/span&gt;
&lt;span id="cb81-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb81-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    η_player &lt;span class="op"&gt;=&lt;/span&gt; θ &lt;span class="op"&gt;-&lt;/span&gt; b&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The sum of the game and player effects determines the foul call probability.&lt;/p&gt;
&lt;p&gt;&lt;span class="math display"&gt;\[\eta_k = \eta^{\textrm{game}}_k + \eta^{\textrm{player}}_k\]&lt;/span&gt;&lt;/p&gt;
&lt;div class="sourceCode" id="cb82"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb82-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb82-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; irt_model:&lt;/span&gt;
&lt;span id="cb82-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb82-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    η &lt;span class="op"&gt;=&lt;/span&gt; η_game &lt;span class="op"&gt;+&lt;/span&gt; η_player&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb83"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb83-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb83-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; irt_model:&lt;/span&gt;
&lt;span id="cb83-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb83-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    p &lt;span class="op"&gt;=&lt;/span&gt; pm.Deterministic(&lt;span class="st"&gt;'p'&lt;/span&gt;, pm.math.sigmoid(η))&lt;/span&gt;
&lt;span id="cb83-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb83-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    y &lt;span class="op"&gt;=&lt;/span&gt; pm.Bernoulli(&lt;/span&gt;
&lt;span id="cb83-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb83-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="st"&gt;'y'&lt;/span&gt;, p,&lt;/span&gt;
&lt;span id="cb83-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb83-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        observed&lt;span class="op"&gt;=&lt;/span&gt;df[&lt;span class="st"&gt;'foul_called'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb83-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb83-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="infer-the-model-given-data-2"&gt;Infer the model given data&lt;/h4&gt;
&lt;p&gt;Again, we sample from the model’s posterior distribution.&lt;/p&gt;
&lt;div class="sourceCode" id="cb84"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb84-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb84-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="cf"&gt;with&lt;/span&gt; irt_model:&lt;/span&gt;
&lt;span id="cb84-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb84-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    irt_trace &lt;span class="op"&gt;=&lt;/span&gt; pm.sample(&lt;span class="op"&gt;**&lt;/span&gt;SAMPLE_KWARGS)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (3 chains in 3 jobs)
NUTS: [σ_b_player_log__, Δ_b_player, σ_θ_player_log__, Δ_θ_player, σ_β_poss_log__, Δ_β_poss, σ_β_call_log__, Δ_β_call, β_season]
100%|██████████| 1500/1500 [13:55&amp;lt;00:00,  1.80it/s]
There were 3 divergences after tuning. Increase `target_accept` or reparameterize.
There were 1 divergences after tuning. Increase `target_accept` or reparameterize.
There were 4 divergences after tuning. Increase `target_accept` or reparameterize.
The estimated number of effective samples is smaller than 200 for some parameters.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;None of the sampling diagnostics indicate problems with convergence.&lt;/p&gt;
&lt;div class="sourceCode" id="cb86"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb86-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb86-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;bfmi &lt;span class="op"&gt;=&lt;/span&gt; pm.bfmi(irt_trace)&lt;/span&gt;
&lt;span id="cb86-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb86-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb86-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb86-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;max_gr &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="bu"&gt;max&lt;/span&gt;(&lt;/span&gt;
&lt;span id="cb86-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb86-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    np.&lt;span class="bu"&gt;max&lt;/span&gt;(gr_stats) &lt;span class="cf"&gt;for&lt;/span&gt; gr_stats &lt;span class="kw"&gt;in&lt;/span&gt; pm.gelman_rubin(irt_trace).values()&lt;/span&gt;
&lt;span id="cb86-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb86-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb87"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb87-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb87-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(pm.energyplot(irt_trace, legend&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;, figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;6&lt;/span&gt;, &lt;span class="dv"&gt;4&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb87-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb87-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;   .set_title(CONVERGENCE_TITLE()))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_139_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;h3 id="criticize-the-model-given-data-take-three"&gt;Criticize the model given data, take three&lt;/h3&gt;
&lt;p&gt;The binned residuals for this model are more asymmetric than for the previous models, but still not too bad.&lt;/p&gt;
&lt;div class="sourceCode" id="cb88"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb88-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb88-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;resid_df &lt;span class="op"&gt;=&lt;/span&gt; (df.assign(p_hat&lt;span class="op"&gt;=&lt;/span&gt;irt_trace[&lt;span class="st"&gt;'p'&lt;/span&gt;].mean(axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb88-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb88-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .assign(resid&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="kw"&gt;lambda&lt;/span&gt; df: df[&lt;span class="st"&gt;'foul_called'&lt;/span&gt;] &lt;span class="op"&gt;-&lt;/span&gt; df[&lt;span class="st"&gt;'p_hat'&lt;/span&gt;]))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb89"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb89-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb89-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;N_BIN &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;50&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb89-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb89-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb89-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb89-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;bin_ix, bins &lt;span class="op"&gt;=&lt;/span&gt; pd.qcut(&lt;/span&gt;
&lt;span id="cb89-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb89-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    resid_df.p_hat, N_BIN,&lt;/span&gt;
&lt;span id="cb89-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb89-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    labels&lt;span class="op"&gt;=&lt;/span&gt;np.arange(N_BIN),&lt;/span&gt;
&lt;span id="cb89-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb89-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    retbins&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb89-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb89-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb90"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb90-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb90-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; (resid_df.groupby(bins[bin_ix])&lt;/span&gt;
&lt;span id="cb90-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb90-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .resid.mean()&lt;/span&gt;
&lt;span id="cb90-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb90-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .rename_axis(&lt;span class="st"&gt;'p_hat'&lt;/span&gt;, axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb90-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb90-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .reset_index()&lt;/span&gt;
&lt;span id="cb90-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb90-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .plot(&lt;span class="st"&gt;'p_hat'&lt;/span&gt;, &lt;span class="st"&gt;'resid'&lt;/span&gt;, kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'scatter'&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb90-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb90-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb90-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb90-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.xaxis.set_major_formatter(pct_formatter)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb90-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb90-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="vs"&gt;r"Binned $\hat&lt;/span&gt;&lt;span class="sc"&gt;{p}&lt;/span&gt;&lt;span class="vs"&gt;$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb90-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb90-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb90-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb90-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_foul_rate_yaxis(ax, label&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Residual"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_144_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;div class="sourceCode" id="cb91"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb91-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb91-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax &lt;span class="op"&gt;=&lt;/span&gt; (resid_df.groupby(&lt;span class="st"&gt;'seconds_left'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb91-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb91-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .resid.mean()&lt;/span&gt;
&lt;span id="cb91-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb91-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .reset_index()&lt;/span&gt;
&lt;span id="cb91-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb91-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;              .plot(&lt;span class="st"&gt;'seconds_left'&lt;/span&gt;, &lt;span class="st"&gt;'resid'&lt;/span&gt;, kind&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'scatter'&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb91-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb91-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;make_time_axes(ax, ylabel&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;"Residual"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_145_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;h4 id="model-selection-1"&gt;Model selection&lt;/h4&gt;
&lt;p&gt;The IRT model is a marginal improvement over the possession model in terms of WAIC.&lt;/p&gt;
&lt;div class="sourceCode" id="cb92"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb92-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb92-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;MODEL_NAME_MAP[&lt;span class="dv"&gt;2&lt;/span&gt;] &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="st"&gt;"IRT"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb92-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb92-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb92-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb92-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;comp_df &lt;span class="op"&gt;=&lt;/span&gt; (pm.compare(&lt;/span&gt;
&lt;span id="cb92-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb92-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                (base_trace, poss_trace, irt_trace),&lt;/span&gt;
&lt;span id="cb92-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb92-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                (base_model, poss_model, irt_model)&lt;/span&gt;
&lt;span id="cb92-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb92-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             )&lt;/span&gt;
&lt;span id="cb92-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb92-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             .rename(index&lt;span class="op"&gt;=&lt;/span&gt;MODEL_NAME_MAP)&lt;/span&gt;
&lt;span id="cb92-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb92-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;             .loc[MODEL_NAME_MAP.values()])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb93"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb93-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb93-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;comp_df&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style scoped&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;center&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
WAIC
&lt;/th&gt;
&lt;th&gt;
pWAIC
&lt;/th&gt;
&lt;th&gt;
dWAIC
&lt;/th&gt;
&lt;th&gt;
weight
&lt;/th&gt;
&lt;th&gt;
SE
&lt;/th&gt;
&lt;th&gt;
dSE
&lt;/th&gt;
&lt;th&gt;
var_warn
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
Base
&lt;/th&gt;
&lt;td&gt;
11610.1
&lt;/td&gt;
&lt;td&gt;
2.11
&lt;/td&gt;
&lt;td&gt;
1566.92
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
56.9
&lt;/td&gt;
&lt;td&gt;
74.03
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
Possession
&lt;/th&gt;
&lt;td&gt;
10068.1
&lt;/td&gt;
&lt;td&gt;
82.93
&lt;/td&gt;
&lt;td&gt;
24.94
&lt;/td&gt;
&lt;td&gt;
0.08
&lt;/td&gt;
&lt;td&gt;
88.05
&lt;/td&gt;
&lt;td&gt;
10.99
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
IRT
&lt;/th&gt;
&lt;td&gt;
10043.2
&lt;/td&gt;
&lt;td&gt;
216.6
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0.91
&lt;/td&gt;
&lt;td&gt;
88.47
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb94"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb94-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb94-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots()&lt;/span&gt;
&lt;span id="cb94-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb94-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.errorbar(&lt;/span&gt;
&lt;span id="cb94-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb94-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    np.arange(&lt;span class="bu"&gt;len&lt;/span&gt;(MODEL_NAME_MAP)), comp_df.WAIC,&lt;/span&gt;
&lt;span id="cb94-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb94-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    yerr&lt;span class="op"&gt;=&lt;/span&gt;comp_df.SE, fmt&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'o'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb94-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb94-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb94-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb94-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xticks(np.arange(&lt;span class="bu"&gt;len&lt;/span&gt;(MODEL_NAME_MAP)))&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb94-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb94-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xticklabels(comp_df.index)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb94-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb94-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="st"&gt;"Model"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb94-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb94-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_ylabel(&lt;span class="st"&gt;"WAIC"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_149_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We now produce two &lt;code&gt;DataFrame&lt;/code&gt;s containing the estimated player ideal points per season.&lt;/p&gt;
&lt;div class="sourceCode" id="cb95"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb95-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb95-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; varname_to_param(varname):&lt;/span&gt;
&lt;span id="cb95-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb95-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; varname[&lt;span class="dv"&gt;0&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb95-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb95-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb95-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb95-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; varname_to_player(varname):&lt;/span&gt;
&lt;span id="cb95-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb95-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="bu"&gt;int&lt;/span&gt;(varname[&lt;span class="dv"&gt;3&lt;/span&gt;:&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;])&lt;/span&gt;
&lt;span id="cb95-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb95-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb95-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb95-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; varname_to_season(varname):&lt;/span&gt;
&lt;span id="cb95-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb95-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="bu"&gt;int&lt;/span&gt;(varname[&lt;span class="op"&gt;-&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb96"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb96-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;irt_df &lt;span class="op"&gt;=&lt;/span&gt; (pm.trace_to_dataframe(&lt;/span&gt;
&lt;span id="cb96-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                irt_trace, varnames&lt;span class="op"&gt;=&lt;/span&gt;[&lt;span class="st"&gt;'θ_player'&lt;/span&gt;, &lt;span class="st"&gt;'b_player'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb96-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            )&lt;/span&gt;
&lt;span id="cb96-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .rename(columns&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="kw"&gt;lambda&lt;/span&gt; col: col.replace(&lt;span class="st"&gt;'_player'&lt;/span&gt;, &lt;span class="st"&gt;''&lt;/span&gt;))&lt;/span&gt;
&lt;span id="cb96-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .T&lt;/span&gt;
&lt;span id="cb96-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .&lt;span class="bu"&gt;apply&lt;/span&gt;(&lt;/span&gt;
&lt;span id="cb96-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               &lt;span class="kw"&gt;lambda&lt;/span&gt; s: pd.Series.describe(&lt;/span&gt;
&lt;span id="cb96-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                   s, percentiles&lt;span class="op"&gt;=&lt;/span&gt;[&lt;span class="fl"&gt;0.055&lt;/span&gt;, &lt;span class="fl"&gt;0.945&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb96-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               ),&lt;/span&gt;
&lt;span id="cb96-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;               axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb96-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            )&lt;/span&gt;
&lt;span id="cb96-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            [[&lt;span class="st"&gt;'mean'&lt;/span&gt;, &lt;span class="st"&gt;'5.5%'&lt;/span&gt;, &lt;span class="st"&gt;'94.5%'&lt;/span&gt;]]&lt;/span&gt;
&lt;span id="cb96-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .rename(columns&lt;span class="op"&gt;=&lt;/span&gt;{&lt;/span&gt;
&lt;span id="cb96-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 &lt;span class="st"&gt;'5.5%'&lt;/span&gt;: &lt;span class="st"&gt;'low'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb96-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                 &lt;span class="st"&gt;'94.5%'&lt;/span&gt;: &lt;span class="st"&gt;'high'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb96-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            })&lt;/span&gt;
&lt;span id="cb96-17"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .rename_axis(&lt;span class="st"&gt;'varname'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb96-18"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .reset_index()&lt;/span&gt;
&lt;span id="cb96-19"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .assign(&lt;/span&gt;
&lt;span id="cb96-20"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                param&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="kw"&gt;lambda&lt;/span&gt; df: df[&lt;span class="st"&gt;'varname'&lt;/span&gt;].&lt;span class="bu"&gt;apply&lt;/span&gt;(varname_to_param),&lt;/span&gt;
&lt;span id="cb96-21"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                player&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="kw"&gt;lambda&lt;/span&gt; df: df[&lt;span class="st"&gt;'varname'&lt;/span&gt;].&lt;span class="bu"&gt;apply&lt;/span&gt;(varname_to_player),&lt;/span&gt;
&lt;span id="cb96-22"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                season&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="kw"&gt;lambda&lt;/span&gt; df: df[&lt;span class="st"&gt;'varname'&lt;/span&gt;].&lt;span class="bu"&gt;apply&lt;/span&gt;(varname_to_season)&lt;/span&gt;
&lt;span id="cb96-23"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            )&lt;/span&gt;
&lt;span id="cb96-24"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb96-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            .drop(&lt;span class="st"&gt;'varname'&lt;/span&gt;, axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;1&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb97"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb97-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb97-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;irt_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style scoped&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;center&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
mean
&lt;/th&gt;
&lt;th&gt;
low
&lt;/th&gt;
&lt;th&gt;
high
&lt;/th&gt;
&lt;th&gt;
param
&lt;/th&gt;
&lt;th&gt;
player
&lt;/th&gt;
&lt;th&gt;
season
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
-0.016516
&lt;/td&gt;
&lt;td&gt;
-0.323127
&lt;/td&gt;
&lt;td&gt;
0.272022
&lt;/td&gt;
&lt;td&gt;
θ
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1
&lt;/th&gt;
&lt;td&gt;
0.003845
&lt;/td&gt;
&lt;td&gt;
-0.289842
&lt;/td&gt;
&lt;td&gt;
0.290248
&lt;/td&gt;
&lt;td&gt;
θ
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2
&lt;/th&gt;
&lt;td&gt;
0.008519
&lt;/td&gt;
&lt;td&gt;
-0.289715
&lt;/td&gt;
&lt;td&gt;
0.304574
&lt;/td&gt;
&lt;td&gt;
θ
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
3
&lt;/th&gt;
&lt;td&gt;
0.031367
&lt;/td&gt;
&lt;td&gt;
-0.240853
&lt;/td&gt;
&lt;td&gt;
0.339297
&lt;/td&gt;
&lt;td&gt;
θ
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
4
&lt;/th&gt;
&lt;td&gt;
-0.037530
&lt;/td&gt;
&lt;td&gt;
-0.320010
&lt;/td&gt;
&lt;td&gt;
0.226110
&lt;/td&gt;
&lt;td&gt;
θ
&lt;/td&gt;
&lt;td&gt;
2
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb98"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb98-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb98-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;player_irt_df &lt;span class="op"&gt;=&lt;/span&gt; irt_df.pivot_table(&lt;/span&gt;
&lt;span id="cb98-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb98-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    index&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'player'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb98-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb98-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    columns&lt;span class="op"&gt;=&lt;/span&gt;[&lt;span class="st"&gt;'param'&lt;/span&gt;, &lt;span class="st"&gt;'season'&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb98-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb98-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    values&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'mean'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb98-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb98-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb99"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb99-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb99-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;player_irt_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style scoped&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead tr th {
        text-align: left;
    }

    .dataframe thead tr:last-of-type th {
        text-align: right;
    }
&lt;/style&gt;
&lt;center&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;
param
&lt;/th&gt;
&lt;th colspan="2" halign="left"&gt;
b
&lt;/th&gt;
&lt;th colspan="2" halign="left"&gt;
θ
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
season
&lt;/th&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;th&gt;
1
&lt;/th&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;th&gt;
1
&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
player
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
-0.069235
&lt;/td&gt;
&lt;td&gt;
0.013339
&lt;/td&gt;
&lt;td&gt;
-0.016516
&lt;/td&gt;
&lt;td&gt;
0.003845
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1
&lt;/th&gt;
&lt;td&gt;
-0.003003
&lt;/td&gt;
&lt;td&gt;
0.001853
&lt;/td&gt;
&lt;td&gt;
0.008519
&lt;/td&gt;
&lt;td&gt;
0.031367
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2
&lt;/th&gt;
&lt;td&gt;
0.084515
&lt;/td&gt;
&lt;td&gt;
0.089058
&lt;/td&gt;
&lt;td&gt;
-0.037530
&lt;/td&gt;
&lt;td&gt;
-0.002373
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
3
&lt;/th&gt;
&lt;td&gt;
-0.028946
&lt;/td&gt;
&lt;td&gt;
0.004360
&lt;/td&gt;
&lt;td&gt;
0.003514
&lt;/td&gt;
&lt;td&gt;
-0.000334
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
4
&lt;/th&gt;
&lt;td&gt;
-0.001976
&lt;/td&gt;
&lt;td&gt;
0.280380
&lt;/td&gt;
&lt;td&gt;
0.072932
&lt;/td&gt;
&lt;td&gt;
0.005571
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;
&lt;/div&gt;
&lt;p&gt;The following plot shows that the committing skill appears to be somewhat larger than the disadvantaged skill. This difference seems reasonable because most fouls are committed by the player on defense; committing skill is quite likely to be correlated with defensive ability.&lt;/p&gt;
&lt;div class="sourceCode" id="cb100"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb100-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; plot_latent_params(df):&lt;/span&gt;
&lt;span id="cb100-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots()&lt;/span&gt;
&lt;span id="cb100-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb100-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    n, _ &lt;span class="op"&gt;=&lt;/span&gt; df.shape&lt;/span&gt;
&lt;span id="cb100-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    y &lt;span class="op"&gt;=&lt;/span&gt; np.arange(n)&lt;/span&gt;
&lt;span id="cb100-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb100-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.errorbar(&lt;/span&gt;
&lt;span id="cb100-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        df[&lt;span class="st"&gt;'mean'&lt;/span&gt;], y,&lt;/span&gt;
&lt;span id="cb100-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        xerr&lt;span class="op"&gt;=&lt;/span&gt;(df[[&lt;span class="st"&gt;'high'&lt;/span&gt;, &lt;span class="st"&gt;'low'&lt;/span&gt;]]&lt;/span&gt;
&lt;span id="cb100-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .sub(df[&lt;span class="st"&gt;'mean'&lt;/span&gt;], axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb100-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .&lt;span class="bu"&gt;abs&lt;/span&gt;()&lt;/span&gt;
&lt;span id="cb100-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                .values.T),&lt;/span&gt;
&lt;span id="cb100-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        fmt&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="st"&gt;'o'&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb100-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb100-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_yticks(y)&lt;/span&gt;
&lt;span id="cb100-17"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_yticklabels(&lt;/span&gt;
&lt;span id="cb100-18"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        player_enc.inverse_transform(df.player)&lt;/span&gt;
&lt;span id="cb100-19"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb100-20"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ax.set_ylabel(&lt;span class="st"&gt;"Player"&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb100-21"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb100-22"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; fig, ax&lt;/span&gt;
&lt;span id="cb100-23"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb100-24"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, axes &lt;span class="op"&gt;=&lt;/span&gt; plt.subplots(&lt;/span&gt;
&lt;span id="cb100-25"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    ncols&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, nrows&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;2&lt;/span&gt;, sharex&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb100-26"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    figsize&lt;span class="op"&gt;=&lt;/span&gt;(&lt;span class="dv"&gt;16&lt;/span&gt;, &lt;span class="dv"&gt;8&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb100-27"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-27" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb100-28"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-28" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(θ&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;, θ&lt;span class="dv"&gt;1&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;), (b0_ax, b1_ax) &lt;span class="op"&gt;=&lt;/span&gt; axes&lt;/span&gt;
&lt;span id="cb100-29"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-29" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb100-30"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-30" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;bins &lt;span class="op"&gt;=&lt;/span&gt; np.linspace(&lt;/span&gt;
&lt;span id="cb100-31"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-31" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fl"&gt;0.9&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; irt_df[&lt;span class="st"&gt;'mean'&lt;/span&gt;].&lt;span class="bu"&gt;min&lt;/span&gt;(),&lt;/span&gt;
&lt;span id="cb100-32"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-32" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="fl"&gt;1.1&lt;/span&gt; &lt;span class="op"&gt;*&lt;/span&gt; irt_df[&lt;span class="st"&gt;'mean'&lt;/span&gt;].&lt;span class="bu"&gt;max&lt;/span&gt;(),&lt;/span&gt;
&lt;span id="cb100-33"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-33" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="dv"&gt;75&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-34"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-34" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb100-35"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-35" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb100-36"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-36" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;θ&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;.hist(&lt;/span&gt;
&lt;span id="cb100-37"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-37" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    player_irt_df[&lt;span class="st"&gt;'θ'&lt;/span&gt;, &lt;span class="dv"&gt;0&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb100-38"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-38" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    bins&lt;span class="op"&gt;=&lt;/span&gt;bins, normed&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-39"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-39" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-40"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-40" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;θ&lt;span class="dv"&gt;1&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;.hist(&lt;/span&gt;
&lt;span id="cb100-41"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-41" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    player_irt_df[&lt;span class="st"&gt;'θ'&lt;/span&gt;, &lt;span class="dv"&gt;1&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb100-42"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-42" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    bins&lt;span class="op"&gt;=&lt;/span&gt;bins, normed&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-43"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-43" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-44"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-44" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb100-45"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-45" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;θ&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;.set_yticks([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-46"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-46" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;θ&lt;span class="dv"&gt;0&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;.set_title(&lt;/span&gt;
&lt;span id="cb100-47"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-47" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="vs"&gt;r"$\hat{\theta}$ ("&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; season_enc.inverse_transform(&lt;span class="dv"&gt;0&lt;/span&gt;) &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="st"&gt;")"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-48"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-48" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-49"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-49" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb100-50"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-50" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;θ&lt;span class="dv"&gt;1&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;.set_yticks([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-51"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-51" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;θ&lt;span class="dv"&gt;1&lt;/span&gt;&lt;span class="er"&gt;_ax&lt;/span&gt;.set_title(&lt;/span&gt;
&lt;span id="cb100-52"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-52" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="vs"&gt;r"$\hat{\theta}$ ("&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; season_enc.inverse_transform(&lt;span class="dv"&gt;1&lt;/span&gt;) &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="st"&gt;")"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-53"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-53" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-54"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-54" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb100-55"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-55" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;b0_ax.hist(&lt;/span&gt;
&lt;span id="cb100-56"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-56" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    player_irt_df[&lt;span class="st"&gt;'b'&lt;/span&gt;, &lt;span class="dv"&gt;0&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb100-57"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-57" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    bins&lt;span class="op"&gt;=&lt;/span&gt;bins, normed&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, color&lt;span class="op"&gt;=&lt;/span&gt;green&lt;/span&gt;
&lt;span id="cb100-58"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-58" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-59"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-59" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;b1_ax.hist(&lt;/span&gt;
&lt;span id="cb100-60"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-60" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    player_irt_df[&lt;span class="st"&gt;'b'&lt;/span&gt;, &lt;span class="dv"&gt;1&lt;/span&gt;],&lt;/span&gt;
&lt;span id="cb100-61"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-61" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    bins&lt;span class="op"&gt;=&lt;/span&gt;bins, normed&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;, color&lt;span class="op"&gt;=&lt;/span&gt;green&lt;/span&gt;
&lt;span id="cb100-62"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-62" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-63"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-63" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb100-64"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-64" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;b0_ax.set_xlabel(&lt;/span&gt;
&lt;span id="cb100-65"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-65" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="vs"&gt;r"$\hat&lt;/span&gt;&lt;span class="sc"&gt;{b}&lt;/span&gt;&lt;span class="vs"&gt;$ ("&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; season_enc.inverse_transform(&lt;span class="dv"&gt;0&lt;/span&gt;) &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="st"&gt;")"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-66"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-66" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-67"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-67" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb100-68"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-68" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;b0_ax.invert_yaxis()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-69"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-69" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;b0_ax.xaxis.tick_top()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-70"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-70" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;b0_ax.set_yticks([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-71"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-71" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb100-72"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-72" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;b1_ax.set_xlabel(&lt;/span&gt;
&lt;span id="cb100-73"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-73" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="vs"&gt;r"$\hat&lt;/span&gt;&lt;span class="sc"&gt;{b}&lt;/span&gt;&lt;span class="vs"&gt;$ ("&lt;/span&gt; &lt;span class="op"&gt;+&lt;/span&gt; season_enc.inverse_transform(&lt;span class="dv"&gt;1&lt;/span&gt;) &lt;span class="op"&gt;+&lt;/span&gt; &lt;span class="st"&gt;")"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-74"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-74" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-75"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-75" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb100-76"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-76" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;b1_ax.invert_yaxis()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-77"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-77" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;b1_ax.xaxis.tick_top()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-78"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-78" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;b1_ax.set_yticks([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-79"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-79" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb100-80"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-80" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.suptitle(&lt;span class="st"&gt;"Disadvantaged skill"&lt;/span&gt;, size&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;18&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb100-81"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-81" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.text(&lt;span class="fl"&gt;0.45&lt;/span&gt;, &lt;span class="fl"&gt;0.02&lt;/span&gt;, &lt;span class="st"&gt;"Committing skill"&lt;/span&gt;, size&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;18&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb100-82"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb100-82" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig.tight_layout()&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_157_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;We now examine the top and bottom ten players in each ability, across both seasons.&lt;/p&gt;
&lt;p&gt;The top players in terms of disadvantaged ability tend to be good scorers (Jimmy Butler, Ricky Rubio, John Wall, Andre Iguodala). The presence of DeAndre Jordan in the top ten may to be due to the hack-a-Shaq phenomenon. In future work, it would be interesting to control for the disavantage player’s free throw percentage in order to mitigate the influence of the hack-a-Shaq effect on the measurement of latent skill.&lt;/p&gt;
&lt;p&gt;Interestingly, the bottom players (in terms of disadvantaged ability) include many stars (Pau Gasol, Carmelo Anthony, Kevin Durant, Kawhi Leonard). The presence of these stars in the bottom may somewhat counteract the pervasive narrative that referees favor stars in their foul calls.&lt;/p&gt;
&lt;div class="sourceCode" id="cb101"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb101-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb101-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;top_bot_irt_df &lt;span class="op"&gt;=&lt;/span&gt; (irt_df.groupby(&lt;span class="st"&gt;'param'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb101-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb101-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    .&lt;span class="bu"&gt;apply&lt;/span&gt;(&lt;/span&gt;
&lt;span id="cb101-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb101-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        &lt;span class="kw"&gt;lambda&lt;/span&gt; df: pd.concat((&lt;/span&gt;
&lt;span id="cb101-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb101-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                df.nlargest(&lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="st"&gt;'mean'&lt;/span&gt;),&lt;/span&gt;
&lt;span id="cb101-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb101-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                df.nsmallest(&lt;span class="dv"&gt;10&lt;/span&gt;, &lt;span class="st"&gt;'mean'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb101-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb101-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                            ),&lt;/span&gt;
&lt;span id="cb101-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb101-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                            axis&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;0&lt;/span&gt;, ignore_index&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb101-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb101-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        )&lt;/span&gt;
&lt;span id="cb101-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb101-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    )&lt;/span&gt;
&lt;span id="cb101-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb101-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    .reset_index(drop&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;True&lt;/span&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb102"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb102-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb102-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;top_bot_irt_df.head()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;style scoped&gt;
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }

    .dataframe thead th {
        text-align: right;
    }
&lt;/style&gt;
&lt;center&gt;
&lt;table border="1" class="dataframe"&gt;
&lt;thead&gt;
&lt;tr style="text-align: right;"&gt;
&lt;th&gt;
&lt;/th&gt;
&lt;th&gt;
mean
&lt;/th&gt;
&lt;th&gt;
low
&lt;/th&gt;
&lt;th&gt;
high
&lt;/th&gt;
&lt;th&gt;
param
&lt;/th&gt;
&lt;th&gt;
player
&lt;/th&gt;
&lt;th&gt;
season
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;
0
&lt;/th&gt;
&lt;td&gt;
0.351946
&lt;/td&gt;
&lt;td&gt;
-0.026786
&lt;/td&gt;
&lt;td&gt;
0.762273
&lt;/td&gt;
&lt;td&gt;
b
&lt;/td&gt;
&lt;td&gt;
86
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
1
&lt;/th&gt;
&lt;td&gt;
0.320737
&lt;/td&gt;
&lt;td&gt;
-0.027064
&lt;/td&gt;
&lt;td&gt;
0.713128
&lt;/td&gt;
&lt;td&gt;
b
&lt;/td&gt;
&lt;td&gt;
23
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
2
&lt;/th&gt;
&lt;td&gt;
0.280380
&lt;/td&gt;
&lt;td&gt;
-0.071020
&lt;/td&gt;
&lt;td&gt;
0.695970
&lt;/td&gt;
&lt;td&gt;
b
&lt;/td&gt;
&lt;td&gt;
4
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
3
&lt;/th&gt;
&lt;td&gt;
0.279678
&lt;/td&gt;
&lt;td&gt;
-0.057249
&lt;/td&gt;
&lt;td&gt;
0.647667
&lt;/td&gt;
&lt;td&gt;
b
&lt;/td&gt;
&lt;td&gt;
462
&lt;/td&gt;
&lt;td&gt;
1
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;
4
&lt;/th&gt;
&lt;td&gt;
0.271735
&lt;/td&gt;
&lt;td&gt;
-0.106795
&lt;/td&gt;
&lt;td&gt;
0.676231
&lt;/td&gt;
&lt;td&gt;
b
&lt;/td&gt;
&lt;td&gt;
78
&lt;/td&gt;
&lt;td&gt;
0
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/center&gt;
&lt;/div&gt;
&lt;div class="sourceCode" id="cb103"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb103-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb103-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plot_latent_params(&lt;/span&gt;
&lt;span id="cb103-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb103-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    top_bot_irt_df[top_bot_irt_df[&lt;span class="st"&gt;'param'&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="st"&gt;'θ'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb103-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb103-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                  .sort_values(&lt;span class="st"&gt;'mean'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb103-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb103-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb103-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb103-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="vs"&gt;r"$\hat{\theta}$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb103-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb103-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Top and bottom ten"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_161_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;The top ten players in terms of committing skill include many defensive standouts (Danny Green — twice, Gordon Hayward, Paul George).&lt;/p&gt;
&lt;p&gt;The bottom ten players include many that are known to be defensively challenged (Ricky Rubio and James Harden). Dwight Howard was, at one point, a fierce defender of the rim, but was well past his prime in 2015, when our data set begins. Chris Paul’s presence in the bottom is somewhat surprising.&lt;/p&gt;
&lt;div class="sourceCode" id="cb104"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb104-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb104-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;fig, ax &lt;span class="op"&gt;=&lt;/span&gt; plot_latent_params(&lt;/span&gt;
&lt;span id="cb104-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb104-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    top_bot_irt_df[top_bot_irt_df[&lt;span class="st"&gt;'param'&lt;/span&gt;] &lt;span class="op"&gt;==&lt;/span&gt; &lt;span class="st"&gt;'b'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb104-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb104-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                  .sort_values(&lt;span class="st"&gt;'mean'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb104-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb104-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;
&lt;span id="cb104-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb104-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_xlabel(&lt;span class="vs"&gt;r"$\hat&lt;/span&gt;&lt;span class="sc"&gt;{b}&lt;/span&gt;&lt;span class="vs"&gt;$"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb104-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb104-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;ax.set_title(&lt;span class="st"&gt;"Top and bottom ten"&lt;/span&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_163_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;In the sports analytics community, year-over-year correlation of latent parameters is the test of whether or not a latent quantity truly measures a skill. The following plots show a slight year-over-year correlation in the committing skill, but not much correlation in the disadvantaged skill.&lt;/p&gt;
&lt;div class="sourceCode" id="cb105"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb105-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; p_val_to_asterisks(p_val):&lt;/span&gt;
&lt;span id="cb105-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;if&lt;/span&gt; p_val &lt;span class="op"&gt;&amp;lt;&lt;/span&gt; &lt;span class="fl"&gt;0.0001&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb105-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="st"&gt;"****"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb105-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;elif&lt;/span&gt; p_val &lt;span class="op"&gt;&amp;lt;&lt;/span&gt; &lt;span class="fl"&gt;0.001&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb105-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="st"&gt;"***"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb105-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;elif&lt;/span&gt; p_val &lt;span class="op"&gt;&amp;lt;&lt;/span&gt; &lt;span class="fl"&gt;0.01&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb105-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="st"&gt;"**"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb105-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;elif&lt;/span&gt; p_val &lt;span class="op"&gt;&amp;lt;&lt;/span&gt; &lt;span class="fl"&gt;0.05&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb105-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="st"&gt;"*"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb105-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;else&lt;/span&gt;:&lt;/span&gt;
&lt;span id="cb105-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="st"&gt;""&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb105-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb105-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; plot_corr(x, y, &lt;span class="op"&gt;**&lt;/span&gt;kwargs):&lt;/span&gt;
&lt;span id="cb105-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    corrcoeff, p_val &lt;span class="op"&gt;=&lt;/span&gt; sp.stats.pearsonr(x, y)&lt;/span&gt;
&lt;span id="cb105-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    asterisks &lt;span class="op"&gt;=&lt;/span&gt; p_val_to_asterisks(p_val)&lt;/span&gt;
&lt;span id="cb105-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb105-17"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    artist &lt;span class="op"&gt;=&lt;/span&gt; AnchoredText(&lt;/span&gt;
&lt;span id="cb105-18"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="ss"&gt;f'&lt;/span&gt;&lt;span class="sc"&gt;{&lt;/span&gt;corrcoeff&lt;span class="sc"&gt;:.2f}{&lt;/span&gt;asterisks&lt;span class="sc"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;'&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb105-19"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        loc&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="dv"&gt;10&lt;/span&gt;, frameon&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb105-20"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        prop&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="bu"&gt;dict&lt;/span&gt;(size&lt;span class="op"&gt;=&lt;/span&gt;LABELSIZE)&lt;/span&gt;
&lt;span id="cb105-21"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb105-22"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    plt.gca().add_artist(artist)&lt;/span&gt;
&lt;span id="cb105-23"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb105-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    plt.grid(b&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="va"&gt;False&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb106"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb106-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;PARAM_MAP &lt;span class="op"&gt;=&lt;/span&gt; {&lt;/span&gt;
&lt;span id="cb106-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'θ'&lt;/span&gt;: &lt;span class="vs"&gt;r"$\hat{\theta}$"&lt;/span&gt;,&lt;/span&gt;
&lt;span id="cb106-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="st"&gt;'b'&lt;/span&gt;: &lt;span class="vs"&gt;r"$\hat&lt;/span&gt;&lt;span class="sc"&gt;{b}&lt;/span&gt;&lt;span class="vs"&gt;$"&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb106-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;}&lt;/span&gt;
&lt;span id="cb106-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb106-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; replace_label(label):&lt;/span&gt;
&lt;span id="cb106-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    param, season &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="bu"&gt;eval&lt;/span&gt;(label)&lt;/span&gt;
&lt;span id="cb106-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb106-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; &lt;span class="st"&gt;"&lt;/span&gt;&lt;span class="sc"&gt;{param}&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="st"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;{season}&lt;/span&gt;&lt;span class="st"&gt;)"&lt;/span&gt;.&lt;span class="bu"&gt;format&lt;/span&gt;(&lt;/span&gt;
&lt;span id="cb106-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        param&lt;span class="op"&gt;=&lt;/span&gt;PARAM_MAP[param],&lt;/span&gt;
&lt;span id="cb106-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        season&lt;span class="op"&gt;=&lt;/span&gt;season_enc.inverse_transform(season)&lt;/span&gt;
&lt;span id="cb106-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    )&lt;/span&gt;
&lt;span id="cb106-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id="cb106-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;def&lt;/span&gt; style_grid(grid):&lt;/span&gt;
&lt;span id="cb106-15"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-15" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;for&lt;/span&gt; ax &lt;span class="kw"&gt;in&lt;/span&gt; grid.axes.flat:&lt;/span&gt;
&lt;span id="cb106-16"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-16" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ax.grid(&lt;span class="va"&gt;False&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb106-17"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-17" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ax.set_xticklabels([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb106-18"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-18" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        ax.set_yticklabels([])&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb106-19"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-19" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;/span&gt;
&lt;span id="cb106-20"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-20" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;if&lt;/span&gt; ax.get_xlabel():&lt;/span&gt;
&lt;span id="cb106-21"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-21" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ax.set_xlabel(replace_label(ax.get_xlabel()))&lt;/span&gt;
&lt;span id="cb106-22"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-22" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb106-23"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-23" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        &lt;span class="cf"&gt;if&lt;/span&gt; ax.get_ylabel():&lt;/span&gt;
&lt;span id="cb106-24"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-24" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            ax.set_ylabel(replace_label(ax.get_ylabel()))&lt;/span&gt;
&lt;span id="cb106-25"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-25" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;            &lt;/span&gt;
&lt;span id="cb106-26"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb106-26" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    &lt;span class="cf"&gt;return&lt;/span&gt; grid&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb107"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb107-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb107-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;player_all_season &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="bu"&gt;set&lt;/span&gt;(df.groupby(&lt;span class="st"&gt;'player_disadvantaged'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb107-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb107-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                          .&lt;span class="bu"&gt;filter&lt;/span&gt;(&lt;span class="kw"&gt;lambda&lt;/span&gt; df: df[&lt;span class="st"&gt;'season'&lt;/span&gt;].nunique() &lt;span class="op"&gt;==&lt;/span&gt; n_season)&lt;/span&gt;
&lt;span id="cb107-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb107-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                          [&lt;span class="st"&gt;'player_committing'&lt;/span&gt;]) &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb107-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb107-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                        &lt;span class="op"&gt;&amp;amp;&lt;/span&gt; &lt;span class="bu"&gt;set&lt;/span&gt;(df.groupby(&lt;span class="st"&gt;'player_committing'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb107-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb107-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                .&lt;span class="bu"&gt;filter&lt;/span&gt;(&lt;span class="kw"&gt;lambda&lt;/span&gt; df: df[&lt;span class="st"&gt;'season'&lt;/span&gt;].nunique() &lt;span class="op"&gt;==&lt;/span&gt; n_season)&lt;/span&gt;
&lt;span id="cb107-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb107-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                [&lt;span class="st"&gt;'player_committing'&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb108"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb108-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb108-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;style_grid(&lt;/span&gt;
&lt;span id="cb108-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb108-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    sns.PairGrid(&lt;/span&gt;
&lt;span id="cb108-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb108-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        player_irt_df.loc[player_all_season],&lt;/span&gt;
&lt;span id="cb108-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb108-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        size&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;1.75&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb108-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb108-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       )&lt;/span&gt;
&lt;span id="cb108-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb108-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .map_upper(plt.scatter, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb108-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb108-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .map_diag(plt.hist)&lt;/span&gt;
&lt;span id="cb108-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb108-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .map_lower(plot_corr)&lt;/span&gt;
&lt;span id="cb108-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb108-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;span class="op"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_168_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;Since we can only reasonably estimate the skills of players for which we have sufficient foul call data, we plot the correlations below for players that appeared in at least ten plays in each season.&lt;/p&gt;
&lt;div class="sourceCode" id="cb109"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb109-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb109-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;MIN &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="dv"&gt;10&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb109-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb109-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb109-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb109-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;player_has_min &lt;span class="op"&gt;=&lt;/span&gt; &lt;span class="bu"&gt;set&lt;/span&gt;(df.groupby(&lt;span class="st"&gt;'player_disadvantaged'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb109-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb109-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                       .&lt;span class="bu"&gt;filter&lt;/span&gt;(&lt;span class="kw"&gt;lambda&lt;/span&gt; df: (df[&lt;span class="st"&gt;'season'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb109-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb109-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                             .value_counts()&lt;/span&gt;
&lt;span id="cb109-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb109-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                             .gt(MIN)&lt;/span&gt;
&lt;span id="cb109-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb109-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                             .&lt;span class="bu"&gt;all&lt;/span&gt;()))&lt;/span&gt;
&lt;span id="cb109-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb109-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                       [&lt;span class="st"&gt;'player_committing'&lt;/span&gt;]) &lt;span class="op"&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb109-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb109-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                    &lt;span class="op"&gt;&amp;amp;&lt;/span&gt; &lt;span class="bu"&gt;set&lt;/span&gt;(df.groupby(&lt;span class="st"&gt;'player_committing'&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb109-10"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb109-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                            .&lt;span class="bu"&gt;filter&lt;/span&gt;(&lt;span class="kw"&gt;lambda&lt;/span&gt; df: (df[&lt;span class="st"&gt;'season'&lt;/span&gt;]&lt;/span&gt;
&lt;span id="cb109-11"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb109-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                  .value_counts()&lt;/span&gt;
&lt;span id="cb109-12"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb109-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                  .gt(MIN)&lt;/span&gt;
&lt;span id="cb109-13"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb109-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                                                  .&lt;span class="bu"&gt;all&lt;/span&gt;()))&lt;/span&gt;
&lt;span id="cb109-14"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb109-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;                            [&lt;span class="st"&gt;'player_committing'&lt;/span&gt;])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb110"&gt;&lt;pre class="sourceCode python"&gt;&lt;code class="sourceCode python"&gt;&lt;span id="cb110-1"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb110-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;grid &lt;span class="op"&gt;=&lt;/span&gt; style_grid(&lt;/span&gt;
&lt;span id="cb110-2"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb110-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    sns.PairGrid(&lt;/span&gt;
&lt;span id="cb110-3"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb110-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        player_irt_df.loc[player_has_min],&lt;/span&gt;
&lt;span id="cb110-4"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb110-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;        size&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;1.75&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb110-5"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb110-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       )&lt;/span&gt;
&lt;span id="cb110-6"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb110-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .map_upper(plt.scatter, alpha&lt;span class="op"&gt;=&lt;/span&gt;&lt;span class="fl"&gt;0.5&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb110-7"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb110-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .map_diag(plt.hist)&lt;/span&gt;
&lt;span id="cb110-8"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb110-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;       .map_lower(plot_corr)&lt;/span&gt;
&lt;span id="cb110-9"&gt;&lt;a href="https://austinrochford.com/posts/2018-02-04-nba-irt-2.html#cb110-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;center&gt;
&lt;img src="https://austinrochford.com/resources/nba_irt2/An%20Improved%20Analysis%20of%20NBA%20Foul%20Calls%20with%20Python_171_0.png" title="fig:" alt="png"&gt;
&lt;/center&gt;
&lt;p&gt;As expected, the season-over-season latent skill correlations are higher for this subset of players.&lt;/p&gt;
&lt;p&gt;From this figure, it seems that committing skill (&lt;span class="math inline"&gt;\(\hat{b}\)&lt;/span&gt;) exists and is measurable, but is fairly small. It also seems that disadvantaged skill (&lt;span class="math inline"&gt;\(\hat{\theta}\)&lt;/span&gt;), if it exists, is difficult to measure from this data set. Ideally, the NBA would release a foul report for the entirety of every game, but that seems quite unlikely.&lt;/p&gt;
&lt;p&gt;In the future it would be useful to include a correction for the probability that a given game appears in the data set. This correction would help with the sample bias introduced by the fact that only games that are close in the last two minutes are included in the NBA’s reports.&lt;/p&gt;
&lt;p&gt;This post is available as a Jupyter notebook &lt;a href="http://nbviewer.jupyter.org/gist/AustinRochford/a9df849f6a78188dbf9886b2a8a3644b"&gt;here&lt;/a&gt;.&lt;/p&gt;</description><category>Bayesian Statistics</category><category>NBA</category><category>PyMC3</category><guid>https://austinrochford.com/posts/2018-02-04-nba-irt-2.html</guid><pubDate>Sun, 04 Feb 2018 05:00:00 GMT</pubDate></item></channel></rss>