<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Silent Spring Institute Developer Blog</title>
    <description>A blog focused on statistics and scientific programming related to environmental health.
</description>
    <link>https://silentspring.org/devblog/</link>
    <atom:link href="https://silentspring.org/devblog/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Thu, 11 Jan 2018 16:48:44 +0000</pubDate>
    <lastBuildDate>Thu, 11 Jan 2018 16:48:44 +0000</lastBuildDate>
    <generator>Jekyll v3.2.1</generator>
    
      <item>
        <title>Bayesian Binomial Test in R</title>
        <description>&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: in this post, I implemenent an R function for computing \( P(\theta_1 &amp;gt; \theta2) \), where \( \theta_1 \) and \( \theta_2 \) are beta-distributed random variables. This is useful for estimating the probability that one binomial proportion is greater than another.&lt;/p&gt;

&lt;p&gt;I am working on a project in which I need to compare two binomial proportions to see if one is likely to be greater than the other. I wanted to do this in a Bayesian framework; fortunately, estimating binomial proportions is one of the first subjects taught to introduce Bayesian statistics (and statistics in general, for that matter) so the method is well established. &lt;a href=&quot;http://www.sumsar.net/blog/2014/01/bayesian-first-aid-binomial-test/&quot;&gt;Rasmus Bååth&lt;/a&gt; has a very nice article describing the Bayesian binomial test, and an estimation approach using JAGS.&lt;/p&gt;

&lt;p&gt;I made the problem even simpler by using the fact that the beta distribution is the conjugate prior to the binomial distribution. That is, if the prior is \( \mathrm{beta}(\alpha, \beta) \) distributed, then the posterior after observing \( k \) successes in \( n \) trials is&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\mathrm{beta}(\alpha + k, \beta + n - k)&lt;/script&gt;

&lt;p&gt;If you want to start with a noninformative prior, then you can use the beta distribution with \( \alpha = \beta = 1\), which collapses to the uniform distribution. This makes the posterior&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\mathrm{beta}(1 + k, 1 + n - k)&lt;/script&gt;

&lt;p&gt;What I am interested is in comparing two binomial proportions, \( \theta_1 \) and \( \theta_2 \). I want to calculate&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;P(\theta_1&gt;\theta_2)&lt;/script&gt;

&lt;p&gt;We observe \( k_1 \) successes out of \( n_1 \) trials and estimate a posterior distribution for \( \theta_1 \), and \( k_2 \) successes out of \( n_2 \) trials for \( \theta_2 \). Then the probability in question is&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;P(\mathrm{beta}(1 + k_1, 1 + n_1 - k_1) &gt; \mathrm{beta}(1 + k_2, 1 + n_2 - k_2)&lt;/script&gt;

&lt;p&gt;So far, so textbook. At this point, the simplest way to get an estimate is to draw two sets of random numbers, distributed by the two respective beta distributions, and see how many times the first random numbers is greater than the second:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span class=&quot;kp&quot;&gt;set.seed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

k1 &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Five successes&lt;/span&gt;
k2 &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# One success&lt;/span&gt;
n1 &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Ten trials&lt;/span&gt;
n2 &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Ten trials&lt;/span&gt;

b1 &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; rbeta&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; k1&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; n1 &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; k1&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
b2 &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; rbeta&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; k2&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; n2 &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; k2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Probability estimate of P(theta_1 &amp;gt; theta_2)&lt;/span&gt;
&lt;span class=&quot;kp&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;b1 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; b2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10000&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;## [1] 0.9688&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This works fine, but it would be nice to have an exact solution. I found several papers describing different approaches.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;a href=&quot;http://onlinelibrary.wiley.com/doi/10.1002/sim.2701/abstract&quot;&gt;Nadarajah and Kotz (2007)&lt;/a&gt; derived a functional form for the distribution of \( P(\theta_1 - \theta_2) \) (and &lt;a href=&quot;http://onlinelibrary.wiley.com/doi/10.1002/sim.4248/full&quot;&gt;Chen and Luo&lt;/a&gt; fixed a typo in their work in 2011.) This approach is implemented in the &lt;code&gt;tolerance&lt;/code&gt; package via the functions &lt;code&gt;ddiffprop&lt;/code&gt;, &lt;code&gt;pdiffprop&lt;/code&gt;, &lt;code&gt;qdiffprop&lt;/code&gt;, and &lt;code&gt;rdiffprop&lt;/code&gt;. The &lt;code&gt;a1&lt;/code&gt; and &lt;code&gt;a2&lt;/code&gt; parameters let you adjust the priors, where &lt;code&gt;a1 = a2 = 1&lt;/code&gt; is a uniform prior for both proportions.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span class=&quot;kn&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;tolerance&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Probability that the first proportion (5 successes out of 10 trials)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# is greater than the second (1 success out of 10 trials)&lt;/span&gt;
pdiffprop&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          k1 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          k2 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          n1 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          n2 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          a1 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          a2 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
          lower.tail &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;## [1] 0.9682663&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The functions work well, but I found that they stop working for large values of \( n_1 \) or \( n_2 \). This is because several of the terms in the density function use the gamma function, and the R implementation returns infinity and throws a warning for any input larger than 171.&lt;/p&gt;

&lt;p&gt;The second approach I found is described in &lt;a href=&quot;https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4019606/&quot;&gt;Raineri et al. 2014&lt;/a&gt;, in which they derived a recursive formula for \( P(\theta_1 &amp;gt; \theta_2) \). I unrolled the recursion so it could handle large \( n \) without overflowing the stack, and implemented it in R. The first two functions, &lt;code&gt;h&lt;/code&gt; and &lt;code&gt;g&lt;/code&gt;, come directly from Raineri et al. and &lt;code&gt;pdiff&lt;/code&gt; provides a wrapper for estimating differences in binomial proportions.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;h &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; d&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;lbeta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;a &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; b &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; d&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;lbeta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;lbeta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; d&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# probability that beta(a, b) &amp;gt; beta(c, d)&lt;/span&gt;
g &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; d&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;stopifnot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;a &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; b &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; d &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  accum &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0.5&lt;/span&gt;
  &lt;span class=&quot;kr&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;a &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; b &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; d&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;a &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      accum &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; accum &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; h&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;a &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; d&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;a &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      a &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; a &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;b &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; d&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      accum &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; accum &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; h&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; b &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; d&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;b &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      b &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; b &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; a&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      accum &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; accum &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; h&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; d&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;d &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; b&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      accum &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; accum &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; h&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;a&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; d &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;d &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      d &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; d &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  accum
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

pdiff &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;k1&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; k2&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; n1&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; n2&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; a1 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; a2 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  g&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; k1&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; a1 &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; n1 &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; k1&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; k2&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; a2 &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; n2 &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; k2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Probability that the first proportion (5 successes out of 10 trials)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# is greater than the second (1 success out of 10 trials)&lt;/span&gt;
pdiff&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;k1 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      k2 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      n1 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      n2 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;## [1] 0.9682663&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It can also handle large values for \( n_1 \) and \( n_2 \):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;pdiff&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;k1 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;420&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      k2 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      n1 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      n2 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;## [1] 0.8182686&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The results from the simulation, &lt;code&gt;tolerance&lt;/code&gt; package, and this new function all agree, which is a good sign. I ended up using the &lt;code&gt;pdiff&lt;/code&gt; function for my project.&lt;/p&gt;

&lt;h2 id=&quot;a-baseball-example&quot;&gt;A baseball example&lt;/h2&gt;

&lt;p&gt;Let’s apply this to a simple example. Suppose we want to estimate an “ability score” for every baseball team, so we can see which teams are better than others. We model each team’s ability score as a binomial random variable representing the team’s proportion of wins to total games. By feeding in each team’s win and loss record for a season, we’ll estimate a posterior distribution that we can use to rank pairs of teams by how likely they are to have different ability scores.&lt;/p&gt;

&lt;p&gt;First, we filter for the team records from 2016:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span class=&quot;kn&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;tidyverse&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;Lahman&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;knitr&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

teams &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; Teams &lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;
  filter&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;yearID &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2016&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;
  select&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;teamID&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; W&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;
  mutate&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;teamID &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;as.character&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;teamID&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
         P &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;paste0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;W &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;W &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; L&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;%&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And generate a dataframe that has the win and loss numbers from every pair of teams:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;teams_compared &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;expand.grid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;teams&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;teamID&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; teams&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;teamID&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; stringsAsFactors &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;
  rename&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;team1 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; Var1&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; team2 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; Var2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;
  filter&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;team1 &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; team2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;
  left_join&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;teams&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; by &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;team1 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;teamID&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;
  left_join&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;teams&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; by &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;team2 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;teamID&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; suffix &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;_1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;_2&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  
&lt;span class=&quot;kp&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;teams_compared&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;##   team1 team2 W_1 L_1 P_1 W_2 L_2 P_2
## 1   ATL   ARI  68  93 42%  69  93 43%
## 2   BAL   ARI  89  73 55%  69  93 43%
## 3   BOS   ARI  93  69 57%  69  93 43%
## 4   CHA   ARI  78  84 48%  69  93 43%
## 5   CHN   ARI 103  58 64%  69  93 43%
## 6   CIN   ARI  68  94 42%  69  93 43%&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now, we can use our &lt;code&gt;pdiff&lt;/code&gt; function to calculate the probability that team 1’s win percentage is greater than team 2’s win percentage.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;teams_compared &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; teams_compared &lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;
  mutate&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;p_1_greater &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; pmap&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;k1 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; W_1&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; k2 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; W_2&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; n1 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; W_1 &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; L_1&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; n2 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; W_2 &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; L_2&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; pdiff&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;
  unnest&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;p_1_greater&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Let’s see which teams are most likely to have a higher win percentage than other teams:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;teams_compared &lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;
  filter&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;P_1 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; P_2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;
  arrange&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;p_1_greater&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;##   team1 team2 W_1 L_1 P_1 W_2 L_2 P_2 p_1_greater
## 1   CHN   MIN 103  58 64%  59 103 36%   0.9999997
## 2   TEX   MIN  95  67 59%  59 103 36%   0.9999694
## 3   WAS   MIN  95  67 59%  59 103 36%   0.9999694
## 4   CHN   CIN 103  58 64%  68  94 42%   0.9999631
## 5   CHN   SDN 103  58 64%  68  94 42%   0.9999631
## 6   CHN   TBA 103  58 64%  68  94 42%   0.9999631&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The Cubs (CHN), Rangers, and Nationals all have extremely high posterior probabilities of having a better win percentage than the Minnesota Twins.&lt;/p&gt;

&lt;p&gt;Let’s see which teams are most likely to be the same:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;teams_compared &lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;
  filter&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;P_1 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; P_2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;
  arrange&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;p_1_greater&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;##   team1 team2 W_1 L_1 P_1 W_2 L_2 P_2 p_1_greater
## 1   TEX   CLE  95  67 59%  94  67 58%   0.5186491
## 2   WAS   CLE  95  67 59%  94  67 58%   0.5186491
## 3   NYN   DET  87  75 54%  86  75 53%   0.5206036
## 4   SFN   DET  87  75 54%  86  75 53%   0.5206036
## 5   ARI   ATL  69  93 43%  68  93 42%   0.5257282
## 6   OAK   ATL  69  93 43%  68  93 42%   0.5257282&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Texas and Cleveland had very similar records, so the posterior probability that Texas was better than Cleveland is only 52%.&lt;/p&gt;
</description>
        <pubDate>Thu, 11 Jan 2018 00:00:00 +0000</pubDate>
        <link>https://silentspring.org/devblog/2018/01/11/bayesian-binomial-test.html</link>
        <guid isPermaLink="true">https://silentspring.org/devblog/2018/01/11/bayesian-binomial-test.html</guid>
        
        <category>r</category>
        
        <category>rbloggers</category>
        
        
      </item>
    
      <item>
        <title>A Bayesian approach to modelling censored data</title>
        <description>&lt;p&gt;For thise case, we can write Bayes formula as:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;p(\mu,\sigma|y^{\ast}) = \frac{p(y^{\ast}|\mu,\sigma)p(\mu,\sigma)}{p(y^{\ast})}&lt;/script&gt;

&lt;p&gt;The two components in the numerator are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The probability of the data given a \( \mu \) and \( \sigma \), also called the &lt;em&gt;likelihood function&lt;/em&gt;:
\( p(y|\mu,\sigma) \)&lt;/li&gt;
  &lt;li&gt;The probability of a given \( \mu \) and \( \sigma \), before seeing any data; also called the &lt;em&gt;prior likelihood&lt;/em&gt;: \( p(\mu, \sigma) \)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The denominator, \( p(y^{\ast}) \), is the &lt;em&gt;total likelihood&lt;/em&gt; of the data integrated over all hypotheses (that is, over all  values of \( \mu \) and \( \sigma \)). This is the part of the formula that typically doesn’t have an analytical solution; in practice, numerical approximations need to be used.&lt;/p&gt;

&lt;p&gt;Our job is to define the likelihood function and provide a prior distribution for \( \mu \) and \( \sigma \).&lt;/p&gt;

&lt;p&gt;In the previous post, we derived the likelihood function for left-censored data:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
p\left(y^{\ast}|\mu,\sigma\right)=\prod\begin{cases}
P\left(y^{\ast}_{i} | \mu,\sigma\right) &amp; y^{\ast}_{i}&gt;L\\
D\left(L | \mu,\sigma\right) &amp; y^{\ast}_{i}=L
\end{cases} %]]&gt;&lt;/script&gt;

&lt;p&gt;where \( P \) is the log-normal probability density function and \( D \) is the log-normal cumulative density function.&lt;/p&gt;

&lt;p&gt;The specification of a prior distribution depends on the application, and what is known about what reasonable values may be for \( \mu \) and \( \sigma \). In this case, let’s set a very weakly informative prior on both variables: \( \mu \sim Normal(0, 100) \) and \( \sigma \sim Normal(0, 100) \)&lt;/p&gt;

&lt;p&gt;A STAN program that encodes our likelihood function and prior specifications:&lt;/p&gt;

&lt;p&gt;This program is written to look like the math, so it doesn’t use some special syntax that makes the code shorter, and it isn’t as computationally efficient as it code be.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;data {
  int&amp;lt;lower=0&amp;gt; N;
  real L; // censoring limit
  real&amp;lt;lower=L&amp;gt; y[N];
  int cens[N]; // -1 if left-censored, 0 if not censored
}
parameters {
  real mu;
  real&amp;lt;lower=0&amp;gt; sigma;
}
model {
  // priors
  mu ~ normal(0, 100);
  sigma ~ normal(0, 100);

  // likelihood
  for(i in 1:N) {
    if(cens[i] == -1) {
      // left-censored
      target += normal_cdf(L | mu, sigma);
    }
    else {
      // not censored
      target += normal_pdf(y[i] | mu, sigma);
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

</description>
        <pubDate>Wed, 05 Jul 2017 00:00:00 +0000</pubDate>
        <link>https://silentspring.org/devblog/2017/07/05/bayesian-censored-log-normal-data.html</link>
        <guid isPermaLink="true">https://silentspring.org/devblog/2017/07/05/bayesian-censored-log-normal-data.html</guid>
        
        <category>r</category>
        
        <category>rbloggers</category>
        
        
      </item>
    
      <item>
        <title>Unlocking Data in PDFs</title>
        <description>&lt;p&gt;Unfortunately, there is a lot of data released in on the web in the form of PDF files. Scraping data out of PFDs is much harder than scraping from a web page; web pages have structure, in the form of HTML, that you can usually leverage to extract structured data.&lt;/p&gt;

&lt;p&gt;It isn’t hopeless, it’s just harder. Here are some of the tools and techniques that we’ve found useful in parsing data from PDFs.&lt;/p&gt;

&lt;h1&gt;&lt;code&gt;pdftotext&lt;/code&gt;&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;pdftotext&lt;/code&gt; is a utility from the &lt;code&gt;Xpdf&lt;/code&gt; project that converts PDFs to flat text files. It is easiest to install and use on unix based platforms, where it can be found in the &lt;code&gt;poppler-utils&lt;/code&gt; package. There is also a windows port of &lt;code&gt;Xpdf&lt;/code&gt; that I’ve used successfully.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pdftotext&lt;/code&gt; has several useful flags that effect how it parses its input:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;-layout&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;-raw&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;tabula&quot;&gt;tabula&lt;/h1&gt;
&lt;p&gt;Recently I’ve switched to &lt;a href=&quot;http://tabula.technology&quot;&gt;Tabula&lt;/a&gt; for most of my PDF scraping needs. Tabula is a desktop application for extracting data from PDFs. I’ve found it to be more reliable than &lt;code&gt;pdftotext&lt;/code&gt;. The only drawback is that it isn’t a command line program, so automating the scraping isn’t as easy as &lt;code&gt;pdftotext&lt;/code&gt;. On the other hand, you can visually select the parts of the PDFs you’d like to scrape, which is useful for one-off jobs.&lt;/p&gt;
</description>
        <pubDate>Thu, 06 Apr 2017 00:00:00 +0000</pubDate>
        <link>https://silentspring.org/devblog/2017/04/06/unlocking-data-in-pdfs.html</link>
        <guid isPermaLink="true">https://silentspring.org/devblog/2017/04/06/unlocking-data-in-pdfs.html</guid>
        
        <category>scraping</category>
        
        
      </item>
    
      <item>
        <title>Tracking Packages in Excel</title>
        <description>&lt;p&gt;We’ve been shipping hundreds of packages as part of our &lt;a href=&quot;http://silentspring.org/detoxmeactionkit&quot;&gt;Detox Me Action Kit&lt;/a&gt; project, and we wanted a way to track all of them without having to manually enter their tracking numbers on the UPS website. Through the UPS REST API and some VBA hacking, we were able to retrieve tracking information directly from Excel.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;em&gt;Dependencies&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Download the &lt;a href=&quot;https://github.com/VBA-tools/VBA-JSON&quot;&gt;VBA-JSON&lt;/a&gt; library and follow the instructions to reference it ni your spreadsheet.&lt;/li&gt;
  &lt;li&gt;An UPS account and a UPS API key, which you can request on their &lt;a href=&quot;https://www.ups.com/upsdeveloperkit&quot;&gt;Developer Kit&lt;/a&gt; page.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The function works by submitting a request, formatted in JSON, to the UPS REST API tracking endpoint. The response, also in JSON, lists the events (arrivals and departures) linked to the package. The function returns the status of the most recent event. If no events are listed, then it returns “Not Shipped”. If the response has a fault or error, then “Error” is returned.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vbnet&quot; data-lang=&quot;vbnet&quot;&gt;&lt;span class=&quot;k&quot;&gt;Function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;UPS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Tracking&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Username&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;Dim&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyRequest&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;As&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Object&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;Dim&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;As&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;{&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;#39;UPSSecurity&amp;#39;: {&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;    &amp;#39;UsernameToken&amp;#39;: {&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;        &amp;#39;Username&amp;#39;: &amp;#39;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Username&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;#39;,&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;        &amp;#39;Password&amp;#39;: &amp;#39;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;#39;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;    },&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;   &amp;#39;ServiceAccessToken&amp;#39;: {&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;       &amp;#39;AccessLicenseNumber&amp;#39;: &amp;#39;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;#39;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;   }&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;},&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;#39;TrackRequest&amp;#39;: {&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;   &amp;#39;Request&amp;#39;: {&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;       &amp;#39;RequestOption&amp;#39;: &amp;#39;15&amp;#39;,&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;       &amp;#39;TransactionReference&amp;#39;: {&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;           &amp;#39;CustomerContext&amp;#39;: &amp;#39;Excel Package Tracker&amp;#39;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;        }&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;   },&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;   &amp;#39;InquiryNumber&amp;#39;: &amp;#39;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Tracking&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;#39;,&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;   &amp;#39;TrackingOption&amp;#39;:&amp;#39;02&amp;#39;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;}}&amp;quot;&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyRequest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CreateObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;WinHttp.WinHttpRequest.5.1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;MyRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Open&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;POST&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;https://onlinetools.ups.com/rest/Track&amp;quot;&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;MyRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Send&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestContents&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;Dim&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Json&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;As&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Object&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Json&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;JsonConverter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParseJson&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ResponseText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;Debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;JsonConverter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ConvertToJson&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;If&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Fault&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;Or&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Error&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Then&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;UPS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Error&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;Else&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;Dim&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Package&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;As&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Object&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Package&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;TrackResponse&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Shipment&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Package&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;If&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;TypeOf&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Package&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Activity&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;Is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Collection&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Then&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;UPS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Package&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Activity&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Status&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Description&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;Else&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;If&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Package&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Activity&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Exists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Status&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Then&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;UPS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Not Shipped&amp;quot;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;End&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;If&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;End&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;If&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;End&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;If&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;End&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Function&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can call the &lt;code&gt;UPS&lt;/code&gt; function from an Excel formula:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vbnet&quot; data-lang=&quot;vbnet&quot;&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UPS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;tracking number&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;API key&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;UPS username&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;UPS password&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Happy tracking!&lt;/p&gt;
</description>
        <pubDate>Thu, 23 Mar 2017 00:00:00 +0000</pubDate>
        <link>https://silentspring.org/devblog/2017/03/23/ups-tracking-in-excel.html</link>
        <guid isPermaLink="true">https://silentspring.org/devblog/2017/03/23/ups-tracking-in-excel.html</guid>
        
        <category>excel</category>
        
        
      </item>
    
      <item>
        <title>NHANES made simple with RNHANES</title>
        <description>&lt;p&gt;Scientists spend a lot of time “munging” data. Finding, cleaning, and managing datasets can take up the majority of the time it takes to complete an analysis. Tools that make the munging process easier can save scientists a lot of time.&lt;/p&gt;

&lt;p&gt;We are tackling a small part of this problem in the context of the CDC’s &lt;a href=&quot;https://www.cdc.gov/nchs/nhanes/&quot;&gt;National Health and Nutrition Examination Survey&lt;/a&gt;, a national study conducted every two years that gathers data on American’s health, nutrition, and exposure to environmental chemicals. Data from NHANES is used widely by environmental health scientists to study the U.S. public’s exposure to chemicals.&lt;/p&gt;

&lt;p&gt;Figuring out how to set up a proper analysis of NHANES data can be tricky if you’re starting from scratch. That’s why we wrote &lt;a href=&quot;https://cran.r-project.org/web/packages/RNHANES/&quot;&gt;RNHANES&lt;/a&gt;, an R package that makes it easy to download, analyze, and visualize NHANES data. RNHANES streamlines accessing the data, helps to set up analyses that correctly incorporate the study’s sample weights, and has built in plotting functions.&lt;/p&gt;

&lt;p&gt;Let’s take the package for a spin by conducting a real-world analysis of NHANES data. Specifically, let’s characterize the U.S. population’s exposure to PFOA, a perfluo-alkyl substance (PFAS, also called “highly fluorinated compound”) that is linked to a number of adverse health effects.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://i.imgur.com/TCYW4qR.gif&quot; alt=&quot;Demo of RNHANES&quot; /&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;
&lt;p&gt;A stable version of RNHANES is available in the CRAN package repository, and a development version is available on Github.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Install stable version&lt;/span&gt;
install.packages&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;RNHANES&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Install development version&lt;/span&gt;
devtools&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;install_github&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;silentspringinstitute/RNHANES&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Whichever version you install, you need to load the package. We will also be using the &lt;code&gt;tidyverse&lt;/code&gt; package in this analysis because it is a handy wrapper package that automatically loads a number of other packages, like &lt;code&gt;ggplot2&lt;/code&gt; and &lt;code&gt;dplyr&lt;/code&gt;, for you.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span class=&quot;kn&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;tidyverse&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;RNHANES&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;downloading-pfas-data&quot;&gt;Downloading PFAS data&lt;/h2&gt;
&lt;p&gt;There is a &lt;a href=&quot;http://www.cdc.gov/nchs/nhanes/nhanes_questionnaires.htm&quot;&gt;comprehensive index&lt;/a&gt; online of the data available through NHANES. The index links to each file and the associated data dictionary. You can use the index to explore the data that is out there.&lt;/p&gt;

&lt;p&gt;In our case, we are interested in PFASs. The latest available data on PFASs in NHANES is from the 2011-2012 survey cycle. You can download a data file easily through RNHANES:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;pfas_data &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; nhanes_load_data&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;PFC_G&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;2011-2012&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; demographics &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;summary-statistics&quot;&gt;Summary Statistics&lt;/h2&gt;

&lt;p&gt;Now that we have the data, we can compute some summary statistics. A good first question to ask is how many people have a detectable level of PFOA in their blood samples, which we can find using the &lt;code&gt;nhanes_detection_frequency&lt;/code&gt; function:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;nhanes_detection_frequency&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;pfas_data&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;LBXPFOA&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;LBDPFOAL&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;##       value     cycle begin_year end_year file_name  column weights_column
## 1 0.9973545 2011-2012       2011     2012     PFC_G LBXPFOA        WTSA2YR
##   comment_column                name
## 1       LBDPFOAL detection_frequency&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;99.7% of Americans have a detectable level of PFOA in their blood. The logical next step is to find out how much PFOA there is in people’s bodies. The 50th percentile (the median) level gives a estimate of the center of the population, and the 95th percentile an estimate of the levels in highly exposed individuals. With environmental chemicals, there can be large differences in exposure between the 95th and 50th percentiles.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;quantiles &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; nhanes_quantile&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;pfas_data&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;LBXPFOA&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;LBDPFOAL&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; quantiles &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0.95&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;plotting&quot;&gt;Plotting&lt;/h2&gt;

&lt;p&gt;We can plot the distribution as a histogram of values. This isn’t a very useful way of visualizing the data, because most environmental chemicals are log-normal. That is, the log transformation of the chemical levels roughly follows a normal distribution. We can see this for PFOA by applying a log transformation to the data.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;nhanes_hist&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;pfas_data&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;LBXPFOA&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;LBDPFOAL&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;img src=&quot;//silentspring.org/devblog/assets/figure/source/2016-11-22-nhanes-made-simple-with-rnhanes/unnamed-chunk-6-1.png&quot; alt=&quot;plot of chunk unnamed-chunk-6&quot; /&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;nhanes_hist&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;pfas_data&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;LBXPFOA&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;LBDPFOAL&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; transform&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;log&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;img src=&quot;//silentspring.org/devblog/assets/figure/source/2016-11-22-nhanes-made-simple-with-rnhanes/unnamed-chunk-6-2.png&quot; alt=&quot;plot of chunk unnamed-chunk-6&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can learn more about RNHANES on its Github page: &lt;a href=&quot;http://github.com/silentspringinstitute/RNHANES&quot;&gt;http://github.com/silentspringinstitute/RNHANES&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Tue, 22 Nov 2016 00:00:00 +0000</pubDate>
        <link>https://silentspring.org/devblog/2016/11/22/nhanes-made-simple-with-rnhanes.html</link>
        <guid isPermaLink="true">https://silentspring.org/devblog/2016/11/22/nhanes-made-simple-with-rnhanes.html</guid>
        
        <category>tutorial</category>
        
        <category>r</category>
        
        <category>nhanes</category>
        
        <category>rbloggers</category>
        
        
      </item>
    
      <item>
        <title>Fitting censored log-normal data</title>
        <description>&lt;p&gt;Data are censored when samples from one or both ends of a continuous distribution are cut off and assigned one value. Environmental chemical exposure datasets are often left-censored: instruments can detect levels of chemicals down to a limit, underneath which you can’t say for sure how much of the chemical was present. The chemical may not have been present at all, or was present at a low enough level that the instrument couldn’t pick it up.&lt;/p&gt;

&lt;p&gt;There are a number of methods of dealing with censored data in statistics. The crudest approach is to substitute a value for every censored value. This may be zero, the detection limit, the detection limit over the square root of two, or some other value. This method, however, biases the statistical results depending on what you choose to substitute.&lt;/p&gt;

&lt;p&gt;A more nuanced alternative is to assume the data follows a particular distribution. In the case of environmental data, it often makes sense to assume a log-normal distribution. When we do this, while we may not know what the precise levels of every non-detect, we can at least assume that they follow a log-normal distribution.&lt;/p&gt;

&lt;p&gt;In this article, we will walk through fitting a log-normal distribution to a censored dataset using the method of maximum likelihood.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://silentspring.org/devblog/assets/posts/2016-11-02-fitting-censored-log-normal-data/Illustration-1.png&quot; width=&quot;800&quot; alt=&quot;Censored data&quot; /&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;h3 id=&quot;fitting-a-censored-log-normal-distribution&quot;&gt;Fitting a censored log-normal distribution&lt;/h3&gt;

&lt;p&gt;First, we need to generate a contrived dataset. Here we take 10000 samples from a log-normal distribution with a log-mean of 5 and log-standard deviation of 1; call those values \( y \). Any value below \( L = 50 \) will be censored. Let \( y^{\ast} \) be the censored dataset in which every censored point is fixed to the censoring limit. Formally, \( y^{\ast} \) is defined as:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
y^{\ast}=\begin{cases}
y &amp; y&gt;L\\
L &amp; y\leq L
\end{cases} %]]&gt;&lt;/script&gt;

&lt;p&gt;Here we generate a dataset in R:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span class=&quot;kn&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;ggplot2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;tibble&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

L &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;50&lt;/span&gt;

data &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; tibble&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  y &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; rlnorm&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; meanlog &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; sdlog &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
  censored &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; y &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; L&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  y_star &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;ifelse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;censored&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; L&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; y&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

ggplot&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; aes&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; y_star&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
  geom_histogram&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;bins &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;150&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
  scale_x_continuous&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;trans &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;log&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
  xlab&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;log(y_star)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;img src=&quot;//silentspring.org/devblog/assets/figure/source/2016-11-02-fitting-censored-log-normal-data/unnamed-chunk-1-1.png&quot; alt=&quot;plot of chunk unnamed-chunk-1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The spike on the left represents the censored values. The detection frequency, or the proportion of detected values, is 0.8669.&lt;/p&gt;

&lt;p&gt;First, let’s do a better job of defining the problem we’re trying to solve. We set out to fit a log-normal distribution to some censored data. Our fundamental problem here is that we want to find the right parameters (the mean and standard deviation) for a log-normal distribution that “fits”” the observed data. But how do you tell what the “right” parameters are, or what the best “fit” is? The maximum likelihood approach is to say “the best distribution is the one that has the highest likelihood of generating the data we’ve observed.” To actually find those parameters, you use an optimization algorithm that tries a bunch of different parameters and hones in on the one that defines a distribution with the highest likelihood of generating the observed data.&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Let’s develop some intuition about how we are going to handle this censored data. With censored data, we don’t know the exact value of each datapoint that is below a censoring limit. The true value could be anywhere below the limit. To deal with this, we assume that the entire dataset is log-normally distributed, so even if we don’t know the &lt;em&gt;exact&lt;/em&gt; value of the censored data, we know something about how those points are distributed.&lt;/p&gt;

&lt;p&gt;Specifically, let \( P(x \vert \mu, \sigma) \) and \( D(x \vert \mu, \sigma) \) be the log-normal probability density function (&lt;abbr title=&quot;Probability Density Function&quot;&gt;PDF&lt;/abbr&gt;) and cumulative density function (&lt;abbr title=&quot;Cumulative Density Function&quot;&gt;CDF&lt;/abbr&gt;), respectively, taking as parameters a mean \( \mu \) and standard deviation \( \sigma \). We seek to find values for \( \mu \) and \( \sigma \) that maximize the likelihood function \( L(y^{\ast} \vert \mu, \sigma) \). A key assumption is that that the measurements in \( y^{\ast} \) are independent.&lt;/p&gt;

&lt;p&gt;If the point is above the censoring limit, then its likelihood is defined by the log-normal &lt;abbr title=&quot;Probability Density Function&quot;&gt;PDF&lt;/abbr&gt;. If it below the censoring limit, we don’t know where the real value was exactly; all we know is that it’s less than \( L \). As such, its likelihood is the cumulative probability of a value being below \( L \) in a log-normal distribution with mean \( \mu \) and standard deviation \( \sigma \).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://silentspring.org/devblog/assets/posts/2016-11-02-fitting-censored-log-normal-data/Illustration-2.png&quot; width=&quot;800&quot; alt=&quot;Likelihoods for censored and non-censored data&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The total likelihood is found by multiplying all the individual likelihoods.&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; Formally:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
L\left(y^{\ast},\mu,\sigma\right)=\prod\begin{cases}
P\left(y^{\ast}_{i},\mu,\sigma\right) &amp; y^{\ast}_{i}&gt;L\\
D\left(L,\mu,\sigma\right) &amp; y^{\ast}_{i}=L
\end{cases} %]]&gt;&lt;/script&gt;

&lt;p&gt;It’s often more convenient, especially for computers, to work with the log-likelihood function. It’s easy to get it, just take the log of both sides:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\mathcal{L}\left(y^{\ast},\mu,\sigma\right)=\sum\begin{cases}
\log P\left(y^{\ast}_{i},\mu,\sigma\right) &amp; y^{\ast}_{i}&gt;L\\
\log D\left(L,\mu,\sigma\right) &amp; y^{\ast}_{i}=L
\end{cases} %]]&gt;&lt;/script&gt;

&lt;p&gt;The R translation uses the built in &lt;code&gt;dlnorm&lt;/code&gt; and &lt;code&gt;plnorm&lt;/code&gt; functions for the log-normal &lt;abbr title=&quot;Probability Density Function&quot;&gt;PDF&lt;/abbr&gt; and &lt;abbr title=&quot;Cumulative Density Function&quot;&gt;CDF&lt;/abbr&gt;, choosing which one to use based on whether the data point is censored. It also checks the parameters to make sure they make sense: a negative standard deviation is invalid, so the function rejects that parameter set.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;logLikCensoredFun &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;params&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  mean &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; params&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  sd &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; params&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

  &lt;span class=&quot;kr&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;sd &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;NA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;kp&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kp&quot;&gt;ifelse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;censored&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
             plnorm&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;L&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; meanlog &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; sdlog &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; sd&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; log.p &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
             dlnorm&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;data&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;y_star&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; meanlog &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; sdlog &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; sd&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; log &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We use the &lt;code&gt;maxLik&lt;/code&gt; function from the &lt;code&gt;maxLik&lt;/code&gt;&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; package to perform the estimation. We need to supply starting values for the parameters, so let’s have it start with a mean of 0 and standard deviation of 1.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span class=&quot;kn&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;maxLik&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;## Error in library(maxLik): there is no package called &amp;#39;maxLik&amp;#39;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;fit &lt;span class=&quot;o&quot;&gt;&amp;lt;-&lt;/span&gt; maxLik&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;logLik &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; logLikCensoredFun&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
              start &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;mean &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; sd &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;## Error in eval(expr, envir, enclos): could not find function &amp;quot;maxLik&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span class=&quot;kp&quot;&gt;summary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;fit&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;## Error in summary(fit): object &amp;#39;fit&amp;#39; not found&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The fitted distribution gets pretty close to recovering the correct mean and standard deviation. Censored data loses information, so in general you shouldn’t expect to get perfect estimates here.&lt;/p&gt;

&lt;p&gt;Let’s plot the original, uncensored data \( y \) against the distribution fitted to the censored data to see how they compare visually:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;ggplot&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;data &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; data&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; aes&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; y&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
  geom_histogram&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;aes&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;y &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;..&lt;/span&gt;density..&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; bins &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;150&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
  stat_function&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;fun &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; dlnorm&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                args &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;meanlog &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; fit&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;estimate&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;mean&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; sdlog &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; fit&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;estimate&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;sd&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
                color &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;#39;green&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;## Error in layer(data = data, mapping = mapping, stat = StatFunction, geom = geom, : object &amp;#39;fit&amp;#39; not found&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The core idea with this overall approach is that we assume something about the distribution of the censored data points so that we can get more nuanced parameter estimates than if we replaced them with a constant, like zero or the detection limit.&lt;/p&gt;

&lt;p&gt;Future posts will go into regression techniques with censored datasets.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;In “generative” statistical modelling you assume that the data you have was generated by some definable process. The task of the modeller is to write down how they think the data was generated, this is your “model” of how the world works. Everything that follows (parameter fitting, inference) is based off of this core assumption. In our case, we assume the data was generated from a log-normal distribution; that’s our “model” of how the data came to be. As it happens, this is exactly where the data came from! &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;This comes from the assumption that each measurement is independent. Recall that the probability of two independent events occurring is the product of the individual probabilities: \( P(A \, \mathrm{and} \, B) = P(A) \cdot P(B) \) &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;Henningsen, Arne and Toomet, Ott (2011). maxLik: A package for maximum likelihood estimation in R. Computational Statistics 26(3), 443-458. DOI 10.1007/s00180-010-0217-1. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 02 Nov 2016 00:00:00 +0000</pubDate>
        <link>https://silentspring.org/devblog/2016/11/02/fitting-censored-log-normal-data.html</link>
        <guid isPermaLink="true">https://silentspring.org/devblog/2016/11/02/fitting-censored-log-normal-data.html</guid>
        
        <category>r</category>
        
        <category>rbloggers</category>
        
        
      </item>
    
      <item>
        <title>ggplot2 axis limit gotchas</title>
        <description>&lt;p&gt;Setting axis limits in ggplot has behaviour that may be unexpected: any data that falls outside of the limits is ignored, instead of just being hidden. This means that if you apply a statistic or calculation on the data, like plotting a box and whiskers plot, the result will only be based on the data within the limits.&lt;/p&gt;

&lt;p&gt;In other words, ggplot doesn’t “zoom in” on a part of your plot when you apply an axis limit, it recalculates a new plot with the restricted data.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;For example, here is a boxplot without any axis limits:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;&lt;span class=&quot;kn&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;ggplot2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
data&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;iris&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

ggplot&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;iris&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; aes&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; Species&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; y &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; Petal.Length&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
  geom_boxplot&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;img src=&quot;//silentspring.org/devblog/assets/figure/source/2016-11-1-ggplot-axis-limits/unnamed-chunk-1-1.png&quot; alt=&quot;plot of chunk unnamed-chunk-1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;and here is the same one with a set Y axis limit:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;ggplot&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;iris&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; aes&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; Species&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; y &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; Petal.Length&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
  geom_boxplot&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
  ylim&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;## Warning: Removed 84 rows containing non-finite values (stat_boxplot).&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;img src=&quot;//silentspring.org/devblog/assets/figure/source/2016-11-1-ggplot-axis-limits/unnamed-chunk-2-1.png&quot; alt=&quot;plot of chunk unnamed-chunk-2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Note how the box and whiskers are recalculated in this plot. To be fair, ggplot does warn you that it is removing rows!&lt;/p&gt;

&lt;p&gt;If you want to zoom in without removing values, use &lt;code&gt;coord_cartesian&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-r&quot; data-lang=&quot;r&quot;&gt;ggplot&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;iris&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; aes&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;x &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; Species&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; y &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; Petal.Length&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
  geom_boxplot&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;
  coord_cartesian&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;ylim &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;img src=&quot;//silentspring.org/devblog/assets/figure/source/2016-11-1-ggplot-axis-limits/unnamed-chunk-3-1.png&quot; alt=&quot;plot of chunk unnamed-chunk-3&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Tue, 01 Nov 2016 00:00:00 +0000</pubDate>
        <link>https://silentspring.org/devblog/2016/11/01/ggplot-axis-limits.html</link>
        <guid isPermaLink="true">https://silentspring.org/devblog/2016/11/01/ggplot-axis-limits.html</guid>
        
        <category>tips</category>
        
        <category>r</category>
        
        <category>rbloggers</category>
        
        
      </item>
    
      <item>
        <title>What do chemicals look like?</title>
        <description>&lt;p&gt;If you look at the structures of chemicals within a family, you can see striking similarities. Take PCBs, which are industrial chemicals that were banned in the 1970s, as an example:&lt;/p&gt;

&lt;div&gt;


  &lt;img src=&quot;https://silentspring.org/devblog/assets/posts/2016-10-26-what-do-chemicals-look-like/PCB11.png&quot; width=&quot;250&quot; alt=&quot;PCB 11&quot; /&gt;




  &lt;img src=&quot;https://silentspring.org/devblog/assets/posts/2016-10-26-what-do-chemicals-look-like/PCB105.png&quot; width=&quot;250&quot; alt=&quot;PCB 105&quot; /&gt;




  &lt;img src=&quot;https://silentspring.org/devblog/assets/posts/2016-10-26-what-do-chemicals-look-like/PCB201.png&quot; width=&quot;250&quot; alt=&quot;PCB 201&quot; /&gt;


&lt;/div&gt;

&lt;p&gt;We wanted a way to generate beautiful chemical structure visualizations, like the ones you see above, for use in our materials.  We developed a lightweight tool called &lt;code&gt;sdftosvg&lt;/code&gt; that does just that:  it takes as input SDF files, downloadable from repositories like PubChem, and outputs SVG renderings.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;sdftosvg&lt;/code&gt; is available as an &lt;a href=&quot;https://www.npmjs.com/package/sdftosvg&quot;&gt;NPM package&lt;/a&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm install -g sdftosvg&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;example&quot;&gt;Example&lt;/h2&gt;

&lt;p&gt;The chemical triclosan is used as an anti-microbial in soaps, oral care products, and other consumer products. The &lt;a href=&quot;https://pubchem.ncbi.nlm.nih.gov/compound/triclosan&quot;&gt;PubChem page&lt;/a&gt; for triclosan has an &lt;a href=&quot;https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/5564/record/SDF/?record_type=2d&amp;amp;response_type=display&quot;&gt;SDF file&lt;/a&gt; available that defines triclosan’s structure. We can convert the SDF to an svg using &lt;code&gt;sdftosvg&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;sdftosvg triclosan.sdf triclosan.svg&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;img src=&quot;https://silentspring.org/devblog/assets/posts/2016-10-26-what-do-chemicals-look-like/triclosan.png&quot; width=&quot;250&quot; alt=&quot;Triclosan&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Full documentation for the project is available on the project’s &lt;a href=&quot;https://github.com/silentspringinstitute/sdftosvg&quot;&gt;Github page&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Wed, 26 Oct 2016 00:00:00 +0000</pubDate>
        <link>https://silentspring.org/devblog/2016/10/26/what-do-chemicals-look-like.html</link>
        <guid isPermaLink="true">https://silentspring.org/devblog/2016/10/26/what-do-chemicals-look-like.html</guid>
        
        <category>javascript</category>
        
        <category>npm</category>
        
        
      </item>
    
  </channel>
</rss>
