<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Unconstant Conjunction</title>
  <link href="https://unconj.ca/blog/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="https://unconj.ca/blog/" rel="alternate"/>
  <updated>2022-01-24T00:00:00Z</updated>
  <id>https://unconj.ca/blog/</id>
  <author>
    <name>Aaron Jacobs</name>
    <email>atheriel@gmail.com</email>
  </author>
  <generator uri="http://gohugo.io/">Hugo 0.80.0</generator>
  <entry>
    <title type="html">Joining RStudio</title>
    
    <link href="https://unconj.ca/blog/joining-rstudio.html" rel="alternate"/>
    <published>2021-12-09T00:00:00Z</published>
    
    
    <updated>2021-12-09T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2021-12-09:blog/joining-rstudio.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;Over the last few years I&amp;rsquo;ve become interested in opportunities for using R in
production, in the broad sense of code with users other than its original
author. The reason is that this is an important avenue for R users to bring
value to others. In the words of &lt;a href=&#34;https://www.youtube.com/watch?v=th79W4rv67g&#34;&gt;David
Robinson&lt;/a&gt;, &amp;ldquo;anything still on your
computer is, to a first approximation, useless.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;My public work in the R community has also largely fallen into this category,
including production-grade
&lt;a href=&#34;https://cran.r-project.org/package=openmetrics&#34;&gt;metrics&lt;/a&gt; and
&lt;a href=&#34;https://cran.r-project.org/package=log4r&#34;&gt;logging&lt;/a&gt; packages, &lt;a href=&#34;https://github.com/atheriel/longears/&#34;&gt;connecting R to
RabbitMQ&lt;/a&gt; (which is very popular in
enterprise production systems), and writing &lt;a href=&#34;https://github.com/atheriel/xrprof/&#34;&gt;R&amp;rsquo;s first external
profiler&lt;/a&gt; &amp;ndash; a tool for answering questions
like &amp;ldquo;&lt;a href=&#34;https://www.rstudio.com/resources/rstudioglobal-2021/introducing-xrprof-a-new-way-to-profile-r/&#34;&gt;why is my R code slow in
production?&lt;/a&gt;&amp;rdquo;&lt;/p&gt;
&lt;p&gt;My private work in R has included work on &lt;a href=&#34;./writing-proprietary-r-packages.html&#34;&gt;platforms and
tools&lt;/a&gt; to build and host many dozens of
internal packages as well as development of production R APIs and Shiny apps. I
was also intimately involved in migrating many of these workloads to Kubernetes
&amp;ndash; increasingly the target for production workloads in industry, and a tool I
feel strongly about as part of R&amp;rsquo;s future.&lt;/p&gt;
&lt;p&gt;In my experience it can be empowering for R users to have a clear path from
ad-hoc analysis to &amp;ldquo;data products&amp;rdquo; &amp;ndash; graphics, emails, reports, APIs, or even
&lt;a href=&#34;https://shiny.rstudio.com/&#34;&gt;interactive applications&lt;/a&gt; &amp;ndash; as they need them. And
so I&amp;rsquo;ve been advocating for these data products to have production-friendly
defaults (or at least production-friendly stories), all while personally
discovering what it means, operationally, to actually take R to production.&lt;/p&gt;
&lt;p&gt;A few months ago I had the realisation that if I&amp;rsquo;m really serious about
expanding the frontier for R in production, the best place to do so is at
RStudio. No organisation is as plugged into the broader ecosystem as they are,
and no organisation has as broad a reach to improve these tools and techniques
for the wider data science community, in R and beyond.&lt;/p&gt;
&lt;p&gt;So I&amp;rsquo;m happy to announce that I have joined RStudio, at least in part to work on
improving the story for R in production, and to help out the folks making that
leap.&lt;/p&gt;
    </content>
    
    
    <category term="r"/>
    <category term="rstudio"/>
  </entry>
  <entry>
    <title type="html">Shipping Application Logs from RStudio Connect</title>
    
    <link href="https://unconj.ca/blog/shipping-application-logs-from-rsconnect.html" rel="alternate"/>
    <published>2021-04-29T00:00:00Z</published>
    
    
    <updated>2021-04-29T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2021-04-29:blog/shipping-application-logs-from-rsconnect.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;RStudio has an enterprise offering called &lt;a href=&#34;https://www.rstudio.com/products/connect/&#34;&gt;RStudio
Connect&lt;/a&gt; that is designed to host R
(and now Python) content. In my experience it&amp;rsquo;s a great platform for R users
using the RStudio IDE, and works particularly well for frictionless deployment
of internal Shiny apps or RMarkdown reports.&lt;/p&gt;
&lt;p&gt;But one of the things we&amp;rsquo;ve struggled with in using Connect is making Shiny app
logs useful. You can view logs for individual sessions in the browser (if you
know what you&amp;rsquo;re looking for), but there&amp;rsquo;s no searching or aggregation of any
kind. This is the existing interface:&lt;/p&gt;
&lt;img src=&#34;./images/rsconnect-log-gui.png&#34; alt=&#34;RStudio Connect Log GUI&#34; width=&#34;331&#34; height=&#34;541&#34;&gt;
&lt;p&gt;This is doubly frustrating for users with experience with any other log
management system &amp;ndash; a crowded field, with many commercial and open-source
solutions available. These solutions typically offer not only searching but
complex querying, visualisation, and ad-hoc dashboard capabilities.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; For
example, check out &lt;a href=&#34;https://www.elastic.co/kibana&#34;&gt;the landing page for
Elasticsearch/Kibana&lt;/a&gt;, which is the most popular
open-source option. Common commercial choices include Splunk and Datadog, and
all of the cloud vendors have highly-integrated platforms of their own.&lt;/p&gt;
&lt;p&gt;Unfortunately, Connect won&amp;rsquo;t work natively with any of these tools. Log
management is focused on the per-session GUI.&lt;/p&gt;
&lt;p&gt;Motivated by our own internal desire to get Shiny logs into Splunk, I wrote a
Connect-specific plugin for the open-source &lt;a href=&#34;https://fluentbit.io/&#34;&gt;Fluent Bit&lt;/a&gt;
project. Fluent Bit itself is a fast, lightweight log forwarding and aggregation
program with a vibrant plugin community.&lt;/p&gt;
&lt;p&gt;The plugin works by watching for new logs written to the filesystem and querying
&lt;a href=&#34;https://docs.rstudio.com/connect/api/&#34;&gt;the Connect API&lt;/a&gt; for additional metadata
to link these logs back to specific applications. Fluent Bit can then be used to
forward the results to any of its &lt;a href=&#34;https://docs.fluentbit.io/manual/pipeline/outputs&#34;&gt;supported
backends&lt;/a&gt;, including
Elasticsearch/Kibana, Splunk, Stackdriver, Cloudwatch Logs, Datadog, Loki, and
many others.&lt;/p&gt;
&lt;p&gt;This should allow R users to easily export logs to their organisation&amp;rsquo;s existing
log management system without needing to modify their reports or Shiny apps to
do so. For example, log entries look like this in our Splunk instance:&lt;/p&gt;
&lt;img src=&#34;./images/rsconnect-log-in-splunk.png&#34; alt=&#34;RStudio Connect Log Entry in Splunk&#34; width=&#34;762&#34; height=&#34;236&#34;&gt;
&lt;p&gt;You can see from the above that entries contain not only the log message,
&amp;ldquo;Warning in readLines&amp;hellip;&amp;rdquo;, but also the session identifier, the name of the app
or report, and the app mode &amp;ndash; a Shiny application, in this case. Support for
Connect&amp;rsquo;s tag system will probably be added in the future.&lt;/p&gt;
&lt;p&gt;The plugin is open-source under the LGPL 2.1 and available &lt;a href=&#34;https://github.com/atheriel/fluent-bit-rsconnect&#34;&gt;on
GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Shoutout to Cole Arendt for his advice on using Connect&amp;rsquo;s APIs to make this
work.&lt;/em&gt;&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;As an aside: originally we pushed Shiny app logs into our Splunk instance
by having them write to the local syslog via the
&lt;a href=&#34;https://cran.r-project.org/package=rsyslog&#34;&gt;&lt;strong&gt;rsyslog&lt;/strong&gt;&lt;/a&gt; package, which
was then independently forwarded on to Splunk. My coworker Nicholas Jhirad
mentioned some of this history in &lt;a href=&#34;https://youtu.be/hFKwzJBXvIU?t=1660&#34;&gt;a talk at eRum last
year&lt;/a&gt;. A huge downside of this
approach is that it requires everyone who writes a Shiny app to opt in to
using this package, and any message not sent through it is lost. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
    </content>
    
    
    <category term="r"/>
    <category term="shiny"/>
    <category term="rstudio"/>
    <category term="logging"/>
  </entry>
  <entry>
    <title type="html">.NET, rsync, and the Linux Page Cache: A Kubernetes War Story</title>
    
    <link href="https://unconj.ca/blog/dotnet-rsync-page-cache-a-kubernetes-war-story.html" rel="alternate"/>
    <published>2021-02-12T00:00:00Z</published>
    
    
    <updated>2021-02-12T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2021-02-12:blog/dotnet-rsync-page-cache-a-kubernetes-war-story.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;Everyone gets a &lt;a href=&#34;https://k8s.af/&#34;&gt;Kubernetes war story&lt;/a&gt;, right? Well, here&amp;rsquo;s
mine.&lt;/p&gt;
&lt;p&gt;At work we have a huge, business-critical C# service that I helped to port to
Linux (from the Windows-only .NET framework) to run under Kubernetes. This
service emits a large number of logs.&lt;/p&gt;
&lt;p&gt;Like, a lot of logs. Many gigabytes of logs per day, in sequentially-numbered
text files of 50MB each.&lt;/p&gt;
&lt;p&gt;For various reasons the developers of this application preferred to be able to
look at these logs as actual files for post-mortem analysis rather than through
our existing centralised logging tools. Under Windows they would remote into a
server and inspect a mounted drive with the logs.&lt;/p&gt;
&lt;p&gt;As part of the porting effort they asked me to emulate this workflow.&lt;/p&gt;
&lt;h2 id=&#34;log-to-the-network-fileshare-like-its-1999&#34;&gt;Log to the Network Fileshare Like It&amp;rsquo;s 1999&lt;/h2&gt;
&lt;p&gt;Since we&amp;rsquo;re running Azure&amp;rsquo;s Kubernetes offering, I had the pods &lt;a href=&#34;https://docs.microsoft.com/en-us/azure/aks/azure-files-dynamic-pv&#34;&gt;mount an Azure
Files share&lt;/a&gt;
as a persistent volume &amp;ndash; which is basically a &lt;a href=&#34;https://en.wikipedia.org/wiki/Server_Message_Block&#34;&gt;classic network
fileshare&lt;/a&gt; &amp;ndash; and write
their logs to that. Developers could then mount that fileshare to their local
Windows computers via Azure&amp;rsquo;s SMB support. Very convenient.&lt;/p&gt;
&lt;p&gt;However, it turns out that writing all of these logs to this network fileshare
introduced so much latency to normal operations that the application ran about
3x slower on Kubernetes than it ran on Windows, which really undermined the
effort we&amp;rsquo;d made porting it.&lt;/p&gt;
&lt;p&gt;To &amp;ldquo;fix&amp;rdquo; this I introduced a very simple workaround: I had the app write logs to
the local disk, and then I ran a dead-simple
&lt;a href=&#34;https://en.wikipedia.org/wiki/Rsync&#34;&gt;rsync&lt;/a&gt; command (in a &lt;a href=&#34;https://kubernetes.io/docs/concepts/workloads/pods/#using-pods&#34;&gt;sidecar
container&lt;/a&gt;)
every minute or so to sync these logs to the network fileshare for later
inspection.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;That&amp;rsquo;s how we did it in the old days.&lt;/p&gt;
&lt;p&gt;&amp;ndash; Our CTO, amused.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This worked nicely and brought the performance up to par (better, thankfully,
than it had been on Windows).&lt;/p&gt;
&lt;p&gt;Time passed.&lt;/p&gt;
&lt;h2 id=&#34;eviction-notice&#34;&gt;Eviction Notice&lt;/h2&gt;
&lt;p&gt;Soon, we started having a problem with this application: Kubernetes would
frequently
&lt;a href=&#34;https://kubernetes.io/docs/tasks/administer-cluster/out-of-resource/#evicting-end-user-pods&#34;&gt;evict&lt;/a&gt;
the service&amp;rsquo;s pods for consuming too much memory and destabilising the cluster,
essentially terminating them without warning.&lt;/p&gt;
&lt;p&gt;Evictions might be fine for misbehaving stateless applications, but this service
was heavily, expensively stateful. Unexpected shutdowns lost us real revenue.&lt;/p&gt;
&lt;p&gt;What was puzzling about this was that Kubernetes was claiming that our service
was using far more memory than I&amp;rsquo;d anticipated &amp;ndash; think 4GB to an expected 1.5.
During the porting effort I&amp;rsquo;d carefully set the pods&#39; &lt;a href=&#34;https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-requests-and-limits-of-pod-and-container&#34;&gt;memory
requests&lt;/a&gt;
to match observed memory usage on Windows and test runs on Linux.&lt;/p&gt;
&lt;p&gt;At first I wondered if Kubernetes was measuring something incorrectly, so I
found a pod with high memory usage that would likely be evicted soon and opened
a shell into it. You can check a container&amp;rsquo;s memory usage once inside by
inspecting &lt;a href=&#34;https://en.wikipedia.org/wiki/Sysfs&#34;&gt;Sysfs&lt;/a&gt; directly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;root@&amp;lt;container&amp;gt;# cat /sys/fs/cgroup/memory/memory.usage_in_bytes
&lt;span class=&#34;m&#34;&gt;4248424448&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So it clearly wasn&amp;rsquo;t measurement error. To dig a little deeper I looked at the
full memory usage statistics for the container:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;root@&amp;lt;container&amp;gt;# cat /sys/fs/cgroup/memory/memory.stat
cache &lt;span class=&#34;m&#34;&gt;2910048256&lt;/span&gt;
rss &lt;span class=&#34;m&#34;&gt;1322893312&lt;/span&gt;
&amp;lt;snip&amp;gt;
active_file &lt;span class=&#34;m&#34;&gt;2884849664&lt;/span&gt;
&amp;lt;snip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;rss&lt;/code&gt; entry (for &lt;a href=&#34;https://en.wikipedia.org/wiki/Resident_set_size&#34;&gt;resident set
size&lt;/a&gt;) is close to what we had
used to measure &lt;a href=&#34;https://docs.microsoft.com/en-us/windows-hardware/test/wpt/wpa-reference-set&#34;&gt;memory usage on
Windows&lt;/a&gt;,
and looked like what I would expect for the service under that particular
configuration.&lt;/p&gt;
&lt;p&gt;So what are those &lt;code&gt;cache&lt;/code&gt; and &lt;code&gt;active_file&lt;/code&gt; entries?&lt;/p&gt;
&lt;p&gt;It turns out that Linux aggressively caches recently-used files in memory, in
what is called &lt;a href=&#34;https://en.wikipedia.org/wiki/Page_cache&#34;&gt;the Page Cache&lt;/a&gt;, in
order to improve filesystem performance. Normally this does not constrain
applications from using memory, because when the system starts to run low Linux
will happily flush older parts of this cache to make the reclaimed RAM
available.&lt;/p&gt;
&lt;p&gt;But where could 2.8GB of recently-used file memory be coming from?&lt;/p&gt;
&lt;p&gt;Oh. Right.&lt;/p&gt;
&lt;p&gt;I was able to confirm (using &lt;a href=&#34;https://github.com/tobert/pcstat&#34;&gt;a handy tool I found on
GitHub&lt;/a&gt;) that &lt;em&gt;all&lt;/em&gt; of the individual log
files were indeed in the page cache (about 55 of them in the case above).&lt;/p&gt;
&lt;h2 id=&#34;caches-to-caches&#34;&gt;Caches to Caches&lt;/h2&gt;
&lt;p&gt;With this in hand a picture of what was happening emerges:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The log files for the service are cached in memory by Linux, but rarely
flushed unless the machine it&amp;rsquo;s running on happens to be low on total memory.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Kubernetes (rightly) views page cache usage as part of a container&amp;rsquo;s
workload, so it counts when making resource allocation/scheduling decisions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Scheduling decisions &lt;em&gt;also&lt;/em&gt; include kicking overly greedy pods off the
cluster, but in this case it&amp;rsquo;s actually a Linux kernel optimisation that
makes the application look more memory-hungry than it really is.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I discovered much later that we&amp;rsquo;re not the only ones with this problem:
including the page cache in the memory calculations for an eviction is
considered &lt;a href=&#34;https://github.com/kubernetes/kubernetes/issues/43916&#34;&gt;a longstanding bug in Kubernetes
itself&lt;/a&gt; that has received
ample commentary. As you&amp;rsquo;ll discover in that thread, it&amp;rsquo;s a tricky issue to
solve, which is probably why it hasn&amp;rsquo;t been.&lt;/p&gt;
&lt;p&gt;It does turn out to be possible to remove individual files from the page cache
manually by using &lt;a href=&#34;https://man7.org/linux/man-pages/man2/posix_fadvise.2.html&#34;&gt;a Linux-specific &lt;code&gt;posix_fadvise(2)&lt;/code&gt;
flag&lt;/a&gt;. Years ago
Tobi Oetiker actually proposed &lt;a href=&#34;https://tobi.oetiker.ch/patches/&#34;&gt;modifying &lt;code&gt;rsync&lt;/code&gt;
itself&lt;/a&gt; to do this so that the files it copied
did not end up in the page cache &amp;ndash; but this was never merged upstream.&lt;/p&gt;
&lt;p&gt;We briefly considered using a patched version of &lt;code&gt;rsync&lt;/code&gt; or even running a
second sidecar to periodically &lt;code&gt;posix_fadvise()&lt;/code&gt; the log files to get them out
of the cache.&lt;/p&gt;
&lt;p&gt;Eventually we settled on a less obscure method: we
&lt;a href=&#34;https://logging.apache.org/log4net/release/sdk/html/T_log4net_Appender_RollingFileAppender.htm&#34;&gt;configured&lt;/a&gt;
the C# service to keep only the three most recent log files (though files still
have a unique suffix to prevent collisions). Provided it doesn&amp;rsquo;t log more than
150MB in the one-minute window between &lt;code&gt;rsync&lt;/code&gt; runs, this means we end up with
all of the logs on the network fileshare, while still deleting them on the local
disk to free up space in the page cache.&lt;/p&gt;
&lt;p&gt;All of this just reinforced for me the wisdom of Charity Majors&amp;rsquo;s collection of
&lt;a href=&#34;https://www.honeycomb.io/blog/lies-my-parents-told-me-about-logs/&#34;&gt;lies we believe about
logging&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Logs are cheap.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;They’re just logs, they can’t impact production reliability.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;They’re just logs, they can’t possibly impact my code efficiency.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
    </content>
    
    
    <category term="c#"/>
    <category term="kubernetes"/>
  </entry>
  <entry>
    <title type="html">Pushing Prometheus Metrics from R Scripts and Reports</title>
    
    <link href="https://unconj.ca/blog/pushing-prometheus-metrics-from-r-scripts-and-reports.html" rel="alternate"/>
    <published>2020-09-15T00:00:00Z</published>
    
    
    <updated>2020-09-15T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2020-09-15:blog/pushing-prometheus-metrics-from-r-scripts-and-reports.html</id>
    
    <content type="html" xml:lang="en">
      &lt;img src=&#34;./images/openmetrics-etl.png&#34; alt=&#34;From R to Pushgateway to Prometheus&#34; width=&#34;720&#34; height=&#34;360&#34;&gt;
&lt;p&gt;The &lt;a href=&#34;https://cran.r-project.org/package=openmetrics&#34;&gt;&lt;strong&gt;openmetrics&lt;/strong&gt;&lt;/a&gt; R package
now supports &lt;a href=&#34;https://prometheus.io/docs/instrumenting/pushing/&#34;&gt;pushing
metrics&lt;/a&gt; to a &lt;a href=&#34;https://github.com/prometheus/pushgateway/blob/master/README.md&#34;&gt;Prometheus
Pushgateway&lt;/a&gt;
instance, which is useful for short-lived batch scripts or RMarkdown reports.&lt;/p&gt;
&lt;p&gt;You might want to expose metrics from these scripts or reports to Prometheus in
order to improve monitoring and alerting on failures, but many of these
processes are not around long enough to run a webserver that Prometheus can pull
from.&lt;/p&gt;
&lt;p&gt;This is where the Pushgateway comes in. It allows you to push metrics to a
centralised location where they can be aggregated and then scraped by Prometheus
itself. But beware: there are &lt;a href=&#34;https://prometheus.io/docs/practices/pushing/&#34;&gt;a limited
number&lt;/a&gt; of use cases for pushing
metrics, and you should always prefer pull-based methods when possible.&lt;/p&gt;
&lt;h2 id=&#34;instrumenting-an-r-etl-job&#34;&gt;Instrumenting an R ETL Job&lt;/h2&gt;
&lt;p&gt;Often R users find themselves writing an R script (&lt;a href=&#34;https://solutions.rstudio.com/examples/apps/output-file-etl/&#34;&gt;or RMarkdown
report&lt;/a&gt;) that runs
regularly, pulling data from a database and creating a new dataset for further
reporting, visualisation or modelling. This is the &amp;ldquo;extract, transform, load&amp;rdquo;
(ETL) pattern.&lt;/p&gt;
&lt;p&gt;There are two natural metrics that we might want to expose from such a script to
Prometheus:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Whether or not the ETL succeeded; and&lt;/li&gt;
&lt;li&gt;How long it took.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;success&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;gauge_metric&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;etl_outcome&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Whether or not the ETL process succeeded.&amp;#34;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;gauge_metric&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;etl_duration_seconds&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Total running time of the ETL process.&amp;#34;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We might also add more granular timing metrics, parcelling out the database pull
(so it could be tracked over time), and more domain-specific metrics (such as
the number of users in the resulting dataset):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;db_pull_duration&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;gauge_metric&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;etl_db_pull_duration_seconds&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;Total time spent pulling data into the ETL process.&amp;#34;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;users&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;gauge_metric&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;etl_users_processed&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Number of unique users processed by the ETL.&amp;#34;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These are all &lt;a href=&#34;https://prometheus.io/docs/concepts/metric_types/#gauge&#34;&gt;gauges&lt;/a&gt;,
because we are not taking repeated measures and none of them are expected to
increase monotonically.&lt;/p&gt;
&lt;p&gt;Actually using these metrics in an ETL script might look as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;start&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;Sys.time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;elapsed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;unclass&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;difftime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Sys.time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;start&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;units&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;secs&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;pull_from_db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;db_pull_duration&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;elapsed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;clean&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;process_raw_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;write_cleaned_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;users&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;unique&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clean&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;user_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;success&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;duration&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;elapsed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These metrics can then be pushed to a Pushgateway instance at the end of the
script:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;push_to_gateway&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;http://localhost:9091&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;job&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;etl-job-1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can also use &lt;code&gt;on.exit()&lt;/code&gt; to ensure metrics are pushed even if the script
fails.&lt;/p&gt;
&lt;p&gt;If you have parameterised scripts or reports (say, running one job for each
language group of your users), you can pass these parameters through as labels
on the job in Pushgateway:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;push_to_gateway&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;http://localhost:9091&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;job&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;etl-job-1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lang&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;en&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These metrics would look like the following when rendered:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# HELP etl_outcome Whether or not the ETL process succeeded.
# TYPE etl_outcome gauge
etl_outcome 1
# HELP etl_duration_seconds Total running time of the ETL process.
# TYPE etl_duration_seconds gauge
etl_duration_seconds 1.21224451065063
# HELP etl_db_pull_duration_seconds Total time spent pulling data into the ETL process.
# TYPE etl_db_pull_duration_seconds gauge
etl_db_pull_duration_seconds 1.18743181228638
# HELP etl_users_processed Number of unique users processed by the ETL.
# TYPE etl_users_processed gauge
etl_users_processed 100
# EOF
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;bonus-timing-chunks-with-knitr-hooks&#34;&gt;Bonus: Timing Chunks with knitr Hooks&lt;/h2&gt;
&lt;p&gt;The &lt;strong&gt;knitr&lt;/strong&gt; package used to render RMarkdown reports sports a feature called
&lt;a href=&#34;https://yihui.org/knitr/hooks/#chunk-hooks&#34;&gt;hooks&lt;/a&gt; that can be used to run code
before and after a chunk is executed. This can be used to time the chunk without
cluttering the code with metric-related boilerplate.&lt;/p&gt;
&lt;p&gt;To do this, we need to define a hook in the RMarkdown document:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;knit_hooks&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration_metric&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;before&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;options&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;envir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;before&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;envir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;.start&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;Sys.time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;exists&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;options&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration_metric&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;envir&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;envir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
      &lt;span class=&#34;n&#34;&gt;elapsed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unclass&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;difftime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Sys.time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;envir&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;.start&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;units&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;secs&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
      &lt;span class=&#34;n&#34;&gt;envir[[options&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;duration_metric]]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;set&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;elapsed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
      &lt;span class=&#34;nf&#34;&gt;stop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;No object matching duration_metric found.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then use it as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```​{r chunk-1, duration_metric = &amp;quot;db_pull_duration&amp;quot;}
df &amp;lt;- pull_from_db()
```
&lt;/code&gt;&lt;/pre&gt;
    </content>
    
    
    <category term="r"/>
    <category term="metrics"/>
  </entry>
  <entry>
    <title type="html">Annotating Deployments in Grafana Using the Process Start Time Metric</title>
    
    <link href="https://unconj.ca/blog/annotating-deployments-using-process-start-time.html" rel="alternate"/>
    <published>2020-05-22T00:00:00Z</published>
    
    
    <updated>2020-05-22T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2020-05-22:blog/annotating-deployments-using-process-start-time.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;Grafana sports a feature called
&lt;a href=&#34;https://grafana.com/docs/grafana/latest/reference/annotations/&#34;&gt;Annotations&lt;/a&gt;
that allow you to label a timestamp on a dashboard with meaningful events &amp;ndash;
most commonly deployments, campaigns, or outages:&lt;/p&gt;
&lt;img src=&#34;./images/annotated-grafana-panel-with-start-time.png&#34; alt=&#34;Process start time annotations on a Grafana panel&#34; width=&#34;864&#34; height=&#34;429&#34;&gt;
&lt;p&gt;(In this case annotating the simulated deployment of a &lt;a href=&#34;https://docs.fluentbit.io/manual/&#34;&gt;Fluent
Bit&lt;/a&gt; container, which I&amp;rsquo;ve used to forward
container logs out of the cluster.)&lt;/p&gt;
&lt;p&gt;Annotations can be input manually, but the only recommendations I&amp;rsquo;ve seen to
generate them automatically is to use something like
&lt;a href=&#34;https://grafana.com/blog/2019/12/09/how-to-do-automatic-annotations-with-grafana-and-loki/&#34;&gt;Loki&lt;/a&gt;,
or &lt;a href=&#34;https://frederic-hemberger.de/notes/grafana/annotate-dashboards-with-deployments/&#34;&gt;teaching your CI/CD
system&lt;/a&gt;
to interact with Grafana&amp;rsquo;s web API. However, if you&amp;rsquo;re running a simple
Prometheus + Grafana stack (say, using the &lt;a href=&#34;https://coreos.com/blog/the-prometheus-operator.html&#34;&gt;Prometheus
Operator&lt;/a&gt; on Kubernetes),
you might be reticent to add more complexity to your setup just to get
deployment annotations.&lt;/p&gt;
&lt;p&gt;Fortunately, there&amp;rsquo;s a simpler alternative for this narrow case: you can use the
&lt;code&gt;process_start_time_seconds&lt;/code&gt; metric from Prometheus to get an approximate idea
of when apps or pods were started. I haven&amp;rsquo;t seen this approach recommended
elsewhere, which is the purpose of this post.&lt;/p&gt;
&lt;p&gt;It turns out that &lt;code&gt;process_start_time_seconds&lt;/code&gt; is exposed by almost all
applications because it&amp;rsquo;s one of the standard metrics &lt;a href=&#34;https://prometheus.io/docs/instrumenting/writing_clientlibs/#process-metrics&#34;&gt;recommended by Prometheus
itself&lt;/a&gt;
and is exported by most client libraries automatically (including &lt;a href=&#34;./introducing-openmetrics-for-r.html&#34;&gt;my
own&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;You can add annotations like the one in the image above as follows, assuming you
have a &lt;code&gt;namespace&lt;/code&gt; and &lt;code&gt;pod&lt;/code&gt; &lt;a href=&#34;https://grafana.com/docs/grafana/latest/variables/templates-and-variables/&#34;&gt;template
variable&lt;/a&gt;
defined:&lt;/p&gt;
&lt;img src=&#34;./images/create-start-time-annotation-in-grafana.png&#34; alt=&#34;Adding process start time annotations in the Grafana web UI&#34; width=&#34;902&#34; height=&#34;628&#34;&gt;
&lt;p&gt;It&amp;rsquo;s important to understand that these annotations will show only when new
processes are started, most likely because of a deployment but also during
rescheduling, scaling, or a pod failure &amp;ndash; but since it is likely that you&amp;rsquo;d
want to know about those as well, perhaps that&amp;rsquo;s a good thing.&lt;/p&gt;
    </content>
    
    
    <category term="metrics"/>
    <category term="kubernetes"/>
  </entry>
  <entry>
    <title type="html">Introducing openmetrics: A Opinionated Prometheus Client for R</title>
    
    <link href="https://unconj.ca/blog/introducing-openmetrics-for-r.html" rel="alternate"/>
    <published>2020-05-17T00:00:00Z</published>
    
    
    <updated>2020-05-17T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2020-05-17:blog/introducing-openmetrics-for-r.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;My &lt;strong&gt;openmetrics&lt;/strong&gt; package is now &lt;a href=&#34;https://cran.r-project.org/package=openmetrics&#34;&gt;available on
CRAN&lt;/a&gt;. The package makes it
possible to add predefined and custom &amp;ldquo;metrics&amp;rdquo; to any R web application and
expose them on a &lt;code&gt;/metrics&lt;/code&gt; endpoint, where they can be consumed by
&lt;a href=&#34;https://prometheus.io/&#34;&gt;Prometheus&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Prometheus itself is a hugely popular, open-source monitoring and metrics
aggregation tool that is widely used in the Kubernetes ecosystem, usually
alongside &lt;a href=&#34;https://grafana.com/&#34;&gt;Grafana&lt;/a&gt; for visualisation.&lt;/p&gt;
&lt;p&gt;To illustrate, the following is a real Grafana dashboard built from the default
metrics exposed by the package for &lt;a href=&#34;https://www.rplumber.io/&#34;&gt;Plumber APIs&lt;/a&gt;:&lt;/p&gt;
&lt;img src=&#34;./images/openmetrics-grafana.png&#34; alt=&#34;Grafana Dashboard&#34; width=&#34;1460&#34; height=&#34;826&#34;&gt;
&lt;p&gt;Adding these to an existing Plumber API is extremely simple:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;openmetrics&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;srv&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plumber&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;plumb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;plumber.R&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;srv&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;register_plumber_metrics&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;srv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;srv&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There is also built-in support for &lt;a href=&#34;https://shiny.rstudio.com/&#34;&gt;Shiny&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;shiny&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;shinyApp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;register_shiny_metrics&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;openmetrics&lt;/strong&gt; is designed to be &amp;ldquo;batteries included&amp;rdquo; and offer good built-in
metrics for existing applications, but it is also possible (and encouraged!) to
add custom metrics tailored to your needs, and to expose them to Prometheus even
if you are not using Plumber or Shiny.&lt;/p&gt;
&lt;p&gt;More detailed usage information is available in the package&amp;rsquo;s
&lt;a href=&#34;https://github.com/atheriel/openmetrics/blob/master/README.md&#34;&gt;&lt;code&gt;README&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
    </content>
    
    
    <category term="r"/>
    <category term="plumber"/>
    <category term="shiny"/>
    <category term="metrics"/>
    <category term="kubernetes"/>
  </entry>
  <entry>
    <title type="html">Three Useful Endpoints for Any Plumber API</title>
    
    <link href="https://unconj.ca/blog/three-useful-endpoints-for-any-plumber-api.html" rel="alternate"/>
    <published>2020-04-21T00:00:00Z</published>
    
    
    <updated>2020-04-21T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2020-04-21:blog/three-useful-endpoints-for-any-plumber-api.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;The &lt;a href=&#34;https://www.rplumber.io/&#34;&gt;Plumber package&lt;/a&gt; is a popular way to make R
models or other code accessible to others with an HTTP API. It&amp;rsquo;s easy to get
started using Plumber, but it&amp;rsquo;s not always clear what to do after you have a
basic API up and running.&lt;/p&gt;
&lt;p&gt;This post shares three simple endpoints I&amp;rsquo;ve used on dozens of Plumber APIs to
make them easier to debug and deploy in development and production environments:
&lt;code&gt;/_ping&lt;/code&gt;, &lt;code&gt;/_version&lt;/code&gt;, and &lt;code&gt;/_sessioninfo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Most Plumber users will be familiar with the special &lt;code&gt;plumber.R&lt;/code&gt; files that can
be used to generate an API. However, for the examples in this post it is
convenient to add them
&lt;a href=&#34;https://www.rplumber.io/docs/programmatic-usage.html&#34;&gt;programmatically&lt;/a&gt;.
Programmatic endpoints are less user-friendly, but also less magic.&lt;/p&gt;
&lt;h2 id=&#34;the-ping-or-healthcheck-endpoint&#34;&gt;The &amp;ldquo;Ping&amp;rdquo; or &amp;ldquo;Healthcheck&amp;rdquo; Endpoint&lt;/h2&gt;
&lt;p&gt;Healthcheck endpoints (often called &lt;code&gt;/status&lt;/code&gt;, &lt;code&gt;/healthz&lt;/code&gt;, or my personal
favourite, &lt;code&gt;/_ping&lt;/code&gt;) give an outside observer the answer to a simple question:
is the API up and running?&lt;/p&gt;
&lt;p&gt;To implement it, just return an empty &amp;ldquo;OK&amp;rdquo;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;srv&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plumber&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;plumb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;plumber.R&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;srv&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;handle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;GET&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;/_ping&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;req&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;setHeader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Content-Type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;200L&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;body&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# ...&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;srv&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This allows you to check if you API is up and running from a browser (by
visiting &lt;code&gt;http://myapi.host/_ping&lt;/code&gt;) or the comfort of your R console (with
&lt;code&gt;httr::GET()&lt;/code&gt;, say). It also makes your API visible to any monitoring tools used
by teams in your organisation to keep tabs on running services.&lt;/p&gt;
&lt;p&gt;A healthcheck endpoint also integrates well with many tools in the Docker
ecosystem, which is a common way to deploy Plumber APIs. For example, a
&lt;code&gt;Dockerfile&lt;/code&gt; can contain a &lt;code&gt;HEALTHCHECK&lt;/code&gt; directive. Here&amp;rsquo;s one from an internal
API:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-dockerfile&#34; data-lang=&#34;dockerfile&#34;&gt;&lt;span class=&#34;c&#34;&gt;# Check the /_ping endpoint every 30 seconds.&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;HEALTHCHECK --interval=30s --timeout=5s &lt;/span&gt;--start-period&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;30s &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;  CMD curl --silent --fail http://0.0.0.0:8080/_ping &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These healthcheck commands are understood by the Docker daemon and used to
determine whether containers are &amp;ldquo;healthy&amp;rdquo; (or &amp;ldquo;unhealthy&amp;rdquo; and in need of a
restart) &amp;ndash; which you can see in commands like &lt;code&gt;docker ps&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;$ docker ps --format &amp;quot;table {{.ID}}\t{{.RunningFor}}\t{{.Status}}&amp;quot;
CONTAINER ID        CREATED             STATUS
7cedb56515a8        6 hours ago         Up 6 hours (healthy)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you don&amp;rsquo;t want to modify the image directly, the Docker compose &lt;a href=&#34;https://docs.docker.com/compose/compose-file/&#34;&gt;file
format&lt;/a&gt; (also used by Docker
Swarm) supports adding healthchecks as well:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;nt&#34;&gt;healthcheck&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;test&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;curl --silent --fail http://0.0.0.0:8080/_ping || exit 1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;interval&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;30s&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;timeout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;5s&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Both Docker Swarm and Kubernetes automatically use the healthchecks to
understand if a deployment was successful, and also to implement zero-downtime
rolling updates.&lt;/p&gt;
&lt;p&gt;Over in the Kubernetes camp, you can also use the
&lt;a href=&#34;https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/&#34;&gt;built-in&lt;/a&gt;
liveness (and/or readiness) probes in Pods and Deployments. Here is one from
ours:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;nt&#34;&gt;livenessProbe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;httpGet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;/_ping&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;8080&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;initialDelaySeconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;periodSeconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;timeoutSeconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Kubernetes&amp;rsquo;s built-in probes have the advantage of &lt;a href=&#34;https://blog.sixeyed.com/docker-healthchecks-why-not-to-use-curl-or-iwr/&#34;&gt;not requiring the Docker
image to bundle &lt;code&gt;curl&lt;/code&gt; or a Windows equivalent&lt;/a&gt;,
too.&lt;/p&gt;
&lt;p&gt;On a related note, Kelsey Hightower has a &lt;a href=&#34;https://vimeo.com/173610242&#34;&gt;talk&lt;/a&gt; on
healthcheck endpoints where he suggests that applications use them to report
various kinds of &amp;ldquo;readiness&amp;rdquo; measures, for example whether they can successfully
connect to an underlying database.&lt;/p&gt;
&lt;h2 id=&#34;the-version-endpoint&#34;&gt;The &amp;ldquo;Version&amp;rdquo; Endpoint&lt;/h2&gt;
&lt;p&gt;Much like the healthcheck endpoint, which answers the question &amp;ldquo;is my API
running?&amp;rdquo;, it is often very useful to know &amp;ldquo;what version of my API is running?&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;As with the healthcheck endpoint, this can be added programmatically to any
existing Plumber API:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;version&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;2.1.1&amp;#34;&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;srv&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;handle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;GET&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;/_version&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;req&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;setHeader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Content-Type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;200L&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;body&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;{&amp;#34;version&amp;#34;:&amp;#34;%s&amp;#34;}&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;version&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course, this requires you to version your API to begin with, but you should
be doing that anyway.&lt;/p&gt;
&lt;p&gt;I find myself checking these endpoints all the time to verify that an API has
deployed correctly, particularly for rolling deployments, which might take some
time to converge to the new version.&lt;/p&gt;
&lt;h2 id=&#34;the-sessioninfo-endpoint&#34;&gt;The &amp;ldquo;SessionInfo&amp;rdquo; Endpoint&lt;/h2&gt;
&lt;p&gt;The last group of questions I find myself asking about Plumber APIs are
variations on &amp;ldquo;what version of R (or a package) is it using?&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;R users often post the result of the &lt;code&gt;sessionInfo()&lt;/code&gt; command when filing bugs
for a package or posting on Stackoverflow, because it can help point to issues
that only show up or newer or older versions of R itself or any of the packages
in use. This information is similarly useful when debugging bad or inconsistent
behaviour with a Plumber API.&lt;/p&gt;
&lt;p&gt;Unfortunately, it can be hard to decipher R&amp;rsquo;s &lt;code&gt;sessionInfo()&lt;/code&gt; results when
directly serialised to JSON, because they contain deeply nested &lt;code&gt;DESCRIPTION&lt;/code&gt;
files for each loaded package.&lt;/p&gt;
&lt;p&gt;Instead, I recommend using the &lt;strong&gt;sessioninfo&lt;/strong&gt; package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;srv&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;handle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;GET&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;/_sessioninfo&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;req&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;setHeader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Content-Type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;200L&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;body&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;jsonlite&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;toJSON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;sessioninfo&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;session_info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auto_unbox&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;null&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;null&amp;#34;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;coda&#34;&gt;Coda&lt;/h2&gt;
&lt;p&gt;Implementing these three endpoints in all our internal APIs has helped diagnose
and solve countless problems. But I&amp;rsquo;ve glossed over how to actually implement
them in practice.&lt;/p&gt;
&lt;p&gt;The approach used by my team is to have a common &lt;code&gt;entrypoint.R&lt;/code&gt; script (recently
reimplemented as an &lt;a href=&#34;./writing-proprietary-r-packages.html&#34;&gt;internal package&lt;/a&gt;)
used across all our Plumber APIs. This ensures that even new projects will get
these endpoints automatically.&lt;/p&gt;
&lt;p&gt;Custom entrypoint support is an extremely useful &lt;a href=&#34;https://github.com/rstudio/plumber/issues/467&#34;&gt;but almost totally
undocumented&lt;/a&gt; feature of Plumber.
Hopefully more examples can be shared in the future to remedy this.&lt;/p&gt;
    </content>
    
    
    <category term="r"/>
    <category term="plumber"/>
    <category term="docker"/>
    <category term="kubernetes"/>
  </entry>
  <entry>
    <title type="html">A Bayesian Estimate of BackBlaze&#39;s Hard Drive Failure Rates</title>
    
    <link href="https://unconj.ca/blog/a-bayesian-estimate-of-hard-drive-failure-rates.html" rel="alternate"/>
    <published>2020-02-13T00:00:00Z</published>
    
    
    <updated>2020-02-13T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2020-02-13:blog/a-bayesian-estimate-of-hard-drive-failure-rates.html</id>
    
    <content type="html" xml:lang="en">
      &lt;center&gt;
&lt;img src=&#34;./images/r-2b1923f7/failure-plot-1.png&#34; alt=&#34;Bayesian Hard Drive Failure Rates&#34;&gt;
&lt;/center&gt;
&lt;p&gt;Each quarter the backup service BackBlaze publishes data on the failure rate of
its hundreds of thousands of hard drives, most recently on &lt;a href=&#34;https://www.backblaze.com/blog/hard-drive-stats-for-2019/&#34;&gt;February
11th&lt;/a&gt;. Since the
failure rate of different models can vary widely, these posts sometimes make a
splash in the tech community. They&amp;rsquo;re also notable as the only large public
dataset on drive failures:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.backblaze.com/blog/wp-content/uploads/2020/02/Blog_Lifetime_Drive_Stats_Chart.png&#34; alt=&#34;BackBlaze 2019 Annualized Hard Drive Failure Rates&#34;&gt;&lt;/p&gt;
&lt;p&gt;One of the things that strikes me about the presentation above is that BackBlaze
uses simple averages to compute the &amp;ldquo;Annualized Failure Rate&amp;rdquo; (AFR), despite the
fact that the actual count data vary by orders of magnitude, down to a single
digit. This might lead us to question the accuracy for smaller samples; in fact,
the authors are sensitive to this possibility and suppress data from drives with
less than 5,000 days of operation in Q4 2019 (although they are detailed in the
text of the article and available in their public datasets).&lt;/p&gt;
&lt;p&gt;This looks like a perfect use case for a Bayesian approach: we want to combine a
prior expectation of the failure rate (which might be close to the historical
average across all drives) with observed failure events to produce a more
accurate estimate for each model.&lt;/p&gt;
&lt;h2 id=&#34;re-estimating-failure-rates-using-empirical-bayes&#34;&gt;Re-estimating Failure Rates using Empirical Bayes&lt;/h2&gt;
&lt;p&gt;First, we can extract the data that is missing from the table but mentioned in
the text:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;omitted&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tibble&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;tribble&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
  &lt;span class=&#34;o&#34;&gt;~&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mfg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;~&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;~&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;~&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;days&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;~&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;failures&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;Seagate&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;ST16000NM001G&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;16TB&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1440&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;Toshiba&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;HDWF180&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;8TB&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;13994&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;HGST&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;HUH721010ALE600&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;10TB&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;8042&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;Toshiba&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;MG08ACA16TA&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;16TB&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; # A tibble: 4 x 5&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;   mfg     name            size   days failures&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;   &amp;lt;chr&amp;gt;   &amp;lt;chr&amp;gt;           &amp;lt;chr&amp;gt; &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 1 Seagate ST16000NM001G   16TB   1440        0&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 2 Toshiba HDWF180         8TB   13994        1&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 3 HGST    HUH721010ALE600 10TB   8042        0&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 4 Toshiba MG08ACA16TA     16TB    100        0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You&amp;rsquo;ll notice that there are zero failures for most of these drives, even though
it seems implausible that they will never fail. This approach will allow us to
fill in reasonable estimates.&lt;/p&gt;
&lt;p&gt;The remaining data come from the CSV download available in the original post,
cleaned up a little:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;fname&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;path/to/lifetime_chart_as_of_Q4_2019.csv&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dplyr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;warn.conflicts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;hdds&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;read.csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;fname&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;skip&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;row.names&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stringsAsFactors&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;nrows&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;14&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;tibble&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;as_tibble&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;mfg&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MFR&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Models&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Drive.Size&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;days&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Drive.Days&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;failures&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Drive.Failures&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;trimws&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;gsub&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fixed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;days&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;as.integer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;gsub&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;days&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fixed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;failures&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;as.integer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;gsub&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;failures&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fixed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;bind_rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;omitted&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Compute BackBlaze&amp;#39;s &amp;#34;Annualized Failure Rate&amp;#34;.&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;afr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;failures&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;days&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;365&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;arrange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;desc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;afr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;hdds&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; # A tibble: 18 x 6&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;    mfg     name            size      days failures     afr&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;    &amp;lt;chr&amp;gt;   &amp;lt;chr&amp;gt;           &amp;lt;chr&amp;gt;    &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;   &amp;lt;dbl&amp;gt;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  1 Seagate ST4000DM000     4TB   52597595     3843 0.0267 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  2 Toshiba HDWF180         8TB      13994        1 0.0261 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  3 Seagate ST12000NM0007   12TB  20853714     1466 0.0257 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  4 Seagate ST8000NM0055    8TB   13172942      439 0.0122 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  5 Seagate ST12000NM0008   12TB    321275       10 0.0114 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  6 Seagate ST8000DM002     8TB   11807158      351 0.0109 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  7 Seagate ST6000DX000     6TB    2902718       84 0.0106 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  8 Toshiba MG07ACA14TA     14TB    673365       16 0.00867&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  9 HGST    HUH728080ALE600 8TB     838384       18 0.00784&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 10 Toshiba MD04ABA400V     4TB     234748        5 0.00777&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 11 Seagate ST10000NM0086   10TB   1006626       19 0.00689&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 12 HGST    HUH721212ALE600 12TB    327080        5 0.00558&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 13 HGST    HMS5C4040ALE640 4TB   11674201      165 0.00516&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 14 HGST    HMS5C4040BLE640 4TB   19578610      245 0.00457&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 15 HGST    HUH721212ALN604 12TB   2919243       32 0.00400&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 16 Seagate ST16000NM001G   16TB      1440        0 0      &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 17 HGST    HUH721010ALE600 10TB      8042        0 0      &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 18 Toshiba MG08ACA16TA     16TB       100        0 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;David Robinson has &lt;a href=&#34;http://varianceexplained.org/r/empirical_bayes_baseball/&#34;&gt;a well-known blog
post&lt;/a&gt; on an analogous
problem in baseball where he takes an &lt;a href=&#34;https://en.wikipedia.org/wiki/Empirical_Bayes_method&#34;&gt;empirical Bayes
approach&lt;/a&gt; and estimates a
reasonable prior distribution from the original data &amp;ndash; which works here as
well. To get a more stable estimate of the distribution, we can omit AFRs
computed for drives with less than 1 million days of service:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;afr_sample&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hdds&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;afr[hdds&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;days&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1e6&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;]
&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;afr_beta&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MASS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;fitdistr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;afr_sample&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dbeta&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;start&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;shape1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;shape2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;lower&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.01&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;      shape1       shape2  &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;     2.379848   198.621649 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  (  1.052762) ( 97.652075)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Empirical beta prior parameters.&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;alpha0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;afr_beta&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;estimate[1]&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;beta0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;afr_beta&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;estimate[2]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This models the failure rate of each model as fixed but drawn from a shared beta
distribution (which is a natural distribution for probabilities), and individual
days as a &lt;a href=&#34;https://en.wikipedia.org/wiki/Beta-binomial_distribution&#34;&gt;Bernoulli
trial&lt;/a&gt; that can either
succeed or fail based on this underlying rate. This is a contestable model &amp;ndash;
for instance, you might think that workload or other environmental factors are
the true cause of failures &amp;ndash; but I believe it&amp;rsquo;s a reasonable approximation.&lt;/p&gt;
&lt;p&gt;With the parameters in hand we can then use Bayes rule to update the rates&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;,
combining the empirical prior with the observed data:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;hdds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;eb_afr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;failures&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alpha0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;days&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;365&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alpha0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;beta0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; # A tibble: 18 x 7&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;    mfg     name            size      days failures     afr  eb_afr&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;    &amp;lt;chr&amp;gt;   &amp;lt;chr&amp;gt;           &amp;lt;chr&amp;gt;    &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;   &amp;lt;dbl&amp;gt;   &amp;lt;dbl&amp;gt;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  1 Seagate ST4000DM000     4TB   52597595     3843 0.0267  0.0266 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  2 Toshiba HDWF180         8TB      13994        1 0.0261  0.0141 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  3 Seagate ST12000NM0007   12TB  20853714     1466 0.0257  0.0256 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  4 Seagate ST8000NM0055    8TB   13172942      439 0.0122  0.0122 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  5 Seagate ST12000NM0008   12TB    321275       10 0.0114  0.0115 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  6 Seagate ST8000DM002     8TB   11807158      351 0.0109  0.0109 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  7 Seagate ST6000DX000     6TB    2902718       84 0.0106  0.0106 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  8 Toshiba MG07ACA14TA     14TB    673365       16 0.00867 0.00898&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;  9 HGST    HUH728080ALE600 8TB     838384       18 0.00784 0.00816&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 10 Toshiba MD04ABA400V     4TB     234748        5 0.00777 0.00874&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 11 Seagate ST10000NM0086   10TB   1006626       19 0.00689 0.00723&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 12 HGST    HUH721212ALE600 12TB    327080        5 0.00558 0.00673&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 13 HGST    HMS5C4040ALE640 4TB   11674201      165 0.00516 0.00520&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 14 HGST    HMS5C4040BLE640 4TB   19578610      245 0.00457 0.00459&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 15 HGST    HUH721212ALN604 12TB   2919243       32 0.00400 0.00419&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 16 Seagate ST16000NM001G   16TB      1440        0 0       0.0116 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 17 HGST    HUH721010ALE600 10TB      8042        0 0       0.0107 &lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; 18 Toshiba MG08ACA16TA     16TB       100        0 0       0.0118&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you look carefully, you&amp;rsquo;ll see that drives with smaller samples are more
strongly influenced by the prior: all of the drives that were originally omitted
have failure rates close to the mean of the prior, and the model suggests that
some of the large HGST drives have had a run of good luck as well.&lt;/p&gt;
&lt;p&gt;Of course, a plot (see the top of the page) is more compelling than a table.&lt;/p&gt;
&lt;p&gt;There is some evidence in the table above that different manufacturers may have
slightly different base failure rates, and BackBlaze has in the past speculated
that different drive sizes may have different failure characteristics as well.
In this case, you could try to recover manufacturer- or drive size-specific
parameters by using a hierarchical model. This approach might bring the estimate
for the HGST 10TB drive down, for example, since the other HGST models all have
low failure rates.&lt;/p&gt;
&lt;p&gt;Finally, it&amp;rsquo;s worth mentioning that failure rates in and of themselves may not
be the right metric against which to make a purchasing decision &amp;ndash; the drives
vary in size and price, so a more useful measure might be an estimate of the
annual per-TB replacement cost for each model.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;This simple update formula for the beta-binomial &lt;a href=&#34;https://en.wikipedia.org/wiki/Conjugate_prior#Example&#34;&gt;is due to the highly
convenient fact&lt;/a&gt;
that the posterior distribution is &lt;em&gt;also&lt;/em&gt; beta-binomial, which is partly
why this distribution is so popular. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
    </content>
    
    
    <category term="r"/>
    <category term="stats"/>
  </entry>
  <entry>
    <title type="html">Browsing Twitch.tv From Emacs</title>
    
    <link href="https://unconj.ca/blog/browsing-twitch-tv-from-emacs.html" rel="alternate"/>
    <published>2020-01-11T00:00:00Z</published>
    
    
    <updated>2020-01-11T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2020-01-11:blog/browsing-twitch-tv-from-emacs.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;A video of my presentation from &lt;a href=&#34;https://emacsconf.org/2019/&#34;&gt;EmacsConf 2019&lt;/a&gt; is
now available. You can check out the recording below or see the slides
&lt;a href=&#34;https://mirror.csclub.uwaterloo.ca/emacsconf/2019/emacsconf-2019-11-browsing-twitch-from-emacs--helm-twitch--slides--ajacobs.html&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
&lt;div style=&#34;position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;&#34;&gt;
  &lt;iframe src=&#34;https://www.youtube.com/embed/Aw2RHXyhtgQ&#34; style=&#34;position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;&#34; allowfullscreen title=&#34;YouTube Video&#34;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;br&gt;&lt;/p&gt;
&lt;!-- &lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/Aw2RHXyhtgQ&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt; --&gt;
&lt;p&gt;Browser-based applications can sometimes punish even new machines. In 2015, due
to limited hardware, I was no longer able to use the popular video streaming
site Twitch.tv to follow eSports. I investigated some alternatives at the time,
but they lacked discovery and curation features, and so I decided to write a
full-fledged Twitch client in my favourite text editor, Emacs. Years later, I
still use this little bit of Emacs Lisp almost every day.&lt;/p&gt;
&lt;p&gt;The talk discusses how I was able to use the richness of the built-in Emacs
features and some community packages to build this client, as well as the
various bumps along the way.&lt;/p&gt;
&lt;p&gt;The code is available &lt;a href=&#34;&#34;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;
    </content>
    
    
    <category term="emacs"/>
    <category term="talks"/>
  </entry>
  <entry>
    <title type="html">Structured Errors in Plumber APIs</title>
    
    <link href="https://unconj.ca/blog/structured-errors-in-plumber-apis.html" rel="alternate"/>
    <published>2019-12-07T00:00:00Z</published>
    
    
    <updated>2019-12-07T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2019-12-07:blog/structured-errors-in-plumber-apis.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;If you&amp;rsquo;ve used the &lt;a href=&#34;https://www.rplumber.io/&#34;&gt;Plumber package&lt;/a&gt; to make R models
or other code accessible to others via an API, sooner or later you will need to
decide how to handle and report errors.&lt;/p&gt;
&lt;p&gt;By default, Plumber will catch R-level errors (like calls to &lt;code&gt;stop()&lt;/code&gt;) and
report them to users of your API as a JSON-encoded error message with HTTP
status code 500 &amp;ndash; also known as &lt;code&gt;Internal Server Error&lt;/code&gt;. This might look
something like the following from the command line:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;$ curl -v localhost:8000/
&amp;gt; GET /status HTTP/1.1
&amp;gt; Host: localhost:8000
&amp;gt; User-Agent: curl/7.64.0
&amp;gt; Accept: */*
&amp;gt; 
&amp;lt; HTTP/1.1 500 Internal Server Error
&amp;lt; Date: Sun, 24 Mar 2019 22:56:27 GMT
&amp;lt; Content-Type: application/json
&amp;lt; Date: Sun, 24 Mar 2019 10:56:27 PM GMT
&amp;lt; Connection: close
&amp;lt; Content-Length: 97
&amp;lt; 
* Closing connection 0
{&amp;quot;error&amp;quot;:[&amp;quot;500 - Internal server error&amp;quot;],&amp;quot;message&amp;quot;:[&amp;quot;Error: Missing required &#39;id&#39; parameter.\n&amp;quot;]}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There are two problems with this approach: first, it gives you almost zero
control over how errors are reported to real users, and second, it&amp;rsquo;s badly
behaved at the protocol level &amp;ndash; HTTP status codes provide for much more
granular and semantically meaningful error reporting.&lt;/p&gt;
&lt;p&gt;In my view, the key to overcoming these problems is treating errors as more than
simply a message and adding additional context when they are emitted. This is
sometimes called &lt;strong&gt;structured error handling&lt;/strong&gt;, and although it has not been
used much historically in R, &lt;a href=&#34;https://www.dropbox.com/s/fi5fswytwatw1kk/condition-erum.pdf&#34;&gt;this may be changing&lt;/a&gt;.
As you&amp;rsquo;ll see, we can take advantage of R&amp;rsquo;s powerful condition system to
implement rich error handling and reporting for Plumber APIs with relative ease.&lt;/p&gt;
&lt;p&gt;But first, it&amp;rsquo;s worth asking precisely what we want to get out of such an error
handling system &amp;ndash; that is, how can we distinguish errors we want our users to
see?&lt;/p&gt;
&lt;h2 id=&#34;operational-vs-programmer-errors&#34;&gt;Operational vs. Programmer Errors&lt;/h2&gt;
&lt;p&gt;Part of the issue here is that R (and Plumber) treat all errors as essentially
the same, when in practice this is not the case.&lt;/p&gt;
&lt;p&gt;The folks at Joyent &lt;a href=&#34;https://www.joyent.com/node-js/production/design/errors#operational-errors-vs-programmer-errors&#34;&gt;coined the terms&lt;/a&gt;
&lt;strong&gt;operational&lt;/strong&gt; and &lt;strong&gt;programmer errors&lt;/strong&gt; in the context of Javascript, and I
think this distinction is apt for R as well. To quote the article at length:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;People use the term &amp;ldquo;errors&amp;rdquo; to talk about both operational and programmer
errors, but they&amp;rsquo;re really quite different. Operational errors are error
conditions that all correct programs must deal with, and as long as they&amp;rsquo;re
dealt with, they don&amp;rsquo;t necessarily indicate a bug or even a serious problem.
&amp;ldquo;File not found&amp;rdquo; is an operational error, but it doesn&amp;rsquo;t necessarily mean
anything&amp;rsquo;s wrong. It might just mean the program has to create the file it&amp;rsquo;s
looking for first.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;By contrast, programmer errors are bugs. They&amp;rsquo;re cases where you made a
mistake, maybe by forgetting to validate user input, mistyping a variable
name, or something like that. By definition there&amp;rsquo;s no way to handle those. If
there were, you would have just used the error handling code in place of the
code that caused the error!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In the context of Plumber APIs, we want to notify users of operational errors,
because we require that they address these errors in order to use the API
correctly. Programmer errors, on the other hand, might generate bizarre or
misleading messages &amp;ndash; so it&amp;rsquo;s not clear we want users to see them at all. At
the same time, it is very important that &lt;em&gt;we&lt;/em&gt; see them so that we can start to
track down the underlying bugs that caused them.&lt;/p&gt;
&lt;p&gt;Operational and programmer errors also have a very natural expression in terms
of &lt;a href=&#34;https://en.wikipedia.org/wiki/List_of_HTTP_status_codes&#34;&gt;HTTP status codes&lt;/a&gt;;
for the most part, &lt;code&gt;4xx&lt;/code&gt; codes are for client (operational) errors, and &lt;code&gt;5xx&lt;/code&gt;
codes are for server (programmer) errors.&lt;/p&gt;
&lt;p&gt;By design, Plumber assumes that any error it encounters while running your code
is a programmer error. This is the right default, but it does mean that you need
to go out of your way to report operational errors instead. You can see this
clearly by attempting to use R-style errors in a Plumber API.&lt;/p&gt;
&lt;h2 id=&#34;r-style-error-handling-in-plumber&#34;&gt;R-Style Error Handling in Plumber&lt;/h2&gt;
&lt;p&gt;Suppose we have the following simple &lt;code&gt;plumber.R&lt;/code&gt; file, which allows users to
query the status of some familiar institutional patients:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;records&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;data.frame&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;George&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Sally&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Michael&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;admitted&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;2018-01-03&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;2018-04-14&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;2018-05-26&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;released&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;2018-11-27&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;2018-12-25&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;#* @param id:numeric* The patient&amp;#39;s ID number.&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#* @serializer unboxedJSON&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#* @get /status&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;as.integer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;record&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;records[records&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;is.na&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;released&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Released&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Admitted&amp;#34;&lt;/span&gt;

  &lt;span class=&#34;nf&#34;&gt;unclass&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can run this in the usual way with&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plumber&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;plumber&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;plumber.R&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;port&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;8000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;debug&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;swagger&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And normal queries should look like the following from the command line (with
&lt;code&gt;curl&lt;/code&gt; and &lt;code&gt;jq&lt;/code&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;$ curl -s localhost:8000/status?id=2 | jq
{
  &amp;quot;id&amp;quot;: 2,
  &amp;quot;name&amp;quot;: &amp;quot;Sally&amp;quot;,
  &amp;quot;admitted&amp;quot;: &amp;quot;2018-04-14&amp;quot;,
  &amp;quot;released&amp;quot;: &amp;quot;2018-12-25&amp;quot;,
  &amp;quot;status&amp;quot;: &amp;quot;Released&amp;quot;
}
$ curl -s localhost:8000/status?id=3 | jq
{
  &amp;quot;id&amp;quot;: 3,
  &amp;quot;name&amp;quot;: &amp;quot;Michael&amp;quot;,
  &amp;quot;admitted&amp;quot;: &amp;quot;2018-05-26&amp;quot;,
  &amp;quot;released&amp;quot;: null,
  &amp;quot;status&amp;quot;: &amp;quot;Admitted&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Of course, there are a number of ways the endpoint could fail, so let&amp;rsquo;s add some
R-style error handling:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;missing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;stop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Missing required &amp;#39;id&amp;#39; parameter.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;call.&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;suppressWarnings&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;as.integer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;is.na&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;stop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;The &amp;#39;id&amp;#39; parameter must be a positive integer.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;call.&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

  &lt;span class=&#34;n&#34;&gt;record&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;records[records&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;nrow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;stop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;No patient found with id: &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;call.&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;is.na&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;released&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Released&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Admitted&amp;#34;&lt;/span&gt;

  &lt;span class=&#34;nf&#34;&gt;unclass&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can then test some error conditions:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;$ curl localhost:8000/status | jq
{
  &amp;quot;error&amp;quot;: &amp;quot;500 - Internal server error&amp;quot;,
  &amp;quot;message&amp;quot;: &amp;quot;Error: Missing required &#39;id&#39; parameter.\n&amp;quot;
}
$ curl localhost:8000/status?id=cats | jq
{
  &amp;quot;error&amp;quot;: &amp;quot;500 - Internal server error&amp;quot;,
  &amp;quot;message&amp;quot;: &amp;quot;Error: The &#39;id&#39; parameter must be a positive integer.\n&amp;quot;
}
$ curl localhost:8000/status?id=4 | jq
{
  &amp;quot;error&amp;quot;: &amp;quot;500 - Internal server error&amp;quot;,
  &amp;quot;message&amp;quot;: &amp;quot;Error: No patient found with id: 4.\n&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You might notice that I passed &lt;code&gt;debug = TRUE&lt;/code&gt; to the &lt;code&gt;run()&lt;/code&gt; method above; this
is because Plumber will only show the &lt;code&gt;message&lt;/code&gt; field in the error responses in
&amp;ldquo;debug&amp;rdquo; mode. This is partly for privacy &amp;ndash; error messages could expose internal
state you&amp;rsquo;d prefer users not to see &amp;ndash; but it also in recognition of the point I
made above: random R error messages are rarely helpful to users.&lt;/p&gt;
&lt;p&gt;Plumber&amp;rsquo;s default error handler does a few useful things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Prints the error to the console, so we can see it on the server side. This is
absolutely essential for tracking down bugs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sets the status code to &lt;code&gt;500&lt;/code&gt;; and&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Adds the error message to the response (as the &lt;code&gt;message&lt;/code&gt; field you see above),
&lt;em&gt;but only when running in debug mode&lt;/em&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Unfortunately, this all means that we can&amp;rsquo;t use the default handler to send
operational error messages back to the user. Instead, we can circumvent it by
constructing error responses manually, or override it with smarter code.&lt;/p&gt;
&lt;h2 id=&#34;manual-error-reporting&#34;&gt;Manual Error Reporting&lt;/h2&gt;
&lt;p&gt;To generate useful operational errors for users, we need to do two things:
first, come up with a meaningful payload for errors; and second, ensure that
errors set an appropriate HTTP status code. Both of these can be accomplished by
manually modifying the response object that Plumber exposes as the magic
parameter &lt;code&gt;res&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are many, many different takes on how to report errors in JSON; I&amp;rsquo;m going
to use a pretty simple one here and include just a status code&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; and a
message. For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;#34;status&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;400&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Missing required parameter.&amp;#34;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Similarly, there is some debate on how to map errors like &amp;ldquo;invalid parameter&amp;rdquo; to
HTTP status codes, but here I&amp;rsquo;ll use &lt;code&gt;400&lt;/code&gt;. Both &lt;code&gt;422&lt;/code&gt; and &lt;code&gt;409&lt;/code&gt; are common
alternatives. For the case when a patient can&amp;rsquo;t be found, I also think it make
sense to use &lt;code&gt;404&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;missing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;400&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;body&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;jsonlite&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;toJSON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;auto_unbox&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
      &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;400&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
      &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Missing required &amp;#39;id&amp;#39; parameter.&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;suppressWarnings&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;as.integer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;is.na&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;400&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;body&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;jsonlite&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;toJSON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;auto_unbox&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
      &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;400&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
      &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;The &amp;#39;id&amp;#39; parameter must be a positive integer.&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

  &lt;span class=&#34;n&#34;&gt;record&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;records[records&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;nrow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;404&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;body&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;jsonlite&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;toJSON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;auto_unbox&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
      &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;404&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
      &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;No patient found with id: &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;is.na&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;released&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Released&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Admitted&amp;#34;&lt;/span&gt;

  &lt;span class=&#34;nf&#34;&gt;unclass&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This gives us much nicer, more meaningful errors we can safely pass down to
users of the API:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;$ curl -s localhost:8000/status | jq
{
  &amp;quot;status&amp;quot;: 400,
  &amp;quot;message&amp;quot;: &amp;quot;Missing required &#39;id&#39; parameter.&amp;quot;
}
$ curl -s localhost:8000/status?id=moose | jq
{
  &amp;quot;status&amp;quot;: 400,
  &amp;quot;message&amp;quot;: &amp;quot;The &#39;id&#39; parameter must be a positive integer.&amp;quot;
}
$ curl -s localhost:8000/status?id=4 | jq
{
  &amp;quot;status&amp;quot;: 404,
  &amp;quot;message&amp;quot;: &amp;quot;No patient found with id: 4.&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The code to manipulate &lt;code&gt;res&lt;/code&gt; objects for error handling ends up involving a lot
of copy &amp;amp; paste, especially for larger APIs where you want to report certain
classes of errors in a standard way. Ideally, we want to provide some helper
functions so that API authors do the right thing without needing to copy so much
code.&lt;/p&gt;
&lt;h2 id=&#34;emitting-errors-via-custom-conditions&#34;&gt;Emitting Errors via Custom Conditions&lt;/h2&gt;
&lt;p&gt;The underlying machinery that powers R&amp;rsquo;s &lt;code&gt;stop()&lt;/code&gt;, &lt;code&gt;warning()&lt;/code&gt;, and &lt;code&gt;message()&lt;/code&gt;
is the concept of a &lt;strong&gt;condition&lt;/strong&gt;. We can construct and &amp;ldquo;signal&amp;rdquo; error-like
conditions using a simple S3 object that inherits from the &lt;code&gt;&amp;quot;error&amp;quot;&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;api_error&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;err&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;structure&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;api_error&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;condition&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;signalCondition&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Works like stop():&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;api_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Bad request.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;400&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; Error: Bad request.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Moreover, since these are S3 objects, we can use the &lt;code&gt;class&lt;/code&gt; attribute to sort
out which errors are purposeful, operational errors that need to be reported to
the user, and those that are not:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;error_handler&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;req&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;inherits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;api_error&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;500&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;body&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;{\&amp;#34;status\&amp;#34;:500,\&amp;#34;message\&amp;#34;:\&amp;#34;Internal server error.\&amp;#34;}&amp;#34;&lt;/span&gt;
    
    &lt;span class=&#34;c1&#34;&gt;# Print the internal error so we can see it from the server side. A more&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# robust implementation would use proper logging.&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# We know that the message is intended to be user-facing.&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;body&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
      &lt;span class=&#34;s&#34;&gt;&amp;#34;{\&amp;#34;status\&amp;#34;:%d,\&amp;#34;message\&amp;#34;:\&amp;#34;%s\&amp;#34;}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Add this to the server with&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# server$setErrorHandler(error_handler)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;d also advise writing some helper methods, like the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;not_found&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Not found.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;api_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;404&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;missing_params&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Missing required parameters.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;api_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;400&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;invalid_params&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Invalid parameter value(s).&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;api_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;400&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These helper functions allow us to simplify and clarify the code so that it is
as concise and familiar looking as it was when we were using &lt;code&gt;stop()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;missing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;missing_params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Missing required &amp;#39;id&amp;#39; parameter.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;suppressWarnings&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;as.integer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;is.na&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;invalid_params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;The &amp;#39;id&amp;#39; parameter must be a positive integer.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

  &lt;span class=&#34;n&#34;&gt;record&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;records[records&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;nrow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;not_found&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;paste0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;No patient found with id: &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;is.na&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;released&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Released&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Admitted&amp;#34;&lt;/span&gt;

  &lt;span class=&#34;nf&#34;&gt;unclass&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;record&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using a custom error handler and the structured error support of S3 conditions,
we now have a way to emit operational errors with ease and a consistent JSON
error reporting format. This is an essential piece of providing a robust,
user-friendly Plumber API.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I like having the original status code as part of the error payload. That
way, even if I don&amp;rsquo;t have access to the full original request (e.g.
someone just copy &amp;amp; pasted the error message to me, or it&amp;rsquo;s not in the
logs, or a proxy along the way did not forward it appropriately), I still
have a good idea where to look. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
    </content>
    
    
    <category term="r"/>
    <category term="plumber"/>
  </entry>
  <entry>
    <title type="html">Writing Proprietary R Packages</title>
    
    <link href="https://unconj.ca/blog/writing-proprietary-r-packages.html" rel="alternate"/>
    <published>2019-11-26T00:00:00Z</published>
    
    
    <updated>2019-11-26T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2019-11-26:blog/writing-proprietary-r-packages.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;&lt;em&gt;Author&amp;rsquo;s note: this is a lightly modified version of the talk I gave at the GTA
R User&amp;rsquo;s Group in May of this year. You can find the original slides
&lt;a href=&#34;https://github.com/gta-r-user-group/gtar/tree/master/2019-06-04/proprietary-r-packages&#34;&gt;here&lt;/a&gt;.
Unfortunately, the talk was not recorded.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As I have &lt;a href=&#34;./copyright-in-closed-source-r-packages-the-right-way.html&#34;&gt;noted before&lt;/a&gt;,
most resources for R package authors are pitched at those writing open-source
packages &amp;mdash; usually hosted on &lt;a href=&#34;https://github.com&#34;&gt;GitHub&lt;/a&gt;, and with the goal
of ending up on &lt;a href=&#34;https://r-project.org&#34;&gt;CRAN&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These are valuable resources, and reflect the healthy free and open-source
(FOSS) R package ecosystem. But it is not the whole story. Many R users,
especially those working as data scientists in industry, can and should be
writing packages for internal use within their company or organisation.&lt;/p&gt;
&lt;p&gt;Yet there is comparatively little out there about how to actually put together
high-quality packages in these environments.&lt;/p&gt;
&lt;p&gt;This post is my attempt to address that gap.&lt;/p&gt;
&lt;p&gt;At &lt;a href=&#34;https://www.pinnacle.com&#34;&gt;work&lt;/a&gt; we have more than 50 internal R packages,
and I have been heavily involved in building up the culture and tooling we use
to make managing those packages possible over the last two years.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll focus on three major themes: code, tooling, and culture.&lt;/p&gt;
&lt;h2 id=&#34;why-should-you-write-r-packages-for-internal-use&#34;&gt;Why Should You Write R Packages for Internal Use?&lt;/h2&gt;
&lt;p&gt;At the outset, it is worth repeating that R packages are the best way to share R
code and keep it well-maintained and reliable. This matters even more inside an
organisation or when you are part of a team.&lt;/p&gt;
&lt;p&gt;The most salient reason why this is the case is that common tools to make your R
code robust, portable, and well-documented are &lt;a href=&#34;./why-there-is-no-importfrom-in-r.html&#34;&gt;only available&lt;/a&gt;
for use with packages: &lt;code&gt;R CMD check&lt;/code&gt;, &lt;code&gt;testthat&lt;/code&gt;, and &lt;code&gt;roxygen&lt;/code&gt; are all good
examples.&lt;/p&gt;
&lt;p&gt;I would push this further than most, and suggest you put as much R code as you
can get away with inside packages. For instance, we put all production models in
R packages, much of our ETL, and a good portion of our Shiny apps &amp;ndash; which has
recently become a lot easier due to the excellent &lt;a href=&#34;https://thinkr-open.github.io/golem/&#34;&gt;&lt;strong&gt;golem&lt;/strong&gt; package&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-code-what-can-internal-packages-contain&#34;&gt;The Code: What Can Internal Packages Contain?&lt;/h2&gt;
&lt;p&gt;It is a oft-repeated observation that when you find yourself copy/pasting the
same function or snippet of R code between projects, it might be time to push
that code into a package.&lt;/p&gt;
&lt;p&gt;Inside a business or organisation, functions that I&amp;rsquo;ve seen generally fall into
a small number of categories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Tools for making data easy to access and use correctly. For example, accessing
the right database with the right credentials.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Plot themes and other internal conventions ported to R, such as presentation
templates.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Business logic, which are conversions and routines that are highly specific to
your organisation or industry; and&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Encoding process in code &amp;ndash; e.g. automation of team or company-specific tasks.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As an illustration, all of the following are real functions from our internal
packages:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Accessing data.&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;pull_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;mongo_collection&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Plot themes and templates.&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;theme_pinnacle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;pinnacle_presentation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Business logic.&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;vig_cents_to_percent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;get_clp_est&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;..&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Encoding process.&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;send_to_slack&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;rnd_release&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There could be other good candidates. As I mentioned, we put models, Shiny
applications, and ETL into packages when possible, some of which turns into
reusable code.&lt;/p&gt;
&lt;h2 id=&#34;the-tooling-limitations-and-opportunities&#34;&gt;The Tooling: Limitations and Opportunities&lt;/h2&gt;
&lt;p&gt;Unlike the CRAN/FOSS world, in an organisation you&amp;rsquo;ll have limited power to
choose the tools your organisation (already) uses for collaboration and
development. And, unless you&amp;rsquo;ve got a compelling reason, you &lt;em&gt;should&lt;/em&gt; adopt your
organisation&amp;rsquo;s existing tools.&lt;/p&gt;
&lt;p&gt;For example, my organisation uses TeamCity for continuous integration, which
does not support R out of the box. In order to get access to shared CI
resources, we had to make this possible (which involved using Docker and some
custom scripts).&lt;/p&gt;
&lt;p&gt;The upside of this is that we could then hook into integrations used by the rest
of the organisation. For instance, Slack alerts for R packages that pass or fail
their CI tests:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;images/teamcity.png&#34; alt=&#34;TeamCity Build Message&#34;&gt;&lt;/p&gt;
&lt;p&gt;Because everyone is required to use the same tools, you can sometimes turn this
to your advantage and leverage a shared tool for opportunities you might not
otherwise have.&lt;/p&gt;
&lt;p&gt;For example, since everyone is required to be in the same Slack channel or read
their corporate email, you can ensure that everyone is notified of important R
package releases &amp;ndash; ie. this is our Slack bot that posts R package releases:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;images/pkgtools.png&#34; alt=&#34;Slack announcements&#34;&gt;&lt;/p&gt;
&lt;p&gt;This kind of broadcast is genuinely impossible for CRAN packages, because there
is simply no medium by which to contact all R users. FOSS communities are and
always will be more decentralised and heterogeneous.&lt;/p&gt;
&lt;p&gt;Moreover, tools can create data (e.g. releases, downloads, commit activity,
email messages, Slack messages) that can be analysed to help you measure and
understand bottlenecks or problems with your internal processes, since you know
they represent the whole picture. I&amp;rsquo;ve used these data to decide what would help
my team by more productive on several occasions.&lt;/p&gt;
&lt;h2 id=&#34;the-culture-authorship-vs-maintainership&#34;&gt;The Culture: Authorship vs. Maintainership&lt;/h2&gt;
&lt;p&gt;Ultimately, I think the biggest difference between FOSS and proprietary R
packages is a cultural one.&lt;/p&gt;
&lt;p&gt;Most CRAN packages are written by someone trying to scratch an itch. Maybe
that&amp;rsquo;s a new statistical method or data transformation, or a new approach to a
older ones; maybe it&amp;rsquo;s a new data format that you need access to from R; or
maybe it&amp;rsquo;s just a bundle of cool stuff you&amp;rsquo;ve done that you want to make more
widely accessible.&lt;/p&gt;
&lt;p&gt;There are some consequences of this model. Even if the package is released to
CRAN, the expectation is that the original author will (1) design the APIs; (2)
write the code; and (3) maintain the package. The author will make all the major
decisions about where the package goes and be the authority on why code works
the way it does.&lt;/p&gt;
&lt;p&gt;The author unconsciously acts as though they will maintain the code forever
(or more likely: until the package is abandoned).&lt;/p&gt;
&lt;p&gt;I call this an &lt;strong&gt;Authorship paradigm&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;These packages have a &lt;a href=&#34;https://en.wikipedia.org/wiki/Bus_factor&#34;&gt;bus factor&lt;/a&gt; of
exactly 1 &amp;ndash; that is, if the author gets hit by a bus, that&amp;rsquo;s probably the end
of the project. It is not an usual state of affairs for FOSS software, by any
means.&lt;/p&gt;
&lt;p&gt;Things are dramatically different for proprietary code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You likely inherited a codebase you did not design, and it is your &lt;strong&gt;job&lt;/strong&gt; to
maintain it, to understand it, and to be the person to ask about bugs and new
features.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You will not maintain new code you have designed/written forever. At some
point it will likely be someone else&amp;rsquo;s job.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I call this a &lt;strong&gt;Maintainership paradigm&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;What does this imply about writing R packages? Well, you should write the kind
of R code you&amp;rsquo;d like to maintain.&lt;/p&gt;
&lt;h2 id=&#34;what-kind-of-r-package-would-you-like-to-maintain&#34;&gt;What Kind of R Package Would You Like to Maintain?&lt;/h2&gt;
&lt;p&gt;This is not a trick question. You want to see&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Clear R source code with helpful comments.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Good documentation, with clear explanations and examples, and an overview of
the main package features in a &lt;code&gt;README&lt;/code&gt; file.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A test suite, both as additional examples and also to help prevent you from
introducing regressions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A documented history: an up-to-date &lt;code&gt;NEWS&lt;/code&gt; file and clear git commit history.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In other words, pretty much all of the usual advice. The difference is that you
are primarily motivated by collaboration with current and future coworkers.&lt;/p&gt;
&lt;p&gt;In sum, I think that there is quite a lot of overlap between &amp;ldquo;best practice&amp;rdquo;
package development in FOSS and proprietary environments. The main differences
arise from the motivations of package authors, the tools and ecosystems they
might operate in, and the nature of the code they might write.&lt;/p&gt;
    </content>
    
    
    <category term="r"/>
    <category term="r-packages"/>
    <category term="talks"/>
  </entry>
  <entry>
    <title type="html">An Autoconf Primer for R Package Authors</title>
    
    <link href="https://unconj.ca/blog/an-autoconf-primer-for-r-package-authors.html" rel="alternate"/>
    <published>2019-11-09T00:00:00Z</published>
    
    
    <updated>2019-11-09T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2019-11-09:blog/an-autoconf-primer-for-r-package-authors.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;Have you ever noticed something like the following when you&amp;rsquo;re installing an R
package?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking how to run the C preprocessor... gcc -E
checking for grep that handles long lines and -e... /usr/bin/grep
checking for egrep... /usr/bin/grep -E
checking for ANSI C header files... yes
...
configure: creating ./config.status
config.status: creating src/Makevars
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;on Windows, users install pre-built packages, but on all other platforms
(including macOS and Linux), they are built from source, including any native C,
C++, or Fortran code. Often it&amp;rsquo;s enough to use the default R settings to build
these packages, but sometimes you might need know a bit more about a user&amp;rsquo;s
system in order to get things working correctly.&lt;/p&gt;
&lt;p&gt;For this reason, R &lt;a href=&#34;https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Configure-and-cleanup&#34;&gt;permits packages&lt;/a&gt;
to have a &lt;code&gt;./configure&lt;/code&gt; shell script to make these checks before a package is
installed.&lt;/p&gt;
&lt;p&gt;Far and away the most common reason you&amp;rsquo;d need a &lt;code&gt;./configure&lt;/code&gt; script is to
check for the presence of a system library that your package needs. You can&amp;rsquo;t be
sure in advance what this library will be called &amp;ndash; it may have a different name
on Linux and macOS, for example &amp;ndash; or where it will be located on a user&amp;rsquo;s
machine, so you need at least a little bit of logic to try and track it down.&lt;/p&gt;
&lt;p&gt;Some package authors like to write &lt;code&gt;./configure&lt;/code&gt; scripts by hand (for example,
&lt;a href=&#34;https://github.com/Rdatatable/data.table/blob/master/configure&#34;&gt;&lt;strong&gt;data.table&lt;/strong&gt;&lt;/a&gt;
and &lt;a href=&#34;https://github.com/jeroen/protolite/blob/master/configure&#34;&gt;&lt;strong&gt;protolite&lt;/strong&gt;&lt;/a&gt;).
But many package authors instead opt to use &lt;a href=&#34;https://www.gnu.org/software/autoconf/&#34;&gt;Autoconf&lt;/a&gt;,
which is an arcane but highly useful language and tool for generating
&lt;code&gt;./configure&lt;/code&gt; scripts that will work on most systems. It also comes with a ton
of built-in functions for the kinds of checks you are likely to make.&lt;/p&gt;
&lt;p&gt;It is Autoconf that generates output like the snippet at the start of the post.&lt;/p&gt;
&lt;p&gt;Unfortunately, there are few resources out there on how to write Autoconf
scripts for R packages.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; Partly as a result, these scripts can be messy and
inconsistent in practice. This post aims to provide the boilerplate you need to
get started with some &amp;ldquo;best practices&amp;rdquo; in place.&lt;/p&gt;
&lt;h2 id=&#34;getting-started&#34;&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;To use Autoconf, you&amp;rsquo;ll generally need the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;configure.ac&lt;/code&gt; script.&lt;/li&gt;
&lt;li&gt;Template files, most often a &lt;code&gt;src/Makevars.in&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Various entries in your &lt;code&gt;.gitignore&lt;/code&gt; or &lt;code&gt;.Rbuildignore&lt;/code&gt;; and&lt;/li&gt;
&lt;li&gt;Optionally, a &lt;code&gt;./cleanup&lt;/code&gt; script to delete various intermediate files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First, create an &lt;code&gt;src/Makevars.in&lt;/code&gt; file with the following contents:&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PKG_CPPFLAGS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; -I. @PKG_CPPFLAGS@
&lt;span class=&#34;nv&#34;&gt;PKG_LIBS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; @PKG_LIBS@
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is a template file that Autoconf will fill in to produce a final &lt;code&gt;Makevars&lt;/code&gt;
file telling R how to compile your package correctly. As such, you should add
&lt;code&gt;src/Makevars.in&lt;/code&gt; to your &lt;code&gt;.Rbuildignore&lt;/code&gt; and &lt;code&gt;src/Makevars&lt;/code&gt; to your
&lt;code&gt;.gitignore&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Second, create a file called &lt;code&gt;configure.ac&lt;/code&gt; like the one below:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;AC_INIT&lt;span class=&#34;o&#34;&gt;([&lt;/span&gt;&amp;lt;package&amp;gt;&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;,&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&amp;lt;version&amp;gt;&lt;span class=&#34;o&#34;&gt;])&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Find the compiler and compiler flags used by R.&lt;/span&gt;
: &lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;R_HOME&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;R RHOME&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;test&lt;/span&gt; -z &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;R_HOME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
  &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;could not determine R_HOME&amp;#34;&lt;/span&gt;
  &lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;CC&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;R_HOME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/bin/R&amp;#34;&lt;/span&gt; CMD config CC&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;CFLAGS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;R_HOME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/bin/R&amp;#34;&lt;/span&gt; CMD config CFLAGS&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;CPPFLAGS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;R_HOME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/bin/R&amp;#34;&lt;/span&gt; CMD config CPPFLAGS&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Search for a system library, in this case the zlib compression library (which&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# contains the function &amp;#39;deflate&amp;#39;). This sets the variable &amp;#39;ac_cv_search_deflate&amp;#39;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# to what must be passed to ${PKG_LIBS}.&lt;/span&gt;
AC_SEARCH_LIBS&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;deflate, z, &lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt;, &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;AC_ERROR&lt;span class=&#34;o&#34;&gt;([&lt;/span&gt;The zlib library is required.&lt;span class=&#34;o&#34;&gt;])])&lt;/span&gt;
AC_CHECK_HEADERS&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;zlib.h, &lt;span class=&#34;o&#34;&gt;[]&lt;/span&gt;, &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;AC_ERROR&lt;span class=&#34;o&#34;&gt;([&lt;/span&gt;The zlib library headers are required.&lt;span class=&#34;o&#34;&gt;])])&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Write the flags into the src/Makevars file.&lt;/span&gt;
AC_SUBST&lt;span class=&#34;o&#34;&gt;([&lt;/span&gt;PKG_CPPFLAGS&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;, &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;PKG_CPPFLAGS&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;])&lt;/span&gt;
AC_SUBST&lt;span class=&#34;o&#34;&gt;([&lt;/span&gt;PKG_LIBS&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;, &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;LIBS&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;PKG_LIBS&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;ac_cv_search_deflate&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;])&lt;/span&gt;
AC_CONFIG_FILES&lt;span class=&#34;o&#34;&gt;([&lt;/span&gt;src/Makevars&lt;span class=&#34;o&#34;&gt;])&lt;/span&gt;
AC_OUTPUT

&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;  --------------------------------------------------
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;  Configuration for &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;PACKAGE_NAME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;PACKAGE_VERSION&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;    cppflags: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;CPPFLAGS&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;PKG_CPPFLAGS&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;    libs:     &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;PKG_LIBS&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;  --------------------------------------------------
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I was not kidding about the &amp;ldquo;arcane&amp;rdquo; bit. But you can now run the command
&lt;code&gt;autoconf&lt;/code&gt; (or, better yet &lt;code&gt;autoreconf&lt;/code&gt;) in your package directory to generate
a &lt;code&gt;configure&lt;/code&gt; script that R can understand.&lt;/p&gt;
&lt;p&gt;Now, the contents of this generated script are scary and near-unreadable, but
that doesn&amp;rsquo;t really matter, since you will never edit the file by hand anyway.
It is good practice to check both the &lt;code&gt;configure.ac&lt;/code&gt; and &lt;code&gt;configure&lt;/code&gt; files into
version control, and in fact &lt;code&gt;R CMD check&lt;/code&gt; will even warn you if you forget.&lt;/p&gt;
&lt;p&gt;Finally, you might also notice that &lt;code&gt;autoreconf&lt;/code&gt; produces a bunch of
intermediate files that you will want to add you your &lt;code&gt;.gitignore&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;autom4te.cache
config.log
config.status
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This should give you a functional Autoconf setup that will check for the &lt;code&gt;zlib&lt;/code&gt;
library on the user&amp;rsquo;s system and link it to your compiled code.&lt;/p&gt;
&lt;h2 id=&#34;more-common-patterns&#34;&gt;More Common Patterns&lt;/h2&gt;
&lt;h3 id=&#34;1-using-c-instead-of-c&#34;&gt;1. Using C++ Instead of C&lt;/h3&gt;
&lt;p&gt;For a project using C++ code instead of C &amp;ndash; for example, if you are using Rcpp
&amp;ndash; you can make the following small adjustment. Replace&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CC&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;R_HOME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/bin/R&amp;#34;&lt;/span&gt; CMD config CC&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;CFLAGS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;R_HOME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/bin/R&amp;#34;&lt;/span&gt; CMD config CFLAGS&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;CPPFLAGS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;R_HOME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/bin/R&amp;#34;&lt;/span&gt; CMD config CPPFLAGS&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;in the example above with&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CXX&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;R_HOME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/bin/R&amp;#34;&lt;/span&gt; CMD config CXX&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;CXXFLAGS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;R_HOME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/bin/R&amp;#34;&lt;/span&gt; CMD config CXXFLAGS&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;CPPFLAGS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;R_HOME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/bin/R&amp;#34;&lt;/span&gt; CMD config CPPFLAGS&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;
AC_LANG&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;C++&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
AC_PROG_CPP
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Autoconf will then run automated checks for C++ features (instead of C). Note
that it is important to set &lt;code&gt;CXX&lt;/code&gt;, &lt;code&gt;CXXFLAGS&lt;/code&gt; and &lt;code&gt;CPPFLAGS&lt;/code&gt; &lt;strong&gt;before&lt;/strong&gt; you make
these checks, to ensure that Autoconf will check these features using the C++
toolchain that R will actually use to compile your package.&lt;/p&gt;
&lt;h3 id=&#34;2-finding-libraries-using-pkg-config&#34;&gt;2. Finding Libraries Using &lt;code&gt;pkg-config&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Most Linux distributions&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; come with a program called &lt;a href=&#34;https://www.freedesktop.org/wiki/Software/pkg-config/&#34;&gt;&lt;code&gt;pkg-config&lt;/code&gt;&lt;/a&gt;
that allows you to query installed libraries and the compiler flags used to
build them.&lt;/p&gt;
&lt;p&gt;I would suggest using &lt;code&gt;pkg-config&lt;/code&gt; by default, falling back on
&lt;code&gt;AC_CHECK_HEADERS&lt;/code&gt; otherwise. Autoconf actually comes with a
&lt;code&gt;PKG_PROG_PKG_CONFIG&lt;/code&gt; macro that will set &lt;code&gt;$PKG_CONFIG&lt;/code&gt; if it is available, so
you can set up these checks fairly easily:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;nv&#34;&gt;have_zlib&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;no
&lt;span class=&#34;nv&#34;&gt;ZLIB_CXXFLAGS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nv&#34;&gt;ZLIB_LIBS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;-lz&amp;#34;&lt;/span&gt;

PKG_PROG_PKG_CONFIG

&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;test&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$PKG_CONFIG&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
  AC_MSG_CHECKING&lt;span class=&#34;o&#34;&gt;([&lt;/span&gt;pkg-config &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; zlib&lt;span class=&#34;o&#34;&gt;])&lt;/span&gt;
  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$PKG_CONFIG&lt;/span&gt; --exists zlib&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
    &lt;span class=&#34;nv&#34;&gt;have_zlib&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;yes
    &lt;span class=&#34;nv&#34;&gt;ZLIB_CXXFLAGS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;PKG_CONFIG&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; --cflags zlib&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;
    &lt;span class=&#34;nv&#34;&gt;ZLIB_LIBS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;PKG_CONFIG&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; --libs zlib&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;
  &lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
  AC_MSG_RESULT&lt;span class=&#34;o&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;have_zlib&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;])&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;test&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;x&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;have_zlib&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; xno&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
  AC_CHECK_HEADERS&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;zlib.h, &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;have_zlib&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;yes&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;, &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;AC_ERROR&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;The zlib library headers are required.&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;
  &lt;span class=&#34;o&#34;&gt;)])&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;

AC_SUBST&lt;span class=&#34;o&#34;&gt;([&lt;/span&gt;PKG_LIBS&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;, &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;LIBS&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;PKG_LIBS&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;ZLIB_LIBS&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;3-showing-users-what-they-need-to-install&#34;&gt;3. Showing Users What They Need to Install&lt;/h3&gt;
&lt;p&gt;The examples above will print&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The zlib library headers are required.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;in case of failure. This isn&amp;rsquo;t a terribly helpful message for users, so an
emerging best practice for R packages is to provide more actionable messages
explaining what users need to install on various systems to get things working.&lt;/p&gt;
&lt;p&gt;For example, you could remove the &lt;code&gt;AC_ERROR&lt;/code&gt; message above add the following
block below it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;test&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;x&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;have_zlib&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; xno&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
  AC_MSG_FAILURE&lt;span class=&#34;o&#34;&gt;([&lt;/span&gt;
  ---------------------------------------------
   &lt;span class=&#34;s1&#34;&gt;&amp;#39;zlib&amp;#39;&lt;/span&gt; and its header files are required.

   Please install:

   * zlib1g-dev &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;on Debian and Ubuntu&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
   * zlib-devel &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;on Fedora, CentOS and RHEL&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
   * zlib &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;via Homebrew on macOS&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
   * libz1 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;on Solaris&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;

   and try again.

   If you believe this library is installed on your system but
   this script is simply unable to find it, you can specify the
   include and lib paths manually:

   R CMD INSTALL &lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;PACKAGE_NAME&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;
     --configure-vars&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;LIBS=-L/path/to/libs CPPFLAGS=-I/path/to/headers&amp;#39;&lt;/span&gt;
  ---------------------------------------------&lt;span class=&#34;o&#34;&gt;])&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A few quick searches should turn up the various package names on each platform.
The ones in the example above are the main platforms that CRAN checks against,
although instructions for Solaris are seldom worth the bother.&lt;/p&gt;
&lt;h3 id=&#34;4-using-a-cleanup-script&#34;&gt;4. Using a Cleanup Script&lt;/h3&gt;
&lt;p&gt;R permits packages to have a &lt;code&gt;./cleanup&lt;/code&gt; script. From &lt;em&gt;Writing R Extensions&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Under a Unix-alike only, an executable (Bourne shell) script cleanup is
executed as the last thing by R CMD INSTALL if option &amp;ndash;clean was given, and
by R CMD build when preparing the package for building from its source.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This can be a useful way to automatically clean up generated Autoconf files.
Here is one to get you started:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/sh
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
rm -f config.*
rm -f src/Makevars
rm -rf autom4te.cache
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;5-windows-support&#34;&gt;5. Windows Support&lt;/h3&gt;
&lt;p&gt;Windows users generally install binary packages, and will not run the
&lt;code&gt;./configure&lt;/code&gt; script during installation. However, you might want to help out
the CRAN maintainers who create these binary packages by creating a static,
Windows-oriented &lt;code&gt;src/Makevars.win&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PKG_CPPFLAGS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; -I. -lz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will obviously break when it cannot find &lt;code&gt;zlib&lt;/code&gt;, but we&amp;rsquo;re punting that
responsibility to the binary package maintainers in this case.&lt;/p&gt;
&lt;h2 id=&#34;further-reading&#34;&gt;Further Reading&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;d like to dig deeper, the following popular R packages all have Autoconf
scripts that I have looked to for inspiration in the past:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/ropensci/git2r/blob/master/configure.ac&#34;&gt;&lt;strong&gt;git2r&lt;/strong&gt;&lt;/a&gt;
package checks for &lt;code&gt;libgit2&lt;/code&gt;, and if none is found, falls back on a bundled
version of that library instead.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/eddelbuettel/rprotobuf/blob/master/configure.ac&#34;&gt;&lt;strong&gt;RProtoBuf&lt;/strong&gt;&lt;/a&gt;
package checks not only for the Protobuf library, but also the &lt;code&gt;protoc&lt;/code&gt;
compiler needed to generate some of the package&amp;rsquo;s C++ headers.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/s-u/rJava/blob/master/configure.ac&#34;&gt;&lt;strong&gt;rJava&lt;/strong&gt;&lt;/a&gt;
package allows for discovering (and further customising, via user-supplied
flags) many features of the R &amp;lt;-&amp;gt; Java bridge.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/r-spatial/sf/blob/master/configure.ac&#34;&gt;&lt;strong&gt;sf&lt;/strong&gt;&lt;/a&gt;
package checks for some complex and demanding system dependencies.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;a href=&#34;https://github.com/s-u/uuid/blob/master/configure.ac&#34;&gt;&lt;strong&gt;uuid&lt;/strong&gt;&lt;/a&gt; package
checks for some system libraries, but also checks if the socket address
structure on that platform contains a particular field.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And, for resources on Autoconf more broadly, check out &lt;a href=&#34;https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/index.html&#34;&gt;the official
documentation&lt;/a&gt;
and &lt;a href=&#34;https://autotools.io/autoconf/index.html&#34;&gt;Autotools Mythbuster&lt;/a&gt;, which has
a more example-driven approach.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I &lt;a href=&#34;https://github.com/r-lib/usethis/issues/313&#34;&gt;once tried&lt;/a&gt; to get a
&lt;code&gt;use_autoconf()&lt;/code&gt; function incorporated into the &lt;strong&gt;usethis&lt;/strong&gt; package, but
Hadley Wickham thought that too few users would benefit for it to be worth
maintaining. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;If you have an existing &lt;code&gt;src/Makevars&lt;/code&gt;, it should be fairly clear how to
move it to &lt;code&gt;src/Makevars.in&lt;/code&gt; and add the right templating syntax. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;&lt;code&gt;pkg-config&lt;/code&gt; is also available for macOS, although it is not installed by
default. Other Unix-based systems (such as Solaris and the BSDs) usually
have &lt;code&gt;pkg-config&lt;/code&gt; as well. &lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
    </content>
    
    
    <category term="r"/>
    <category term="r-packages"/>
  </entry>
  <entry>
    <title type="html">For and Against data.table</title>
    
    <link href="https://unconj.ca/blog/for-and-against-data-table.html" rel="alternate"/>
    <published>2019-06-27T00:00:00Z</published>
    
    
    <updated>2019-06-27T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2019-06-27:blog/for-and-against-data-table.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;I was reminded by Megan Stodel&amp;rsquo;s recent post &amp;ndash; &amp;ldquo;&lt;a href=&#34;https://www.meganstodel.com/posts/data-table/&#34;&gt;Three reasons why I use
data.table&lt;/a&gt;&amp;rdquo; &amp;ndash; of the enduring
&lt;strong&gt;data.table&lt;/strong&gt; vs. &lt;strong&gt;dplyr&lt;/strong&gt; argument.&lt;/p&gt;
&lt;p&gt;To Stodel&amp;rsquo;s points in favour of &lt;strong&gt;data.table&lt;/strong&gt;, which I would summarise as (1)
performance, (2) good design, and (3) that it makes you feel a bit iconoclastic
in these tidyverse times, I would add the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A very stable, actively-maintained, and battle-tested codebase. This is also
true of both &lt;strong&gt;dplyr&lt;/strong&gt; and base R, of course, but it is valuable nonetheless.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;http://www.tinyverse.org/&#34;&gt;Zero third-party dependencies&lt;/a&gt;. In contrast,
&lt;strong&gt;dplyr&lt;/strong&gt; has, at the time of writing, 22 direct or indirect package
dependencies. In combination with the choice of C over Rcpp, this leads to
very fast compilation and installation times.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Both of these are highly valued in production environments, which happens to be
the focus of my current work.&lt;/p&gt;
&lt;p&gt;However, I would usually advocate &lt;em&gt;against&lt;/em&gt; using &lt;strong&gt;data.table&lt;/strong&gt; unless you
really, really do need its performance benefits.&lt;/p&gt;
&lt;p&gt;Much of the &lt;code&gt;tibble&lt;/code&gt;/&lt;code&gt;data.table&lt;/code&gt; debate seems to be over peoples&#39; preferred
syntax,&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; or the degree to which base R, &lt;strong&gt;data.table&lt;/strong&gt;, or the tidyverse
produces more understandable code &amp;ndash; and, relatedly, &lt;a href=&#34;http://varianceexplained.org/r/teach-tidyverse/&#34;&gt;whether it is easier to
teach to newcomers&lt;/a&gt;. All of
these are valuable discussions.&lt;/p&gt;
&lt;p&gt;However, I&amp;rsquo;d like to articulate another reason why I&amp;rsquo;m always cautious about
adopting &lt;strong&gt;data.table&lt;/strong&gt;: modify-by-reference can lead to surprising and
non-idiomatic R code.&lt;/p&gt;
&lt;p&gt;Every &lt;strong&gt;data.table&lt;/strong&gt; user probably knows that the reason the package is fast is
that it discards R&amp;rsquo;s usual copy-on-modify behaviour, instead modifying objects
&amp;ldquo;by reference&amp;rdquo;.&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; It is worth explaining in some detail what this means.&lt;/p&gt;
&lt;h2 id=&#34;copy-on-modify-vs-modify-by-reference&#34;&gt;Copy-on-Modify vs. Modify-by-Reference&lt;/h2&gt;
&lt;p&gt;R users are accustomed to the fact that objects will not change unless you
reassign to them with the &lt;code&gt;&amp;lt;-&lt;/code&gt; operator. And so we can look at code like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;data.frame&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;rnorm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;runif&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;custom_summary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;create_features&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and expect that the call to &lt;code&gt;custom_summary()&lt;/code&gt; will not modify &lt;code&gt;df&lt;/code&gt;, while the
call to &lt;code&gt;create_features()&lt;/code&gt; clearly does. We would know this without needing to
look at the source code for these functions, even if they were given unhelpful
names like &lt;code&gt;fn1()&lt;/code&gt; and &lt;code&gt;fn2()&lt;/code&gt;. Now suppose that &lt;code&gt;custom_summary()&lt;/code&gt; looked like
the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;custom_summary&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;summary_measure&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;floor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ifelse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-1e-4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-1e-4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ifelse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1e-4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1e-4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;summary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That is, the function cleans up the data a little before presenting a summary.
Even though the function is modifying &lt;code&gt;df&lt;/code&gt; internally, we know that these
changes will not &amp;ldquo;leak&amp;rdquo; out of the scope of the function. This is what is meant
by copy-on-modify: R will copy objects as necessary to prevent modifications
from manifesting in the original.&lt;/p&gt;
&lt;p&gt;Now suppose that for performance reasons we decide to translate this code to use
&lt;code&gt;data.table&lt;/code&gt; objects. The result might look like the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;data.table&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;rnorm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;runif&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;custom_summary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;df[&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;floor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;df[&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;feature1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y]&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;df[&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;feature2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Even though there are no further uses of &lt;code&gt;&amp;lt;-&lt;/code&gt;, these last lines all modify &lt;code&gt;df&lt;/code&gt;
in-place. This is what is meant by &amp;ldquo;modify-by-reference&amp;rdquo;. We could also move
these into a new &lt;code&gt;create_features()&lt;/code&gt; function, and this function would not need
to use &lt;code&gt;&amp;lt;-&lt;/code&gt; to modify the original &lt;code&gt;data.table&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;A naive refactor could be carried out for the summary function, as well:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;custom_summary&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;df[&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;summary_measure&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;floor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;df[x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-1e-4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-1e-4&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;df[x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1e-4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1e-4&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;summary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This new version introduces an subtle bug: if the call to &lt;code&gt;custom_summary()&lt;/code&gt; is
later removed or commented out, &lt;code&gt;df$x&lt;/code&gt; may have larger or smaller entries than
expected (since they are no longer capped). This is a direct consequence of
modify-by-reference, and could never happen with native &lt;code&gt;data.frame&lt;/code&gt; or &lt;code&gt;tibble&lt;/code&gt;
objects.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s true that this is a contrived example, but I think it&amp;rsquo;s a useful
illustration nonetheless. Experienced &lt;code&gt;data.table&lt;/code&gt; users might argue that
functions should &amp;ldquo;clean up&amp;rdquo; after themselves if they make use of
modify-by-reference features, or perhaps that sometimes-surprising side effects
are merely the cost of using the package to begin with. The authors of
&lt;strong&gt;data.table&lt;/strong&gt; present an analogous scenario in &lt;a href=&#34;https://cran.r-project.org/web/packages/data.table/vignettes/datatable-reference-semantics.html#https://cran.r-project.org/web/packages/data.table/vignettes/datatable-reference-semantics.html#and-copy&#34;&gt;one of the vignettes&lt;/a&gt;;
they suggest that the function call &lt;code&gt;copy()&lt;/code&gt; before modifying the input.
Yet this is likely to erase the performance benefits of using &lt;code&gt;data.table&lt;/code&gt;
objects in the first place.&lt;/p&gt;
&lt;h2 id=&#34;reference-semantics-are-not-idiomatic-in-user-code&#34;&gt;Reference Semantics are Not Idiomatic in User Code&lt;/h2&gt;
&lt;p&gt;As Bob Rudis &lt;a href=&#34;https://rud.is/b/2017/05/23/r%E2%81%B6-idiomatic-for-the-people/&#34;&gt;remarks&lt;/a&gt;,
what constitutes &amp;ldquo;idiomatic&amp;rdquo; R can vary, but in practice there are very few
aspects of base R that have &amp;ldquo;reference semantics&amp;rdquo; &amp;ndash; i.e. that break
copy-on-modify rules in favour of modify-by-reference.&lt;/p&gt;
&lt;p&gt;An important set of exceptions to this general rule are the functions that load
packages, print to the console, or plot. All of these modify in place (e.g.
without using &lt;code&gt;&amp;lt;-&lt;/code&gt;) important objects: the search path, the console, and the
graphics device. What these exceptions have in common is precisely that they
manipulate well-known global objects that are baked into R itself.&lt;/p&gt;
&lt;p&gt;In contrast, user-created objects &amp;ndash; the usual vectors, data frames, and
functions &amp;ndash; almost never have reference semantics. This is not to say that you
are categorically unable to use them. There are even explicit language features
with reference semantics, namely environments, reference classes, and external
pointers &amp;ndash; or even when writing functions that use the &lt;code&gt;&amp;lt;&amp;lt;-&lt;/code&gt; operator. Yet it
is exceedingly rare to see these in the usual data analysis code; they are
mostly used by packages to implement design patterns that would otherwise be
very difficult in a copy-on-modify world.&lt;/p&gt;
&lt;p&gt;You can see echos of this in Hadley Wickham&amp;rsquo;s warning to users about R6 classes
(which have reference semantics) in the new edition of &lt;a href=&#34;https://adv-r.hadley.nz/oo-tradeoffs.html&#34;&gt;&lt;em&gt;Advanced R&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[I]f you use R6 it’s very easy to create a non-idiomatic API that will feel
very odd to native R users, and will have surprising pain points because of
the reference semantics.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It&amp;rsquo;s my guess that concern about these pain points is the primary reason why
&lt;strong&gt;dplyr&lt;/strong&gt; never adopted the modify-by-reference approach, even though it has
obviously been shown by &lt;strong&gt;data.table&lt;/strong&gt; to be more performant.&lt;/p&gt;
&lt;h2 id=&#34;does-this-mean-you-should-use-dplyr&#34;&gt;Does This Mean You Should Use dplyr?&lt;/h2&gt;
&lt;p&gt;To be clear, &lt;strong&gt;data.table&lt;/strong&gt; has its place. All of the arguments in favour of
using it I mentioned at the outset remain in good standing. And reference
semantics are not the &lt;a href=&#34;https://cran.r-project.org/web/packages/data.table/vignettes/datatable-keys-fast-subset.html&#34;&gt;only reason&lt;/a&gt;
for the performance of &lt;code&gt;data.table&lt;/code&gt; operations.&lt;/p&gt;
&lt;p&gt;Nor does this mean that I would wholeheartedly recommend using &lt;strong&gt;dplyr&lt;/strong&gt; and
friends at every opportunity. Most data wrangling can be done in base R,&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; and
I often argue that this is the right choice, for instance, inside packages.&lt;/p&gt;
&lt;p&gt;If anything, what I would suggest is that if you are going to use
&lt;strong&gt;data.table&lt;/strong&gt;, try to ensure that you write an API that exposes as little as
possible of its reference semantics. Avoid creating situations that will
surprise users expecting &lt;code&gt;&amp;lt;-&lt;/code&gt; as the signal for modification.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Atrebas has produced an excellent &lt;a href=&#34;https://atrebas.github.io/post/2019-03-03-datatable-dplyr/&#34;&gt;side-by-side comparison&lt;/a&gt;
of some common analysis patterns with &lt;strong&gt;data.table&lt;/strong&gt; and &lt;strong&gt;dplyr&lt;/strong&gt;. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I&amp;rsquo;m a bit critical of this language because all R objects are, at the C
level, pointers/references. Copy-on-modify is actually a contract adhered
to by the parts of R written in C; it is not enforced by the language and
can be broken. This is how it was possible to actually implement
&lt;strong&gt;data.table&lt;/strong&gt; in the first place.&lt;/p&gt;
&lt;p&gt;Better terms are &amp;ldquo;reference semantics&amp;rdquo; or &amp;ldquo;modify-by-reference&amp;rdquo;, because
they separate behaviour from implementation. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;For instance, Jozef Hajnala has a &lt;a href=&#34;https://jozef.io/categories/rcase4base/&#34;&gt;neat collection&lt;/a&gt;
of articles demonstrating how common &lt;strong&gt;dplyr&lt;/strong&gt; and &lt;strong&gt;data.table&lt;/strong&gt; patterns
can be implemented in base R. &lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
    </content>
    
    
    <category term="r"/>
  </entry>
  <entry>
    <title type="html">Copyright in Closed-Source R Packages: The Right Way</title>
    
    <link href="https://unconj.ca/blog/copyright-in-closed-source-r-packages-the-right-way.html" rel="alternate"/>
    <published>2019-03-18T00:00:00Z</published>
    
    
    <updated>2019-03-18T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2019-03-18:blog/copyright-in-closed-source-r-packages-the-right-way.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;There are a wealth of excellent resources for R users on creating and
maintaining R packages, which remain the best way to share your code within your
organisation or the larger community. However, almost all of these resources
tend to focus on open-source packages, tools, and workflows. As a result of
this, they tend to skim over more corporate issues like copyright assignment.&lt;/p&gt;
&lt;p&gt;Yet many R users are working on their code in proprietary environments, creating
packages for internal use by their company. That code is closed source, with the
copyright belonging to their organisation. If you fall into this category, how
should you communicate that in your R package? This post is intended to provide
a very clear answer to that question.&lt;/p&gt;
&lt;p&gt;It turns out that R has excellent support for embedding copyright information in
the metadata of the package itself. This makes it easy to precisely communicate
both open- and closed-source ownership in a few well-defined places: your
&lt;code&gt;DESCRIPTION&lt;/code&gt; and &lt;code&gt;LICENSE&lt;/code&gt; files.&lt;/p&gt;
&lt;h2 id=&#34;the-description-file&#34;&gt;The DESCRIPTION File&lt;/h2&gt;
&lt;p&gt;It is very likely that if you are writing R packages for your employer, they are
the ultimate copyright owner of the software. Fortunately it&amp;rsquo;s very easy to lay
out this fact in your &lt;code&gt;DESCRIPTION&lt;/code&gt; file &amp;ndash; there is a special copyright holder
role (&lt;code&gt;cph&lt;/code&gt;) that can be used in the &lt;code&gt;Authors&lt;/code&gt; fields. For example, suppose that
I worked for Widgets Incorporated. In that case, my &lt;code&gt;DESCRIPTION&lt;/code&gt; file would
contain something like the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;Authors@R: c(
  person(&amp;#34;Aaron&amp;#34;, &amp;#34;Jacobs&amp;#34;, role = c(&amp;#34;cre&amp;#34;, &amp;#34;aut&amp;#34;)),
  person(&amp;#34;Widgets Incorporated&amp;#34;, role = &amp;#34;cph&amp;#34;)
  )
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is not quite the end of the story, because R &lt;a href=&#34;https://cran.r-project.org/doc/manuals/R-exts.html#The-DESCRIPTION-file&#34;&gt;also requires&lt;/a&gt;
that you to lay out what open-source license your code is available under in the
&lt;code&gt;License&lt;/code&gt; field, or use the special value &lt;code&gt;file LICENSE&lt;/code&gt; to point users to a
file explaining it. Since your code is not open-source, your &lt;code&gt;DESCRIPTION&lt;/code&gt; file
&lt;em&gt;must&lt;/em&gt; take this route and contain the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;License: file LICENSE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But this just punts on the issue &amp;ndash; what do you put in that &lt;code&gt;LICENSE&lt;/code&gt; file?&lt;/p&gt;
&lt;h2 id=&#34;the-license-file&#34;&gt;The LICENSE File&lt;/h2&gt;
&lt;p&gt;Hadley Wickham&amp;rsquo;s highly influential &lt;em&gt;R Packages&lt;/em&gt; book makes &lt;a href=&#34;http://r-pkgs.had.co.nz/description.html#license&#34;&gt;the following suggestion&lt;/a&gt;
for the contents of a proprietary &lt;code&gt;LICENSE&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;Proprietary 

Do not distribute outside of Widgets Incorporated.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In my view, this is a mistake. Why? Because this file says &lt;strong&gt;absolutely
nothing&lt;/strong&gt; about copyright. It bears no resemblance to a valid software license;
notably, it does not detail any of the rights or permissions granted to those in
possession of the source code.&lt;/p&gt;
&lt;p&gt;But wait, you say, my company doesn&amp;rsquo;t want to grant &lt;em&gt;any&lt;/em&gt; rights or permissions!
If this is the case &amp;ndash; and likely it is &amp;ndash; your &lt;code&gt;LICENSE&lt;/code&gt; file should contain a
familiar legal phrase: &amp;ldquo;All rights reserved&amp;rdquo;. In full:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;Copyright 2019 Widgets Incorporated. All rights reserved.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is a true proprietary software license.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&#34;relicensing&#34;&gt;Relicensing&lt;/h2&gt;
&lt;p&gt;For most closed source code, this is the end of the copyright story. But some
initially-internal packages are later released under an open source license, and
you might be curious as to how you should go about doing this.&lt;/p&gt;
&lt;p&gt;Fortunately the answer is quite simple if you&amp;rsquo;ve got things set up as I outlined
above: all you have to do is change the license. If you are using one of the
open-source licenses &lt;a href=&#34;https://cran.r-project.org/doc/manuals/R-exts.html#Licensing&#34;&gt;understood by R itself&lt;/a&gt;,
you can delete the &lt;code&gt;LICENSE&lt;/code&gt; file and change the &lt;code&gt;License&lt;/code&gt; field in your
&lt;code&gt;DESCRIPTION&lt;/code&gt; file. If you are using a more uncommon license, just replace the
content of the &lt;code&gt;LICENSE&lt;/code&gt; file in its entirety with the text of that license.&lt;/p&gt;
&lt;p&gt;(You can see examples of this on GitHub in the commit history of the internal
projects an employer permitted me to open-source: &lt;a href=&#34;https://github.com/atheriel/rsyslog/commit/c23eab6658bc8c057e3ca1c2fe44694266c6eb95&#34;&gt;here&lt;/a&gt;
and &lt;a href=&#34;https://github.com/atheriel/longears/commit/04609927bd4794467fe7a9d505f91c183c8f7c92&#34;&gt;here&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;It is important to note what you should not change here, namely the copyright
role (&lt;code&gt;cph&lt;/code&gt;) for your employer in the &lt;code&gt;DESCRIPTION&lt;/code&gt; file. Open-sourcing a
package &lt;strong&gt;does not transfer copyright&lt;/strong&gt; to you or anyone else &amp;ndash; that is a
wholly separate process.&lt;/p&gt;
&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;To sum up, put this in your &lt;code&gt;DESCRIPTION&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;Authors@R: c(
  person(&amp;#34;&amp;lt;My&amp;gt;&amp;#34;, &amp;#34;&amp;lt;Name&amp;gt;&amp;#34;, role = c(&amp;#34;cre&amp;#34;, &amp;#34;aut&amp;#34;)),
  person(&amp;#34;&amp;lt;My Company&amp;gt;&amp;#34;, role = &amp;#34;cph&amp;#34;)
  )
License: file LICENSE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And this in a &lt;code&gt;LICENSE&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;Copyright 2019 &amp;lt;My Company&amp;gt;. All rights reserved.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that&amp;rsquo;s it.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Fair warning: I&amp;rsquo;m not a copyright lawyer. If you are, and have an issue
with the content or arguments presented in this post, please reach out to
me and I will attempt to address it. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
    </content>
    
    
    <category term="r"/>
  </entry>
  <entry>
    <title type="html">What Does R Value?</title>
    
    <link href="https://unconj.ca/blog/what-does-r-value.html" rel="alternate"/>
    <published>2018-12-13T00:00:00Z</published>
    
    
    <updated>2018-12-13T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2018-12-13:blog/what-does-r-value.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;I&amp;rsquo;m fan of Bryan Cantrill&amp;rsquo;s argument that we ought to think about &amp;ldquo;platform
values&amp;rdquo; when assessing technologies, highlighted in &lt;a href=&#34;https://www.youtube.com/watch?v=2wZ1pCpJUIM&#34;&gt;a recent talk&lt;/a&gt;,
but explained more thoroughly in an earlier one on &lt;a href=&#34;https://vimeo.com/230142234&#34;&gt;his experience with the node.js community&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In my reading, he argues that of the many values (such as performance, security,
or expressiveness) that programming languages or platforms may hold, many are in
conflict, and the platform inevitably emphasises some of these values over
others. These decisions are a reflection of explicit or implicit &amp;ldquo;platform
values&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Cantrill illustrates this with a series of examples, but, no surprise, the R
platform does not make his shortlist. I couldn&amp;rsquo;t resist trying to cook up my own
taxonomy of platform values for the R language and its community.&lt;/p&gt;
&lt;p&gt;More broadly, though, Cantrill believes that the values of a platform affect the
projects that adopt them, and conflicts can arise between the values of a
project and its respective choice of platform. This strongly echoes my own
experience in the R community, and I&amp;rsquo;ve gotten a measure of clarity for future
and existing projects by learning to articulate these conflicts.&lt;/p&gt;
&lt;h2 id=&#34;rs-values-the-list&#34;&gt;R&amp;rsquo;s Values: The List&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Note: The effect of the following tables will be diminished without this site&amp;rsquo;s
CSS.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Cantrill gives the following selection of values that we might claim as &amp;ldquo;core&amp;rdquo;
to a platform, although he doesn&amp;rsquo;t consider them exhaustive:&lt;/p&gt;
&lt;table class=&#34;platform-values&#34;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Approachability&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Integrity&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Robustness&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Availability&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Maintainability&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Safety&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Compatibility&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Measurability&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Security&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Composability&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Operability&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Simplicity&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Debuggability&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Performance&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Stability&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Expressiveness&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Portability&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Thoroughness&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Extensibility&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Resiliency&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Transparency&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Interoperability&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Rigour&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Velocity&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;He also gives a few illustrations of platform values; for example, he formulates
the core values of the C programming language as&lt;/p&gt;
&lt;table class=&#34;platform-values&#34;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Approachability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Integrity&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Robustness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Availability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Maintainability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Safety&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Compatibility&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Measurability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Security&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Composability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Operability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Simplicity&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Debuggability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Performance&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Stability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Expressiveness&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Portability&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Thoroughness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Extensibility&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Resiliency&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Transparency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Interoperability&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Rigour&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Velocity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This is not to say that these values preclude us from writing safe, robust, or
composable C code &amp;ndash; in fact, this is expected of expert C programmers &amp;ndash; but
that the language itself does not offer strong support for doing so. Many
features that would make C programs safer have been sacrificed at the altar of
performance.&lt;/p&gt;
&lt;p&gt;In contrast, these are what he sees as the core values of the Javascript
community in general and &lt;code&gt;node.js&lt;/code&gt; in particular:&lt;/p&gt;
&lt;table class=&#34;platform-values&#34;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Approachability&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Integrity&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Robustness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Availability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Maintainability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Safety&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Compatibility&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Measurability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Security&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Composability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Operability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Simplicity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Debuggability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Performance&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Stability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Expressiveness&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Portability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Thoroughness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Extensibility&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Resiliency&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Transparency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Interoperability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Rigour&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Velocity&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;There are some additional examples for C++, Awk, &lt;a href=&#34;https://en.wikipedia.org/wiki/K_(programming_language)&#34;&gt;K&lt;/a&gt;,
OpenBSD &amp;ndash; which values only &lt;em&gt;Security&lt;/em&gt; &amp;ndash; and others in his talks.&lt;/p&gt;
&lt;p&gt;I would formulate the core values of the R platform as follows:&lt;/p&gt;
&lt;table class=&#34;platform-values&#34;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Approachability&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Integrity&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Robustness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Availability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Maintainability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Safety&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Compatibility&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Measurability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Security&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Composability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Operability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Simplicity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Debuggability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Performance&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Stability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Expressiveness&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Portability&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Thoroughness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Extensibility&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Resiliency&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Transparency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Interoperability&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;Rigour&lt;/td&gt;
&lt;td&gt;&lt;span style=&#34;color: #d44950&#34;&gt;•&lt;/span&gt;&amp;nbsp;&lt;strong&gt;Velocity&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The presence of &lt;em&gt;Approachability&lt;/em&gt; and &lt;em&gt;Velocity&lt;/em&gt; in this list should be no
surprise: R is and always has been a language heavily geared to those learning a
bit of programming to fulfil their need to do data analysis and statistics. It
has a long history of efforts to get that group up and running as fast as
possible. I also think that the recent push to build tools and packages that
make working with R &amp;ldquo;fun&amp;rdquo; or &amp;ldquo;easy&amp;rdquo; &amp;ndash; complete with the requisite emoji &amp;ndash; is a
re-expression of these values as core to the platform.&lt;/p&gt;
&lt;p&gt;Similarly, it is clear to me that R holds &lt;em&gt;Extensibility&lt;/em&gt; by its users, through
the development of functions and then packages, in very high regard. It is a
&lt;a href=&#34;./why-there-is-no-importfrom-in-r.html&#34;&gt;widely-held view&lt;/a&gt; that any non-trivial
R code ought to be bundled up into a package so that it can be distributed
painlessly to others. In fact, this view is so pervasive that the traditional
&amp;ldquo;scripting&amp;rdquo; options for R are limited: &lt;code&gt;Rscript&lt;/code&gt; did not become part of the
language until 2007, and none of the built-in tooling (e.g. &lt;code&gt;NAMESPACE&lt;/code&gt; or
&lt;code&gt;DESCRIPTION&lt;/code&gt; files, or &lt;code&gt;R CMD check&lt;/code&gt;) works with standalone R scripts.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s worth explaining why I have highlighted &lt;em&gt;Integrity&lt;/em&gt;. What I have in mind
here is R&amp;rsquo;s language level support for the notion of &amp;ldquo;missing values&amp;rdquo; (&lt;code&gt;NA&lt;/code&gt;).
All functions &lt;em&gt;must&lt;/em&gt; handle missing values, and function authors are constantly
on the hook for deciding how their function ought to behave in the absence of
data (&lt;code&gt;na.rm&lt;/code&gt;, anyone?). This represents a remarkable commitment to ensuring the
integrity of R&amp;rsquo;s many mathematical programs.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&#34;rs-values-the-consequences&#34;&gt;R&amp;rsquo;s Values: The Consequences&lt;/h2&gt;
&lt;p&gt;Part of the larger argument about why platform values are important is that they
affect the nature of the projects that are built on these platforms. Some of
this is unequivocally positive: for instance, I would argue that efforts by
folks like DataCamp to teach R &lt;a href=&#34;https://medium.com/datacamp/context-on-why-we-started-datacamp-d4df02fcc87c&#34;&gt;as widely as possible&lt;/a&gt;
have been much helped by the platform&amp;rsquo;s preexisting commitment to
&lt;em&gt;Approachability&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Similarly, one might well attribute the enormous popularity of R as an
implementation language for cutting-edge statistical methods to the platform&amp;rsquo;s
focus on &lt;em&gt;Velocity&lt;/em&gt; and &lt;em&gt;Extensibility&lt;/em&gt;, at least in the case of the academic
statistical community.&lt;/p&gt;
&lt;p&gt;And I have no doubt that R&amp;rsquo;s focus on &lt;em&gt;Integrity&lt;/em&gt; has had a quiet but meaningful
impact on the many statistical analyses that are undertaken with it.&lt;/p&gt;
&lt;p&gt;Still, we can&amp;rsquo;t have everything, and in the case of the R platform, there is no
doubt that you can encounter hurdles if you pursue projects that align with
different values. In my view, the most pressing concern is the way R&amp;rsquo;s platform
values diverge from those held by those running applications of one kind or
another.&lt;/p&gt;
&lt;p&gt;Much of my recent professional life has been focused on divining ways for my
team to run R code in &amp;ldquo;production&amp;rdquo; environments, where values like &lt;em&gt;Stability&lt;/em&gt;,
&lt;em&gt;Resiliency&lt;/em&gt;, &lt;em&gt;Robustness&lt;/em&gt;, &lt;em&gt;Measurability&lt;/em&gt;, and &lt;em&gt;Debuggability&lt;/em&gt; become
dramatically more important. This has had a substantial impact on the nature of
the R code we write, and the kinds of tools we build to help us write it better.&lt;/p&gt;
&lt;p&gt;With the advent of &lt;a href=&#34;https://shiny.rstudio.com/&#34;&gt;Shiny&lt;/a&gt; and &lt;a href=&#34;https://www.rplumber.io/&#34;&gt;Plumber&lt;/a&gt;,
these past few years have witnessed a sea change in the ability for R users to
tackle writing true applications. It remains to be seen whether R&amp;rsquo;s platform
values &amp;ndash; as they exist today &amp;ndash; will curtail the growth of these projects, or
whether these projects will have some success in changing the culture of R
itself.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;One might also argue that the popular &lt;strong&gt;tidyverse&lt;/strong&gt; ecosystem attempts to
bring &lt;em&gt;Composability&lt;/em&gt; and &lt;em&gt;Compatibility&lt;/em&gt; more into the foreground. You
can see this in the current &lt;a href=&#34;https://www.tidyverse.org&#34;&gt;mission statement&lt;/a&gt;
of the project:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The tidyverse is an opinionated collection of R packages designed for
data science. All packages share an underlying design philosophy,
grammar, and data structures.&lt;/p&gt;
&lt;/blockquote&gt;
 &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
    </content>
    
    
    <category term="r"/>
  </entry>
  <entry>
    <title type="html">Why There is No importFrom() Function in R</title>
    
    <link href="https://unconj.ca/blog/why-there-is-no-importfrom-in-r.html" rel="alternate"/>
    <published>2018-08-27T00:00:00Z</published>
    
    
    <updated>2018-08-27T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2018-08-27:blog/why-there-is-no-importfrom-in-r.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;For those coming to R from other languages, it seems very odd that R users
import code from packages the way that they do. For instance, if you are used to
Python, this is the general pattern of &amp;ldquo;using code from elsewhere&amp;rdquo;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;math&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;numpy&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;np&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;random&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;randint&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Usage:&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;math&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;floor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;3.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;np&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;randint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Meanwhile, in R, you&amp;rsquo;re likely to see&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dplyr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;data_frame&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;hellip; with the subtext being that users must simply &lt;em&gt;know&lt;/em&gt; that the
&lt;code&gt;data_frame()&lt;/code&gt;, &lt;code&gt;mutate()&lt;/code&gt;, and &lt;code&gt;%&amp;gt;%&lt;/code&gt; functions are actually all from the
&lt;strong&gt;dplyr&lt;/strong&gt; package. Why is R so unusual here?&lt;/p&gt;
&lt;p&gt;Unlike C or &lt;a href=&#34;https://emacs.stackexchange.com/questions/2706/why-does-elisp-not-have-namespaces&#34;&gt;some familiar Lisps&lt;/a&gt;,
R has proper namespace support, so it&amp;rsquo;s not as though conflicting symbols are
simply overwritten when you use &lt;code&gt;library()&lt;/code&gt; in the way they would be when using
&lt;code&gt;#include&lt;/code&gt; in C. Moreover, there is one place that R users &lt;em&gt;do&lt;/em&gt; work with a
highly granular mechanism to control how symbols are imported into an
environment: when working with the &lt;code&gt;NAMESPACE&lt;/code&gt; file included with every R
package. If you crack open one of these files, you&amp;rsquo;ll see lines like&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;importFrom(dplyr, mutate, data_frame, %&amp;gt;%)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;which look a bit like pseudo-R code. Yet there is no &lt;code&gt;importFrom()&lt;/code&gt;
function in R itself. It&amp;rsquo;s not hard to write one if we make use of the
not-widely-advertised namespace API, either:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;importFrom&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pkg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;pkg&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;as.character&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;substitute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pkg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;call&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;match.call&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;symbols&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;vapply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;call&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;as.character&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;call[[i]]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;character&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;ns&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;loadNamespace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pkg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;importIntoEnv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;parent.frame&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;symbols&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ns&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;symbols&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;invisible&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Confirm that it works:&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;importFrom&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tibble&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;is.tibble&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;as_tibble&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dplyr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;data_frame&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;is.tibble&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; [1] TRUE&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;is.tibble&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; function(x) {&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt;   &amp;#34;tbl_df&amp;#34; %in% class(x)&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; }&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; &amp;lt;bytecode: 0x55c14454ca60&amp;gt;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; &amp;lt;environment: namespace:tibble&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So that&amp;rsquo;s clearly not the barrier. In fact if this appeals to you there is a
fully-realized vision of an &lt;code&gt;import*()&lt;/code&gt; function for R available in the
&lt;a href=&#34;https://github.com/smbache/import&#34;&gt;&lt;strong&gt;import&lt;/strong&gt; package&lt;/a&gt;. But there is still a
question of why the language itself does not include such a function.&lt;/p&gt;
&lt;p&gt;I was curious about whether anything had been written about this before, so I
&lt;a href=&#34;https://stat.ethz.ch/pipermail/r-devel/2018-July/076467.html&#34;&gt;asked about the historical reason that R does not have an &lt;code&gt;importFrom()&lt;/code&gt;
function&lt;/a&gt; on the
&lt;code&gt;r-devel&lt;/code&gt; mailing list. While I didn&amp;rsquo;t get an answer from those involved, those
who did comment raised some interesting points.&lt;/p&gt;
&lt;p&gt;The first is that larger R programs tend to get refactored into R packages,
which &lt;em&gt;do&lt;/em&gt; have careful management of imported functions and packages. (This
largely aligns with my own experience.) And the second is that R has a strong
culture of development-by-interpreter, where &lt;code&gt;library()&lt;/code&gt; is a useful shortcut to
getting the third-party functions that you want.&lt;/p&gt;
&lt;p&gt;I also suspect that the history of the language plays a part as well. When
&lt;a href=&#34;http://homepage.divms.uiowa.edu/~luke/R/namespaces/morenames.pdf&#34;&gt;namespace support was added to the R language in 2003&lt;/a&gt;, the
language had a strong emphasis on maintaining compatibility with the S language,
so that new users would not need to rewrite much of their existing code. S used
&lt;code&gt;library()&lt;/code&gt;, and thus R provided &lt;code&gt;library()&lt;/code&gt;. And insofar as there was a design
principle for the S language, it was that users could &lt;a href=&#34;https://web.archive.org/web/20170807164202/http://ect.bell-labs.com/sl/S/history.html&#34;&gt;begin using it without
thinking of themselves as &amp;ldquo;programmers&amp;rdquo;&lt;/a&gt;,
and gradually slide into programming as their analyses demanded it. The
&lt;code&gt;library()&lt;/code&gt; approach is in line with this philosophy, in my view.&lt;/p&gt;
&lt;p&gt;And of course, there is also the reality that R has almost thirty years of
development and design decisions to account for &amp;ndash; almost 50 if we include its S
ancestors dating back to 1976. By this measure, R is contemporary with the very
first versions of Unix (1975), Emacs (1976), and &lt;a href=&#34;https://en.wikipedia.org/wiki/TeX&#34;&gt;TeX&lt;/a&gt;
(1978). I&amp;rsquo;m sure that some of these decisions might be regretted or resented by
the core R developers, but most of these now-features have users expecting at
least some semblance of backwards compatibility.&lt;/p&gt;
&lt;p&gt;In the end I think that the main reason that we don&amp;rsquo;t see mass migration to
solutions like the &lt;strong&gt;import&lt;/strong&gt; package speaks to a deeper division in the R
community. The R users who are likely to raise concerns over using &lt;code&gt;library()&lt;/code&gt;
in scripts &amp;ndash; those worried about code hygiene or dependency management, for
example &amp;ndash; are likely willing and able to solve these problems in other ways,
notably by refactoring code into packages. And as Roger Peng argued in his
recent keynote at useR! 2018, R has focused on programmer-oriented features &lt;a href=&#34;https://simplystatistics.org/2018/07/12/use-r-keynote-2018/#making-r-a-real-programming-language-almost-killed-it&#34;&gt;at
its peril&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For the large contingent of R users writing run-once data analysis scripts &amp;ndash;
still the key constituency of the language &amp;ndash; &lt;code&gt;library()&lt;/code&gt; is exactly what you
want: no hassle access to third-party functions. That this is the default
recommendation, as opposed to some version of &lt;code&gt;importFrom()&lt;/code&gt;, reflects the
nature of the R community.&lt;/p&gt;
    </content>
    
    
    <category term="r"/>
  </entry>
  <entry>
    <title type="html">Communicating with UDP Sockets from R</title>
    
    <link href="https://unconj.ca/blog/udp-sockets-in-r.html" rel="alternate"/>
    <published>2018-07-06T00:00:00Z</published>
    
    
    <updated>2018-07-06T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2018-07-06:blog/udp-sockets-in-r.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;Recently I wanted to send some Shiny usage data from R to a &lt;a href=&#34;https://github.com/etsy/statsd&#34;&gt;certain metrics
server&lt;/a&gt;. Since R includes &lt;code&gt;write.socket()&lt;/code&gt; and
friends for opening arbitrary network sockets, it seemed at the outset that this
would be quite simple. However, I ran into an interesting roadblock along the
way.&lt;/p&gt;
&lt;p&gt;It turns out that R&amp;rsquo;s socket API only supports TCP connections, which you can
confirm by &lt;a href=&#34;https://github.com/wch/r-source/blob/trunk/src/modules/internet/sock.c#L104-L157&#34;&gt;looking at the source code&lt;/a&gt;
&amp;ndash; and in this case I needed to send &lt;a href=&#34;https://en.wikipedia.org/wiki/User_Datagram_Protocol&#34;&gt;UDP&lt;/a&gt;
packets instead. This was a little surprising to me, since most other languages
would include UDP support out of the box; it&amp;rsquo;s a core internet protocol, after
all. For whatever reason, this seems not to be the case with R, and even after
searching CRAN and GitHub I wasn&amp;rsquo;t able to find an existing package that
provides UDP socket support.&lt;/p&gt;
&lt;p&gt;To remedy this, I put together a simple way to write messages to UDP sockets
from R.&lt;/p&gt;
&lt;p&gt;Since working with sockets is done at the system level, it makes sense to use
R&amp;rsquo;s C API in this case. The following is a self-contained implementation that
you can drop into an R package&amp;rsquo;s &lt;code&gt;src&lt;/code&gt; directory as &lt;code&gt;udp.c&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;Rinternals.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;R_ext/Rdynload.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;sys/socket.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;arpa/inet.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;SEXP&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;udp_send_impl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SEXP&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SEXP&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;host&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SEXP&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;msg&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;CHAR&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;asChar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
  &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;host_&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;CHAR&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;asChar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;host&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
  &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;port_&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;asInteger&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

  &lt;span class=&#34;c1&#34;&gt;// Open the socket.
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
  &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sockaddr_in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sock&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;socket&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AF_INET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SOCK_DGRAM&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IPPROTO_UDP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;Rf_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Failed to create UDP socket.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;R_NilValue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

  &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin_family&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AF_INET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s_addr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;INADDR_ANY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin_port&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;htons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;short&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;port_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;inet_aton&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;host_&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sin_addr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;Rf_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Failed to parse host address.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;close&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;R_NilValue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

  &lt;span class=&#34;c1&#34;&gt;// Send message.
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sendto&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;msg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;strlen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;msg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sockaddr&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;Rf_error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Failed to send message.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

  &lt;span class=&#34;n&#34;&gt;close&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;R_NilValue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;R_CallMethodDef&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;udp_entries&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;udp_send_impl&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DL_FUNC&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;udp_send_impl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;

&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;R_init_udp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DllInfo&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;R_registerRoutines&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;udp_entries&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;R_useDynamicSymbols&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that you may need to adjust the &lt;code&gt;R_registerRoutines()&lt;/code&gt; code if you have
existing C or C++ code in your package.&lt;/p&gt;
&lt;p&gt;To use this C function from R, you&amp;rsquo;ll need something like the following in your
package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;c1&#34;&gt;#&amp;#39; @export&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;#39; @useDynLib udp udp_send_impl&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;udp_send&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;host&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;localhost&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;stopifnot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;is.character&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;stopifnot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;is.character&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;host&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;stopifnot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;is.numeric&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;.Call&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;udp_send_impl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;host&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;as.integer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
  &lt;span class=&#34;nf&#34;&gt;invisible&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To confirm that this works, you can listen for UDP packets with from a terminal
with&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ nc -lu &lt;span class=&#34;m&#34;&gt;1001&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and you can send UDP packets to that server from R with&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;udp_send&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Hello from R!&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;host&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;localhost&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;port&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1001&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
    </content>
    
    
    <category term="r"/>
  </entry>
  <entry>
    <title type="html">Principles for Pipe-Friendly APIs in R Packages</title>
    
    <link href="https://unconj.ca/blog/principles-for-pipe-friendly-apis.html" rel="alternate"/>
    <published>2018-03-28T00:00:00Z</published>
    
    
    <updated>2018-03-28T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2018-03-28:blog/principles-for-pipe-friendly-apis.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;In the past few years the APIs of the wildly popular &lt;strong&gt;tidyverse&lt;/strong&gt; packages have
coalesced around the pipe operator (&lt;code&gt;%&amp;gt;%&lt;/code&gt;). R users familiar with this ecosystem
of packages are now accustomed to writing &amp;ldquo;pipelines&amp;rdquo; where code is expressed as
a series of steps composed with the pipe operator.&lt;/p&gt;
&lt;p&gt;For example, plenty of data science code basically boils down to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;transform&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;summarise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(This is even more evident if you subscribe to Wickham &amp;amp; Grolemund&amp;rsquo;s view that
models are a &lt;a href=&#34;http://r4ds.had.co.nz/model-intro.html&#34;&gt;&amp;ldquo;low-dimensional summary of your data&amp;rdquo;&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;There are plenty of resources on how to use pipes to re-write you R code. There
are fewer on the implications of pipes on how R functions and package APIs are
designed. What should package authors should keep in mind, knowing that their
users are likely to use their functions in pipelines?&lt;/p&gt;
&lt;p&gt;My own experience has led me to compile four principles for writing pipe-
friendly APIs for R packages:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Only one argument is going to be &amp;ldquo;piped&amp;rdquo; into your functions, so you should
design them to accommodate this. The first argument should be what you&amp;rsquo;d
expect to be piped in; all other arguments should be parameters with
meaningful default values. If you think you&amp;rsquo;ll always need more than one
argument, consider wrapping them up in a lightweight S3 class.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Think carefully about the output of your functions, since this will be what
is passed down the pipeline. Strive to always return a single type of output
(a data frame, a numeric vector, etc). Never return &lt;code&gt;NULL&lt;/code&gt;, because very few
functions can take &lt;code&gt;NULL&lt;/code&gt; as an input. (To signify empty values, use zero-row
data frames or vectors with &lt;code&gt;NA&lt;/code&gt;.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Prefer &amp;ldquo;pure&amp;rdquo; functions &amp;ndash; e.g. those that have no &amp;ldquo;side effects&amp;rdquo; that mutate
global state &amp;ndash; whenever possible. Users think about pipelines as a linear
progression of steps. The transparency of pure functions make them easy to
reason about in this fashion.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When your functions must have side effects (e.g. when printing or plotting),
return the original object (instead of the conventional &lt;code&gt;NULL&lt;/code&gt;) so that
pipelines can continue.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I&amp;rsquo;ve found that being explicit about these design goals has improved the quality
of my own package interfaces; perhaps they can be of use to others.&lt;/p&gt;
    </content>
    
    
    <category term="r"/>
  </entry>
  <entry>
    <title type="html">A Note on Migrating Packages from rjson to jsonlite</title>
    
    <link href="https://unconj.ca/blog/a-note-on-migrating-packages-from-rjson-to-jsonlite.html" rel="alternate"/>
    <published>2018-02-19T00:00:00Z</published>
    
    
    <updated>2018-02-19T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2018-02-19:blog/a-note-on-migrating-packages-from-rjson-to-jsonlite.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;Recently I was working on an R package that had historically used both &lt;strong&gt;rjson&lt;/strong&gt;
and &lt;strong&gt;jsonlite&lt;/strong&gt; to serialize R objects to JSON (before sending it off to an
API). In this case we wanted to remove the &lt;strong&gt;rjson&lt;/strong&gt; depdency, which was only
used in a few places.&lt;/p&gt;
&lt;p&gt;The most noticable hiccup I encountered while porting the code was during
encoding of parameter lists generated in R, which looked something like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;key1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;param&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;key2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
               &lt;span class=&#34;n&#34;&gt;key3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;paired&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;params&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this case, &lt;strong&gt;rjson&lt;/strong&gt; produced exactly what our API was looking for:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;cat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rjson&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;toJSON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; {&amp;#34;key1&amp;#34;:&amp;#34;param&amp;#34;,&amp;#34;key2&amp;#34;:null,&amp;#34;key3&amp;#34;:[&amp;#34;paired&amp;#34;,&amp;#34;params&amp;#34;]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But by default the &lt;strong&gt;jsonlite&lt;/strong&gt; package will behave very differently:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;jsonlite&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;toJSON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; {&amp;#34;key1&amp;#34;:[&amp;#34;param&amp;#34;],&amp;#34;key2&amp;#34;:{},&amp;#34;key3&amp;#34;:[&amp;#34;paired&amp;#34;,&amp;#34;params&amp;#34;]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;(That is, the &lt;code&gt;NULL&lt;/code&gt; has been converted to an empty dictionary and the &lt;code&gt;key1&lt;/code&gt;
parameter has been turned into a one-element array.)&lt;/p&gt;
&lt;p&gt;Fortunately, &lt;strong&gt;jsonlite&lt;/strong&gt; is quite configurable. Vectors of a single element can
be converted into bare values by passing the &lt;code&gt;auto_unbox&lt;/code&gt; parameter to
&lt;code&gt;toJSON()&lt;/code&gt; (or handled individually with &lt;code&gt;unbox()&lt;/code&gt;), and handling of &lt;code&gt;NULL&lt;/code&gt;
values can be customized with the &lt;code&gt;null&lt;/code&gt; paramter.&lt;/p&gt;
&lt;p&gt;To get the &lt;strong&gt;jsonlite&lt;/strong&gt; equivalent to the &lt;strong&gt;rjson&lt;/strong&gt; output above, we used&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;jsonlite&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;toJSON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auto_unbox&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;null&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;null&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; {&amp;#34;key1&amp;#34;:&amp;#34;param&amp;#34;,&amp;#34;key2&amp;#34;:null,&amp;#34;key3&amp;#34;:[&amp;#34;paired&amp;#34;,&amp;#34;params&amp;#34;]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;During the transition, I ran a number of tests to ensure that the conversions
were equivalent. Since &lt;strong&gt;jsonlite&lt;/strong&gt; produces an object of class &lt;code&gt;&amp;quot;json&amp;quot;&lt;/code&gt;, you&amp;rsquo;ll
need to coerce to character to make things like &lt;code&gt;all.equal()&lt;/code&gt; work correctly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rjson&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;toJSON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;jsonlite&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;toJSON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;auto_unbox&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;null&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;null&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;all.equal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; [1] &amp;#34;Attributes: &amp;lt; target is NULL, current is list &amp;gt;&amp;#34;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; [2] &amp;#34;target is character, current is json&amp;#34;&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;all.equal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;as.character&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;#&amp;gt; [1] TRUE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Technical merits of each respective package aside, I think it&amp;rsquo;s likely that some
existing &lt;strong&gt;rjson&lt;/strong&gt; code will migrate to &lt;strong&gt;jsonlite&lt;/strong&gt; in the future. Hopefully
this post helps make that process a smooth one.&lt;/p&gt;
    </content>
    
    
    <category term="r"/>
  </entry>
  <entry>
    <title type="html">Don&#39;t Forget to Reproject Spatial Data when Exporting to GeoJSON</title>
    
    <link href="https://unconj.ca/blog/dont-forget-to-reproject-for-geojson.html" rel="alternate"/>
    <published>2017-07-05T00:00:00Z</published>
    
    
    <updated>2017-07-05T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2017-07-05:blog/dont-forget-to-reproject-for-geojson.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;In the process of working on a recent &lt;a href=&#34;https://cdhowe.org/graphic-intelligence/mapping-childhood-immunization-coverage-canada&#34;&gt;choropeth piece for work&lt;/a&gt;,
I discovered that it&amp;rsquo;s easy to stumble when moving spatial data out of R and
onto the web. It&amp;rsquo;s a poorly-documented reality that many web-based mapping
libraries (including both D3 and Leaflet) expect GeoJSON data to be in
&lt;code&gt;EPSG:4326&lt;/code&gt;, and it is by no means a given that that your spatial data will
start off in this projection.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re like me and do your spatial data pre-processing in R before exporting
to GeoJSON, you may have to re-project your data before these libraries will
handle them properly. Thankfully, this is fairly easy to do with the modern
spatial packages.&lt;/p&gt;
&lt;p&gt;The next-gen spatial package &lt;strong&gt;sf&lt;/strong&gt; provides an &lt;code&gt;st_transform()&lt;/code&gt; function for
reprojecting spatial objects. My current workflow for taking shapefiles,
adding/removing features and data, and writing out a GeoJSON file that can be
read in D3 or Leaflet looks something like the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-R&#34; data-lang=&#34;R&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dplyr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;sf&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;st_read&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;path/to/shapefile&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;layer&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;layer&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&#34;c1&#34;&gt;# Filter, mutate, join, select on this spatial data.&lt;/span&gt;
  &lt;span class=&#34;kc&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&#34;c1&#34;&gt;# Re-project the map into EPSG:4326 before writing to GeoJSON.&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;sf&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;st_transform&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;4326&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
  &lt;span class=&#34;n&#34;&gt;sf&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;st_write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;map.json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;driver&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;GeoJSON&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This GeoJSON data can then be re-projected using the Javascript library into
something more appropriate than &lt;code&gt;EPSG:4326&lt;/code&gt;. In D3 this looks something like the
following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// This example projection works well for Canadian maps. I
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// cribbed it from Statistics Canada:
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// http://www.statcan.gc.ca/pub/82-402-x/2015001/gui-eng.htm#a6
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;proj&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;d3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;geoConicConformal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;parallels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;49&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;77&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;rotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;91.86&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;63.390675&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]);&lt;/span&gt;

&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;path&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;d3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;geoPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;projection&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;proj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

&lt;span class=&#34;nx&#34;&gt;d3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;json&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;map.json&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;throw&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;// Protip: use `fitSize()` set the projection scale, center,
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;// and translation automatically to fit in the SVG element.
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;nx&#34;&gt;proj&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fitSize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;780&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;features&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

    &lt;span class=&#34;nx&#34;&gt;d3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;svg&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;attr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;width&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;780&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;attr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;height&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;selectAll&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;features&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;enter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;attr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;d&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;style&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;stroke&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;white&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I did &lt;a href=&#34;https://github.com/edzer/sfr/issues/344&#34;&gt;report this issue to &lt;strong&gt;sf&lt;/strong&gt; itself&lt;/a&gt;,
but the maintainer indicated that the library ought to be sticking to the
standard, regardless of existing implementation quirks. In the meantime, if you
plan to export GeoJSON data for use with Javascript libraries, don&amp;rsquo;t forget to
reproject as necessary.&lt;/p&gt;
    </content>
    
    
    <category term="d3"/>
    <category term="data"/>
    <category term="js"/>
    <category term="r"/>
    <category term="visualization"/>
  </entry>
  <entry>
    <title type="html">Forecasting YYZ Passengers in the Tidyverse</title>
    
    <link href="https://unconj.ca/blog/forecasting-yyz-passengers-in-the-tidyverse.html" rel="alternate"/>
    <published>2017-03-02T00:00:00Z</published>
    
    
    <updated>2017-03-02T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2017-03-02:blog/forecasting-yyz-passengers-in-the-tidyverse.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;Buried in the &lt;a href=&#34;http://www1.toronto.ca/wps/portal/contentonly?vgnextoid=c9d08c94b2e55510VgnVCM10000071d60f89RCRD&amp;amp;vgnextchannel=b227e03bb8d1e310VgnVCM10000071d60f89RCRD&#34;&gt;Toronto Economic Bulletin&lt;/a&gt;
(warning: Excel document) is a column listing the number of passengers passing
through Pearson International Airport (YYZ) each month, going back more than
fifteen years. There&amp;rsquo;s a story to tell in the forecast, too:&lt;/p&gt;
&lt;center&gt;
&lt;img src=&#34;./images/r-6c067198/narrative-plot-1.png&#34; alt=&#34;Passengers at Pearson&#34;&gt;
&lt;/center&gt;
&lt;p&gt;Flight data are a great forecasting example because they display such clear
seasonal patterns, in this case peaking in the summer months and falling off in
the winter. R has excellent tools for working with time series data and whipping
up simple forecasts like this one. But there&amp;rsquo;s some friction with the modern
&lt;strong&gt;tidyverse&lt;/strong&gt; tools, because the latter expect a &lt;code&gt;data.frame&lt;/code&gt; as the common
interchange format.&lt;/p&gt;
&lt;p&gt;In this post, I&amp;rsquo;ll outline an approach to fitting many time series models using
the tidyverse tools, including model selection for out-of-sample performance. To
ease the transition between these two worlds I make extensive use of list
columns and the &lt;strong&gt;broom&lt;/strong&gt; package.&lt;/p&gt;
&lt;h2 id=&#34;the-set-up&#34;&gt;The Set Up&lt;/h2&gt;
&lt;p&gt;For this post I&amp;rsquo;ve extracted the data into a vector of R&amp;rsquo;s built-in &lt;code&gt;ts&lt;/code&gt; class,
which is the common interchange format for most time series packages. As of
writing, I have data from January 2000 through August 2016.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# load(&amp;#34;path/to/passengers.rda&amp;#34;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;passengers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;##  Time-Series [1:200] from 2000 to 2017: 2072798 2118150 2384907 2260620 2386165 2635018 2788843 2942082 2477000 2527969 ...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You&amp;rsquo;ll also need the following packages, all of which are staples of the
tidyverse except for &lt;strong&gt;forecast&lt;/strong&gt;, which is a prominent time series forecasting
package for R:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;suppressMessages&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dplyr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tidyr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;purrr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;broom&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ggplot2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;forecast&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;time-series-forecasting-in-r&#34;&gt;Time Series Forecasting in R&lt;/h2&gt;
&lt;p&gt;There are an overwhelming number of time series models used for forecasting out
there (see &lt;a href=&#34;https://cran.r-project.org/web/views/TimeSeries.html&#34;&gt;the CRAN task view on time series&lt;/a&gt;
for a sense of what&amp;rsquo;s available in R alone), but the most common ones are
probably &lt;abbr title=&#34;Autoregressive Integrated Moving Average&#34;&gt;ARIMA&lt;/abbr&gt;
and &lt;abbr title=&#34;Exponential Smoothing State Space&#34;&gt;ETS&lt;/abbr&gt;, both of which
can handle seasonal data sets like this one.&lt;/p&gt;
&lt;p&gt;In choosing a model for forecasting, what we care about is the accuracy of the
model on &lt;em&gt;unseen&lt;/em&gt; (that is, out-of-sample) data. Since we don&amp;rsquo;t have a way of
measuring that directly, we simulate the experience by holding out a test set.&lt;/p&gt;
&lt;p&gt;The nature of the autocorrelated errors in time series data mean that randomly
selecting training and test sets (or, indeed, using traditional bootstrap or
cross-validation) will erase much of the information in the data, so common
practice with time series data is to hold out the last few observations, ideally
the same interval as you&amp;rsquo;d like to forecast over.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll mention that this risks overfitting to this particular test set, something
I&amp;rsquo;ll return to below. (As the statistician Andrew Gelman &lt;a href=&#34;http://andrewgelman.com/2015/06/02/cross-validation-magic/&#34;&gt;has remarked&lt;/a&gt;,
it is important to realise that test sets and cross validation are estimates of
out-of-sample performance, not a direct measure.)&lt;/p&gt;
&lt;p&gt;For this post I&amp;rsquo;m going to hold out the two most recent years&#39; worth of data as
a test set. R provides a convenient &lt;code&gt;window&lt;/code&gt; function for breaking up time
series:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;train&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;passengers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;end&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2014&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;test&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;passengers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;start&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2014&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;9&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can use this training set to fit some ARIMA and ETS models, and see how they
compare.&lt;/p&gt;
&lt;h3 id=&#34;fitting-arima-models-in-r&#34;&gt;Fitting ARIMA Models in R&lt;/h3&gt;
&lt;p&gt;R has built in support for fitting ARIMA models with, you guessed it, the
&lt;code&gt;arima()&lt;/code&gt; function. However, there are a number of shortcomings to this
implementation, so I&amp;rsquo;d recommend using the &lt;code&gt;Arima()&lt;/code&gt; version from the
&lt;strong&gt;forecast&lt;/strong&gt; package instead. You can also try your luck with the package&amp;rsquo;s
&lt;code&gt;auto.arima()&lt;/code&gt; function, which will try and find an optimal model automatically.&lt;/p&gt;
&lt;p&gt;Choosing the order of an ARIMA model usually benefits from some manual
exploration of the autocorrelated errors, especially using the
&lt;code&gt;forecast::tsdisplay()&lt;/code&gt; plot. For brevity I won&amp;rsquo;t walk you through the process
here, but I&amp;rsquo;d strongly recommend taking a look at Rob Hyndman and George
Athanasopoulos&#39; &lt;a href=&#34;https://www.otexts.org/fpp/8/9&#34;&gt;chapter on forecasting seasonal data using ARIMA&lt;/a&gt;,
which is freely available online.&lt;/p&gt;
&lt;p&gt;For now, &lt;code&gt;auto.arima()&lt;/code&gt; should do just fine. It&amp;rsquo;s worth experimenting with the
approximations disabled, as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;arima.fit&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;forecast&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;auto.arima&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;train&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;D&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                  &lt;span class=&#34;n&#34;&gt;stepwise&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                  &lt;span class=&#34;n&#34;&gt;approximation&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;arima.fit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## Series: train 
## ARIMA(0,1,1)(0,1,1)[12]                    
## 
## Coefficients:
##           ma1     sma1
##       -0.1927  -0.6731
## s.e.   0.0774   0.0675
## 
## sigma^2 estimated as 6.925e+09:  log likelihood=-2080.57
## AIC=4167.15   AICc=4167.3   BIC=4176.43
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The automatic process selects an ARIMA model with low order, indicating that a
simple model might fit this data reasonably well.&lt;/p&gt;
&lt;h3 id=&#34;fitting-ets-models-in-r&#34;&gt;Fitting ETS Models in R&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;forecast&lt;/strong&gt; package also provides an &lt;code&gt;ets&lt;/code&gt; function, which by default will
choose an optimal model:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;ets.fit&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;forecast&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;ets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;train&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;ZZZ&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;ets.fit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## ETS(A,N,A) 
## 
## Call:
##  forecast::ets(y = train, model = &amp;quot;ZZZ&amp;quot;) 
## 
##   Smoothing parameters:
##     alpha = 0.7467 
##     gamma = 1e-04 
## 
##   Initial states:
##     l = 2373863.6415 
##     s=-155048.7 -371915.5 -66744.27 -9469.378 562836.6 411528.9
##            104613.3 -2894.734 -101326.8 65840.67 -269851.6 -167568.5
## 
##   sigma:  79047.8
## 
##      AIC     AICc      BIC 
## 4909.794 4912.794 4957.351
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Notice that this (ostensibly optimal) model has an AICc of 4912.794,
which is much higher than the ARIMA models explored above. This may be an
indication that ETS models are not a good fit for this data set.&lt;/p&gt;
&lt;h2 id=&#34;fitting-many-models-using-list-columns-and-purrr&#34;&gt;Fitting Many Models using List-Columns and Purrr&lt;/h2&gt;
&lt;p&gt;One can choose both an ARIMA and ETS model based on how well it fits the
training data. However, when forecasting, better out-of-sample performance is
the true goal. For this reason, I&amp;rsquo;m going to take a more systematic approach,
fitting a wide variety of both ETS and ARIMA models and comparing their
out-of-sample performance.&lt;/p&gt;
&lt;p&gt;Inspired by the general coherence of the tidyverse, I believe all of this can be
organized into a &lt;a href=&#34;https://www.jstatsoft.org/article/view/v059i10&#34;&gt;tidy&lt;/a&gt; data
frame, with one model per row. I use the following approach:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create columns for training data, modelling functions, and any other model
parameters.&lt;/li&gt;
&lt;li&gt;Wrap these training data and model parameters into a single &lt;code&gt;param&lt;/code&gt; column.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;purrr::invoke_map()&lt;/code&gt; to apply the modelling function to these model
parameters; and&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;purrr::map()&lt;/code&gt; and friends (or &lt;code&gt;broom::glance()&lt;/code&gt;) to extract goodness of
fit measures.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To start with, we create data sets of models and their parameters. The following
will generate a data frame of all possible ETS models (check out &lt;code&gt;?ets&lt;/code&gt; for
details):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;ets.params&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tidyr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;crossing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;error&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;M&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;trend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;N&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;M&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;seasonal&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;N&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;M&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;damped&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Drop combinations with a damped non-trend.&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;drop&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ifelse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;trend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;N&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;damped&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;drop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Create labels for the models out of these parameters.&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kind&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;ETS&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
           &lt;span class=&#34;n&#34;&gt;desc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;(&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;trend&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                         &lt;span class=&#34;nf&#34;&gt;ifelse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;damped&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;d&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
                         &lt;span class=&#34;s&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;seasonal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
           &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;trend&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;seasonal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Drop nonsensical models (these are flagged by `ets` anyway).&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%in%&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;MMA&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;AMN&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;AMA&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;AMM&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                         &lt;span class=&#34;s&#34;&gt;&amp;#34;ANM&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;AAM&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;desc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;damped&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;ets.params&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 19 × 4
##     kind     desc model damped
##    &amp;lt;chr&amp;gt;    &amp;lt;chr&amp;gt; &amp;lt;chr&amp;gt;  &amp;lt;lgl&amp;gt;
## 1    ETS  (A,A,A)   AAA  FALSE
## 2    ETS (A,Ad,A)   AAA   TRUE
## 3    ETS  (A,A,N)   AAN  FALSE
## 4    ETS (A,Ad,N)   AAN   TRUE
## 5    ETS  (A,N,A)   ANA  FALSE
## 6    ETS  (A,N,N)   ANN  FALSE
## 7    ETS  (M,A,A)   MAA  FALSE
## 8    ETS (M,Ad,A)   MAA   TRUE
## 9    ETS  (M,A,M)   MAM  FALSE
## 10   ETS (M,Ad,M)   MAM   TRUE
## 11   ETS  (M,A,N)   MAN  FALSE
## 12   ETS (M,Ad,N)   MAN   TRUE
## 13   ETS  (M,M,M)   MMM  FALSE
## 14   ETS (M,Md,M)   MMM   TRUE
## 15   ETS  (M,M,N)   MMN  FALSE
## 16   ETS (M,Md,N)   MMN   TRUE
## 17   ETS  (M,N,A)   MNA  FALSE
## 18   ETS  (M,N,M)   MNM  FALSE
## 19   ETS  (M,N,N)   MNN  FALSE
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With this set of model parameters in hand, we can create list columns containing
the training data and the function to compute the model (&lt;code&gt;ets&lt;/code&gt; in this case). We
can also wrap up the parameters into a &lt;code&gt;param&lt;/code&gt; list column by using the curious
but useful &lt;code&gt;transpose()&lt;/code&gt; function.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;ets.models&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ets.params&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Add in the training set and the modelling function.&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;replicate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;forecast&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()),&lt;/span&gt;
           &lt;span class=&#34;n&#34;&gt;train&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;replicate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;train&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Create a &amp;#34;param&amp;#34; column to pass to `fn`.&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;purrr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;transpose&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
        &lt;span class=&#34;s&#34;&gt;&amp;#34;y&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;train&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;model&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;damped&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;damped&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;desc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;train&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;ets.models&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 19 × 5
##     kind     desc    train     fn     params
##    &amp;lt;chr&amp;gt;    &amp;lt;chr&amp;gt;   &amp;lt;list&amp;gt; &amp;lt;list&amp;gt;     &amp;lt;list&amp;gt;
## 1    ETS  (A,A,A) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 2    ETS (A,Ad,A) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 3    ETS  (A,A,N) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 4    ETS (A,Ad,N) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 5    ETS  (A,N,A) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 6    ETS  (A,N,N) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 7    ETS  (M,A,A) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 8    ETS (M,Ad,A) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 9    ETS  (M,A,M) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 10   ETS (M,Ad,M) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 11   ETS  (M,A,N) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 12   ETS (M,Ad,N) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 13   ETS  (M,M,M) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 14   ETS (M,Md,M) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 15   ETS  (M,M,N) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 16   ETS (M,Md,N) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 17   ETS  (M,N,A) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 18   ETS  (M,N,M) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
## 19   ETS  (M,N,N) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And now we can make use of &lt;code&gt;invoke_map()&lt;/code&gt; to fit all of these models. I&amp;rsquo;ve also
extracted the AICc values of each for comparison.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;ets.fits&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ets.models&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Fit the models, and extract the AICc.&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fit&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;purrr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;invoke_map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
           &lt;span class=&#34;n&#34;&gt;aicc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;purrr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;map_dbl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;aicc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;arrange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;aicc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;ets.fits&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 19 × 7
##     kind     desc    train     fn     params       fit     aicc
##    &amp;lt;chr&amp;gt;    &amp;lt;chr&amp;gt;   &amp;lt;list&amp;gt; &amp;lt;list&amp;gt;     &amp;lt;list&amp;gt;    &amp;lt;list&amp;gt;    &amp;lt;dbl&amp;gt;
## 1    ETS  (A,N,A) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 4912.794
## 2    ETS  (M,N,M) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 4914.492
## 3    ETS  (A,A,A) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 4923.181
## 4    ETS (A,Ad,A) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 4925.173
## 5    ETS (M,Ad,M) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 4925.813
## 6    ETS (M,Md,M) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 4926.635
## 7    ETS  (M,N,A) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 4928.246
## 8    ETS (M,Ad,A) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 4941.445
## 9    ETS  (M,A,A) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 4942.699
## 10   ETS  (M,A,M) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 4977.796
## 11   ETS  (M,M,M) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 4985.782
## 12   ETS  (M,M,N) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 5283.217
## 13   ETS  (M,N,N) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 5283.227
## 14   ETS  (M,A,N) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 5285.426
## 15   ETS (M,Ad,N) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 5285.783
## 16   ETS (M,Md,N) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 5286.098
## 17   ETS  (A,N,N) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 5301.575
## 18   ETS (A,Ad,N) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 5305.353
## 19   ETS  (A,A,N) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ets&amp;gt; 5308.133
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note that the best-performing model here &amp;mdash; &lt;code&gt;ETS(A,N,A)&lt;/code&gt; &amp;mdash; is the same one
arrived at automatically above.&lt;/p&gt;
&lt;p&gt;We can do the same thing with the ARIMA models: generate a list of model
parameters as a data frame, collect these into a &lt;code&gt;param&lt;/code&gt; list-column, and then
fit the function using &lt;code&gt;invoke_map()&lt;/code&gt;. Unlike ETS, there are an infinite number
of possible ARIMA models. However, we can guess from above that good models will
have low order.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;arima.params&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tidyr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;crossing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ar&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ma&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                &lt;span class=&#34;n&#34;&gt;sar&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sma&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Create a label for the model.&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kind&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;ARIMA&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
           &lt;span class=&#34;n&#34;&gt;desc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;(&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;,&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ma&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;)(&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                         &lt;span class=&#34;n&#34;&gt;sar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;,1,&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sma&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;group_by&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;desc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# This has to be done rowwise to avoid the flattening&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# behaviour of c().&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;do&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;order&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;.$ar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;.$d&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;.$ma&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
       &lt;span class=&#34;n&#34;&gt;seasonal&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;.$sar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;.$sma&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;ungroup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;arima.models&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arima.params&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Add in the training set and the modelling function.&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;replicate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;forecast&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Arima&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()),&lt;/span&gt;
           &lt;span class=&#34;n&#34;&gt;train&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;replicate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;train&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Create a &amp;#34;param&amp;#34; column to pass to `fn`.&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;params&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;purrr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;transpose&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
        &lt;span class=&#34;s&#34;&gt;&amp;#34;y&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;train&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;order&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;order&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;seasonal&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;seasonal&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;desc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;train&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;arima.fits&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arima.models&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Fit the models, and extract the AICc.&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fit&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;purrr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;invoke_map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;params&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
           &lt;span class=&#34;n&#34;&gt;aicc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;purrr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;map_dbl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;aicc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;arrange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;aicc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;arima.fits&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 72 × 7
##     kind           desc    train     fn     params         fit     aicc
##    &amp;lt;chr&amp;gt;          &amp;lt;chr&amp;gt;   &amp;lt;list&amp;gt; &amp;lt;list&amp;gt;     &amp;lt;list&amp;gt;      &amp;lt;list&amp;gt;    &amp;lt;dbl&amp;gt;
## 1  ARIMA (0,2,2)(0,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4157.528
## 2  ARIMA (1,2,1)(0,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4157.796
## 3  ARIMA (0,2,2)(1,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4158.203
## 4  ARIMA (1,2,1)(1,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4158.223
## 5  ARIMA (2,2,1)(0,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4159.600
## 6  ARIMA (1,2,2)(0,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4159.658
## 7  ARIMA (2,2,1)(1,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4160.292
## 8  ARIMA (1,2,2)(1,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4160.306
## 9  ARIMA (0,2,1)(0,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4160.888
## 10 ARIMA (0,2,1)(1,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4161.533
## # ... with 62 more rows
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Since this data frame has the same form as the one used for the ETS models, we
can concatenate them into a master list of models. The &lt;code&gt;forecast()&lt;/code&gt; function is
its namesake package&amp;rsquo;s universal forecasting function. We can use it to add a
column of the two-year forecast for all of these models.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;yyz.forecasts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dplyr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;bind_rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ets.fits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;arima.fits&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;forecast&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;forecast&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;forecast&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;h&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;24&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;arrange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;aicc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;yyz.forecasts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 91 × 8
##     kind           desc    train     fn     params         fit     aicc
##    &amp;lt;chr&amp;gt;          &amp;lt;chr&amp;gt;   &amp;lt;list&amp;gt; &amp;lt;list&amp;gt;     &amp;lt;list&amp;gt;      &amp;lt;list&amp;gt;    &amp;lt;dbl&amp;gt;
## 1  ARIMA (0,2,2)(0,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4157.528
## 2  ARIMA (1,2,1)(0,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4157.796
## 3  ARIMA (0,2,2)(1,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4158.203
## 4  ARIMA (1,2,1)(1,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4158.223
## 5  ARIMA (2,2,1)(0,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4159.600
## 6  ARIMA (1,2,2)(0,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4159.658
## 7  ARIMA (2,2,1)(1,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4160.292
## 8  ARIMA (1,2,2)(1,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4160.306
## 9  ARIMA (0,2,1)(0,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4160.888
## 10 ARIMA (0,2,1)(1,1,1) &amp;lt;S3: ts&amp;gt;  &amp;lt;fun&amp;gt; &amp;lt;list [3]&amp;gt; &amp;lt;S3: ARIMA&amp;gt; 4161.533
## # ... with 81 more rows, and 1 more variables: forecast &amp;lt;list&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;measuring-forecast-accuracy&#34;&gt;Measuring Forecast Accuracy&lt;/h2&gt;
&lt;p&gt;The AICc is not a direct measure of forecast accuracy. Traditional root mean
squared error (RMSE) and mean absolute error (MAE) are both options, although
the author of the &lt;strong&gt;forecast&lt;/strong&gt; package recommends mean absolute scaled error
(MASE). The package provides the &lt;code&gt;accuracy()&lt;/code&gt; function to compute all of these
measures (and a few others) for any &lt;code&gt;forecast&lt;/code&gt; object, but unfortunately it
returns a matrix with meaningful row names, which would be hard to wrap up
inside a list column. What we need is an API that returns a data frame.&lt;/p&gt;
&lt;p&gt;It turns out that &lt;a href=&#34;https://github.com/tidyverse/broom&#34;&gt;there is a project&lt;/a&gt;
devoted specifically to this problem. The &lt;strong&gt;broom&lt;/strong&gt; package provides a standard
interface for &amp;ldquo;tidying&amp;rdquo; model summaries using the S3 &lt;code&gt;glance()&lt;/code&gt; method. At the
time of writing, the package doesn&amp;rsquo;t contain an implementation for &lt;code&gt;forecast&lt;/code&gt;
objects, but it isn&amp;rsquo;t too hard to write one using the output of
&lt;code&gt;forecast::accuracy()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;glance.forecast&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;newdata&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;is.null&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;newdata&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;forecast&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;accuracy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;tibble&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;as_tibble&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;acc[1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;forecast&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;accuracy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;newdata&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;tibble&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;as_tibble&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;acc[2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Format the names of the measures to suit broom::glance().&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;names&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;tolower&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;names&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;if &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;names&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;names&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;[8]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;thielsu&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This can now be combined with &lt;code&gt;tidyr::unnest()&lt;/code&gt; to get columns of RMSE, MAE, MASE,
and so on using &lt;code&gt;map()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;yyz.forecasts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;glance&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;forecast&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;broom&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;glance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;unnest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;glance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;arrange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rmse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mae&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;kind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;desc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rmse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mae&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 91 × 5
##     kind           desc     rmse      mae      mase
##    &amp;lt;chr&amp;gt;          &amp;lt;chr&amp;gt;    &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;     &amp;lt;dbl&amp;gt;
## 1  ARIMA (2,1,2)(1,1,1) 76061.98 51352.61 0.3289412
## 2    ETS        (M,N,M) 76143.55 49990.36 0.3202153
## 3    ETS       (M,Ad,M) 76387.04 50008.08 0.3203288
## 4    ETS       (M,Md,M) 76595.67 50443.22 0.3231161
## 5    ETS        (A,N,A) 79047.80 53876.34 0.3451071
## 6    ETS        (M,N,A) 79174.58 54396.73 0.3484405
## 7  ARIMA (2,2,1)(1,1,1) 79294.88 53378.97 0.3419212
## 8  ARIMA (1,2,2)(1,1,1) 79303.39 53397.52 0.3420400
## 9  ARIMA (1,1,2)(1,1,1) 79305.25 53167.62 0.3405674
## 10 ARIMA (0,2,2)(1,1,1) 79307.55 53368.28 0.3418527
## # ... with 81 more rows
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Each accuracy measure provides a slightly different ranking of models. Does this
list lay out which model is best? If what you are after is forecast accuracy,
the answer is no. It is overwhelmingly likely that some models which perform
exceptionally well on this training data may do poorly when confronted with new
data. This is precisely why we left a &amp;ldquo;test&amp;rdquo; series aside earlier.&lt;/p&gt;
&lt;h2 id=&#34;measuring-out-of-sample-performance-using-a-test-set&#34;&gt;Measuring Out-of-Sample Performance Using a Test Set&lt;/h2&gt;
&lt;p&gt;You might have noticed above that the &lt;code&gt;broom::glance()&lt;/code&gt; implementation above
accepts a &lt;code&gt;newdata&lt;/code&gt; parameter for out-of-sample accuracy assessment. We can
pass the &lt;code&gt;test&lt;/code&gt; data left aside at the start of the post in the same fashion as
above, and lay out the in-sample and out-of-sample measures side by side.&lt;/p&gt;
&lt;p&gt;This is also a great opportunity for visual exploration! I&amp;rsquo;m going to use the
&lt;strong&gt;ggrepel&lt;/strong&gt; package to add cleaner labels to the top in-sample and test-set
performers, although you can also substitute the built-in
&lt;code&gt;ggplot2::geom_label()&lt;/code&gt; here.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;perf&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;yyz.forecasts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;test&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;replicate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;test&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()),&lt;/span&gt;
           &lt;span class=&#34;n&#34;&gt;glance&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;map2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;forecast&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;test&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;broom&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;glance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;tidyr&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;unnest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;glance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Pull out the out-of-sample RMSE, MAE, and MASE.&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;desc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;oos.rmse&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rmse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
           &lt;span class=&#34;n&#34;&gt;oos.mae&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mae&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;oos.mase&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Join the in-sample RMSE, MAE, and MASE columns.&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;inner_join&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;by&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;kind&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;desc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;rename&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;is.rmse&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rmse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;is.mae&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mae&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;is.mase&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;arrange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;oos.rmse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;is.rmse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;desc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;is.rmse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;oos.rmse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;is.mae&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;oos.mae&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
           &lt;span class=&#34;n&#34;&gt;is.mase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;oos.mase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Find the top four models by in-sample and out-of-sample MASE.&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;top.perf&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;perf&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;top.is&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;rank&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;is.mase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;top.oos&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;rank&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;oos.mase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;top.is&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;top.oos&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ggrepel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Graph in-sample vs. out-of-sample MASE for the top 50% of each.&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;perf&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;oos.mase&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;quantile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;oos.mase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;
           &lt;span class=&#34;n&#34;&gt;is.mase&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;quantile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;is.mase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;ggplot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;oos.mase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;is.mase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_point&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;kind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Vertical/horizontal lines at the minimum MASE for each sample.&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_vline&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;xintercept&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;min&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;is.mase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;
               &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;gray50&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_hline&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;yintercept&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;min&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;oos.mase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;
               &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;gray50&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Label the top models.&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ggrepel&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;geom_label_repel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;desc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;
                             &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;segment.colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;gray50&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                             &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;top.perf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;labs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;In-Sample MASE&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Out-of-Sample MASE&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Family&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk forecast-perf-plot](/images/r-6c067198/forecast-perf-plot-1.png)
&lt;/center&gt;
&lt;p&gt;This plot reveals some interesting patterns. First, it looks as though some of
the multiplicative ETS models do quite well on measures of in-sample accuracy,
but poorly when confronted with the test set (top left). Second, there is an
&lt;code&gt;ETS (M,M,M)&lt;/code&gt; model that does very well on the test set, but quite unremarkably
on the training data (bottom right). To mirror this, the best in-sample
performer has only middling test set performance (middle right). Third, the
models that do well on both measures tend to be ARIMA models of low order
(bottom left).&lt;/p&gt;
&lt;p&gt;What conclusions can we draw from this? Test set performance isn&amp;rsquo;t the ultimate
arbiter of forecasting performance. As I mentioned above, you can overfit to
this specific test set, which is probably what is going on with the high-flying
&lt;code&gt;ETS (M,M,M)&lt;/code&gt; model. The low-order ARIMA models strike me as a better choice.&lt;/p&gt;
&lt;h2 id=&#34;forecasting-finally&#34;&gt;Forecasting, Finally&lt;/h2&gt;
&lt;p&gt;Okay, now that we&amp;rsquo;ve settled on a model, it&amp;rsquo;s time to actually forecast the
series forward.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;passengers.fc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;passengers&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;Arima&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;order&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;seasonal&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;forecast&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;h&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;24&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;level&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;95&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All forecast accuracy measures aside, there&amp;rsquo;s no substitute for the sense of
model performance one gets by visual inspection. The &lt;code&gt;forecast&lt;/code&gt; object has an
implementation for the &lt;code&gt;ggplot2::autoplot()&lt;/code&gt; S3 method in addition to the base
graphics &lt;code&gt;plot()&lt;/code&gt;, so we can get a &lt;code&gt;ggplot2&lt;/code&gt; graphic very easily. The
&lt;code&gt;autoplot()&lt;/code&gt; output doesn&amp;rsquo;t include the fitted values by default, but we can add
them manually:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;autoplot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;passengers.fc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_path&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;as.vector&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;passengers.fc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fitted&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
                  &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;passengers.fc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fitted&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;
              &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;red&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk forecast-plot](/images/r-6c067198/forecast-plot-1.png)
&lt;/center&gt;
&lt;p&gt;It looks like the model fits the data quite well, aside from some trouble
around 2003. The forecast output also gives us a nice story to tell: monthly
passengers at YYZ looks likely to break 5 million for the first time in summer
2017.&lt;/p&gt;
&lt;p&gt;With this story in hand, you can wrap up the output of &lt;code&gt;autoplot()&lt;/code&gt; in a pretty
theme, add some bells and whistles, and publish a nice little graphic on this
data. The code below generates the plot at the top of this post:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;millions&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1e6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;digits&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;m&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;autoplot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;passengers.fc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;shadecols&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;#cccccc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;#eeeeee&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_segment&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5e6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;yend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5e6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2016.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2019&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
                 &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;#888888&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;scale_x_continuous&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;breaks&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;seq&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2018&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;by&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;expand&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;scale_y_continuous&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;labels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;millions&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme_minimal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;legend.position&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;panel.grid.minor&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_blank&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;panel.grid.major.x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_blank&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;axis.ticks.x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;#333333&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;axis.ticks.length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;grid&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;units&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;pt&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;text&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;family&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Arial Narrow&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;plot.title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;face&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;bold&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;labs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Monthly Passengers at Pearson International Airport&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                       &lt;span class=&#34;s&#34;&gt;&amp;#34;to Top 5 Million in 2017&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;subtitle&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Incoming and outgoing passengers in millions,&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                          &lt;span class=&#34;s&#34;&gt;&amp;#34;with forecast data in blue.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;caption&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;A. Jacobs :: unconj.ca\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                         &lt;span class=&#34;s&#34;&gt;&amp;#34;Data: Toronto Open Data (2016)\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                         &lt;span class=&#34;s&#34;&gt;&amp;#34;You may redistribute this graphic under&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                         &lt;span class=&#34;s&#34;&gt;&amp;#34;the terms of the CC-by-SA license.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## Scale for &#39;x&#39; is already present. Adding another scale for &#39;x&#39;, which
## will replace the existing scale.
&lt;/code&gt;&lt;/pre&gt;&lt;center&gt;
![plot of chunk narrative-plot](/images/r-6c067198/narrative-plot-1.png)
&lt;/center&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;The author of the &lt;strong&gt;forecast&lt;/strong&gt; package &lt;a href=&#34;http://robjhyndman.com/hyndsight/tscv/&#34;&gt;has recently revealed&lt;/a&gt;
that future versions of the package will provide support for computing
cross validation-like residuals. I may discuss incorporating this function
in a future post. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
    </content>
    
    
    <category term="data"/>
    <category term="r"/>
  </entry>
  <entry>
    <title type="html">Using hledger with ledger-mode</title>
    
    <link href="https://unconj.ca/blog/using-hledger-with-ledger-mode.html" rel="alternate"/>
    <published>2017-02-10T00:00:00Z</published>
    
    
    <updated>2017-02-10T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2017-02-10:blog/using-hledger-with-ledger-mode.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;Last summer I landed &lt;a href=&#34;https://github.com/ledger/ledger-mode/commits?author=atheriel&#34;&gt;a few patches&lt;/a&gt;
in Emacs&amp;rsquo;s &lt;code&gt;ledger-mode&lt;/code&gt; that make it easier to use with alternative
implementations of &lt;a href=&#34;http://ledger-cli.org/&#34;&gt;Ledger&lt;/a&gt;, such as &lt;a href=&#34;http://hledger.org/&#34;&gt;hledger&lt;/a&gt;.
Since the competing &lt;code&gt;hledger-mode&lt;/code&gt; garnered some attention
&lt;a href=&#34;https://news.ycombinator.com/item?id=13566147&#34;&gt;last week on Hacker News&lt;/a&gt;, I
thought these new features might be worth highlighting to those interested in
plain-text accounting in Emacs.&lt;/p&gt;
&lt;h2 id=&#34;why-choose-ledger-mode-over-hledger-mode&#34;&gt;Why choose ledger-mode over hledger-mode?&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ledger-mode&lt;/code&gt; is the original major mode for the Ledger file format, first
penned by current Emacs maintainer and Ledger author John Wiegley himself. It&amp;rsquo;s
generally less opinionated than the newer &lt;code&gt;hledger-mode&lt;/code&gt; and is less tied to the
specifics of hledger&amp;rsquo;s command line output, but each has some nice features the
other lacks.&lt;/p&gt;
&lt;p&gt;Unfortunately, up until last summer certain commands (such as register reports)
expected command line flags that hledger lacks, and so several things were
broken if you tried to use hledger to run your reports instead.&lt;/p&gt;
&lt;p&gt;To summarise the changes, you can now use hledger pretty seamlessly by adding
the following somewhere in your &lt;code&gt;init.el&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span class=&#34;c1&#34;&gt;;; Required to use hledger instead of ledger itself.&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;setq&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ledger-mode-should-check-version&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;nil&lt;/span&gt;
      &lt;span class=&#34;nv&#34;&gt;ledger-report-links-in-register&lt;/span&gt; &lt;span class=&#34;no&#34;&gt;nil&lt;/span&gt;
      &lt;span class=&#34;nv&#34;&gt;ledger-binary-path&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;hledger&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you write your own reports, you might also be interested in the new
&lt;code&gt;%(binary)&lt;/code&gt; format specifier (demo below), which will substitute in whatever you
have set as the binary path. This makes it a little easier to switch back and
forth, too.&lt;/p&gt;
&lt;h2 id=&#34;why-use-hledger-at-all&#34;&gt;Why use hledger at all?&lt;/h2&gt;
&lt;p&gt;Again, this is mostly a matter of taste, but hledger and Ledger do offer
&lt;a href=&#34;http://hledger.org/faq.html#hledger-and-ledger&#34;&gt;slightly different features&lt;/a&gt;.
I&amp;rsquo;m particularly fond of hledger&amp;rsquo;s column format for periodic reports. I find it
useful to compare expenses from one month to the next, and this makes it easy to
do so.&lt;/p&gt;
&lt;p&gt;For example, you could add the following to your &lt;code&gt;ledger-reports&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;monthly expenses&amp;#34;&lt;/span&gt;
 &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;concat&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;%(binary) -f %(ledger-file) balance expenses&amp;#34;&lt;/span&gt;
         &lt;span class=&#34;s&#34;&gt;&amp;#34;--tree --no-total --row-total --average --monthly&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It should produce output like the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Balance changes in 2016/12/01-2017/02/28:

               ||  2016/12  2017/01  2017/02    Total  Average 
===============++==============================================
 Expenses      || $1977.97 $1713.99 $1402.97 $5094.93 $1698.31 
   Bills       ||   $90.00   $90.00   $90.00  $270.00   $90.00 
     Internet  ||   $35.00   $35.00   $35.00  $105.00   $35.00 
     Phone     ||   $55.00   $55.00   $55.00  $165.00   $55.00 
   Cash        ||   $41.00   $27.50   $60.00  $128.50   $42.83 
   Food        ||  $549.21  $679.52  $443.09 $1671.82  $557.27 
     Dining    ||  $247.67  $302.31  $186.77  $736.75  $245.58 
     Groceries ||  $301.54  $377.21  $256.32  $935.07  $311.69 
   FunTimes    ||  $177.76  $210.21  $145.56  $533.53  $177.84 
   Misc        ||  $500.00   $86.76   $44.32  $631.08  $210.36 
     Books     ||        0   $34.99        0   $34.99   $11.66 
     Car       ||        0   $51.77   $44.32   $96.09   $32.03 
     Gifts     ||  $340.00        0        0  $340.00  $113.33 
     Travel    ||  $160.00        0        0  $160.00   $53.33 
   Rent        ||  $500.00  $500.00  $500.00 $1500.00  $500.00 
   Transit     ||  $120.00  $120.00  $120.00  $360.00  $120.00 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(No, this is not my real data.)&lt;/p&gt;
&lt;p&gt;You can get &lt;code&gt;ledger-mode&lt;/code&gt; on &lt;a href=&#34;https://melpa.org/#/ledger-mode&#34;&gt;MELPA&lt;/a&gt;.&lt;/p&gt;
    </content>
    
    
    <category term="emacs"/>
  </entry>
  <entry>
    <title type="html">An Update to the Choropleth Post</title>
    
    <link href="https://unconj.ca/blog/an-update-to-the-choropleth-post.html" rel="alternate"/>
    <published>2017-02-06T00:00:00Z</published>
    
    
    <updated>2017-02-06T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2017-02-06:blog/an-update-to-the-choropleth-post.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;A few years ago I published a post outlining &lt;a href=&#34;./choropleth-maps-with-r-and-ggplot2.html&#34;&gt;how to make nice-looking
choropleth maps in R&lt;/a&gt;,
and this piece still draws a reasonable share of my hits each month.
Unfortunately, some of the techniques I used at the time are now quite out of
date, and I was starting to feel bad for anyone taking my advice.&lt;/p&gt;
&lt;p&gt;As of today the post has received a makeover, and takes a more modern approach.
For any returning readers, the changes are explained in a series of HTML &lt;code&gt;&amp;lt;ins&amp;gt;&lt;/code&gt;
tags &amp;mdash; which I have only recently discovered.&lt;/p&gt;
    </content>
    
    
    <category term="data"/>
    <category term="meta"/>
    <category term="r"/>
    <category term="visualization"/>
  </entry>
  <entry>
    <title type="html">When do RcppEigen &#39;expressions&#39; matter?</title>
    
    <link href="https://unconj.ca/blog/when-do-rcppeigen-expressions-matter.html" rel="alternate"/>
    <published>2016-09-27T00:00:00Z</published>
    
    
    <updated>2016-09-27T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2016-09-27:blog/when-do-rcppeigen-expressions-matter.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;Some time ago I discovered a very surprising performance issue while working
with the &lt;a href=&#34;http://dirk.eddelbuettel.com/code/rcpp.html&#34;&gt;&lt;code&gt;Rcpp&lt;/code&gt;&lt;/a&gt; package, and
thought I&amp;rsquo;d share the example I discovered.&lt;/p&gt;
&lt;p&gt;At the time, I was interested in computing the vector of
&lt;a href=&#34;https://en.wikipedia.org/wiki/Leverage_(statistics)&#34;&gt;leverages&lt;/a&gt; for a linear
model (which you need for certain covariance matrices). This vector is
constructed from the diagonal elements of the &amp;ldquo;hat&amp;rdquo; (or &amp;ldquo;influence&amp;rdquo;) matrix &lt;em&gt;H&lt;/em&gt;,
such that&lt;/p&gt;
&lt;p&gt;$$ H = X (X^T X)^{-1} X^T$$&lt;/p&gt;
&lt;p&gt;In base R, you might write the following function to compute this for you:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;leverage&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;diag&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;X&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%*%&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;solve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%*%&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%*%&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In other words, it&amp;rsquo;s a simple matrix calculation: the exact kind of thing you
might want to optimize with &lt;code&gt;Rcpp&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;computing-leverages-using-rcpp&#34;&gt;Computing Leverages using Rcpp&lt;/h2&gt;
&lt;p&gt;For fun, I decided to implement this same computation in &lt;code&gt;Rcpp&lt;/code&gt; code,
specifically using the &lt;a href=&#34;https://github.com/RcppCore/RcppEigen&#34;&gt;&lt;code&gt;RcppEigen&lt;/code&gt;&lt;/a&gt;
package, since having matrix classes is really nice in this case.&lt;/p&gt;
&lt;p&gt;My first version looked like the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// [[Rcpp::depends(RcppEigen)]]
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;RcppEigen.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;namespace&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Rcpp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Eigen&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Eigen&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;VectorXd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Eigen&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MatrixXd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;typedef&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Map&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MatrixXd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MapMatd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;// [[Rcpp::export]]
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;VectorXd&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;leverage_cpp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NumericMatrix&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;XX&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MapMatd&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MapMatd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;XX&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MatrixXd&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;H&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;X&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;adjoint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;inverse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;adjoint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;H&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;diagonal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But later I was feeling strongly about brevity, and opted for this instead:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// [[Rcpp::export]]
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;VectorXd&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;leverage_cpp_short&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NumericMatrix&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;XX&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MapMatd&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;as&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MapMatd&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;XX&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;X&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;adjoint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;inverse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;adjoint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;diagonal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can load these into R by using the &lt;code&gt;sourceCpp&lt;/code&gt; function&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;RcppEigen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;#sourceCpp(&amp;#34;code above&amp;#34;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And we can confirm that they produce the same results as the pure R version by
using one of the built-in data sets, called &lt;code&gt;attitude&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;attitude&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;package&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;datasets&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;lm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rating&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;~&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;.,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;attitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;X&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;model.matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;all.equal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;leverage&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;leverage_cpp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;names for target but not for current&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;all.equal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;leverage&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;leverage_cpp_short&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] &amp;quot;names for target but not for current&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Notice that &lt;code&gt;RcppEigen&lt;/code&gt; does not set the &lt;code&gt;names&lt;/code&gt; of these vectors in the same
way that &lt;code&gt;diag&lt;/code&gt; does, so the vectors are not precisely identical.&lt;/p&gt;
&lt;h2 id=&#34;benchmarking-r-against-rcpp-functions&#34;&gt;Benchmarking R Against Rcpp Functions&lt;/h2&gt;
&lt;p&gt;The first thing that comes to mind when rewriting any R code using &lt;code&gt;Rcpp&lt;/code&gt; is:
how much faster is it? The brillaint &lt;code&gt;microbenchmark&lt;/code&gt; package provides an easy
way to test this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;microbenchmark&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ggplot2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
 
&lt;span class=&#34;c1&#34;&gt;# Benchmark the results.&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;test&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;microbenchmark&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;leverage_r&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;leverage&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;leverage_cpp&lt;/span&gt;       &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;leverage_cpp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;leverage_cpp_short&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;leverage_cpp_short&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;X&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;times&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1000L&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## Unit: microseconds
##                expr    min     lq      mean median      uq      max neval
##          leverage_r 73.378 87.126 103.80609 91.880 100.933 3683.704  1000
##        leverage_cpp 10.542 13.503  18.59291 16.767  22.383   83.863  1000
##  leverage_cpp_short  7.857  9.182  12.03752 10.254  13.728  128.881  1000
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;microbenchmark&lt;/code&gt; package also supports the &lt;code&gt;ggplot2::autoplot&lt;/code&gt; API, if you
prefer a plot:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ggplot2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;ggplot2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;autoplot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;test&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk unnamed-chunk-5](./images/r-7797a4c4/unnamed-chunk-5-1.png)
&lt;/center&gt;
&lt;p&gt;As expected, the &lt;code&gt;Rcpp&lt;/code&gt; code is 5 to 10 times faster, even on this small data
set. But there&amp;rsquo;s a small mystery here as well: why is the second piece of C++
code faster than the first?&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re operating in R world, it&amp;rsquo;s not all that surprising that two different
pieces of code to do the same thing have different performance characteristics.
This is, after all, the main reason that the &lt;code&gt;microbenchmark&lt;/code&gt; package comes in
handy.&lt;/p&gt;
&lt;p&gt;But since C++ is a compiled language, I generally expect the compiler to figure
out that two pieces of code that do the same thing ought to boil down to the
same machine code. Why is that not the case here?&lt;/p&gt;
&lt;p&gt;The answer is probably to do with how Eigen (the library that &lt;code&gt;RcppEigen&lt;/code&gt; wraps)
&lt;a href=&#34;http://eigen.tuxfamily.org/dox/TopicLazyEvaluation.html&#34;&gt;defers computation of an expression&lt;/a&gt;
in intelligent ways. My guess is that Eigen figures out at compile time that
there&amp;rsquo;s a really simple loop for computing this matrix expression, and pares
your high-level description down to a simple statement. By breaking the
computation in to two parts (as in the first C++ function), you hamper the
ability of the library (not the compiler!) to help you out.&lt;/p&gt;
&lt;p&gt;This whole experience has made me much more cautious about the C++ code that I
write for R, to the point that I&amp;rsquo;m now prone to writing the function a number of
different ways, and then doing some tests with &lt;code&gt;microbenchmark&lt;/code&gt; to see what ends
up being faster. Of course, it&amp;rsquo;s arguable that I should have been taking that
kind of empirical approach to begin with.&lt;/p&gt;
&lt;p&gt;If anyone can shed some light on this by looking at the assembly output (which
is beyond my own abilities), I would be quite grateful.&lt;/p&gt;
&lt;script src=&#39;https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML&#39;&gt;&lt;/script&gt;
    </content>
    
    
    <category term="r"/>
    <category term="rcpp"/>
  </entry>
  <entry>
    <title type="html">Exporting Clock Entries from org-mode to CSV</title>
    
    <link href="https://unconj.ca/blog/exporting-clock-entries-from-org-mode-to-csv.html" rel="alternate"/>
    <published>2016-09-05T00:00:00Z</published>
    
    
    <updated>2016-09-05T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2016-09-05:blog/exporting-clock-entries-from-org-mode-to-csv.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;If you&amp;rsquo;ve used the clocking features of &lt;code&gt;org-mode&lt;/code&gt;, you&amp;rsquo;re no doubt familiar
with the &lt;a href=&#34;http://orgmode.org/manual/The-clock-table.html&#34;&gt;clock table&lt;/a&gt;, which
allows you to summarise time spent on different tasks. This is great for getting
an overview of projects, but it&amp;rsquo;s not a very flexible tool if you want to have a
more detailed idea of how you spend your time.&lt;/p&gt;
&lt;p&gt;At this point I&amp;rsquo;ve accumulated about a year&amp;rsquo;s worth of clocked work time in org,
and while clock tables have served me well so far, eventually I just wanted to
get my data into R or Python for more minute analysis, and charts like the
following:&lt;/p&gt;
&lt;center&gt;
![Calendar heatmap example](/images/calendar-clock-heatmap.png)
&lt;/center&gt;
&lt;p&gt;However, I haven&amp;rsquo;t come across a reliable&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; way to get individual clock entries
out of &lt;code&gt;org-mode&lt;/code&gt; files and into a more widely readable format. So I&amp;rsquo;ve written
one.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;org-clock-csv&lt;/code&gt; package,
&lt;a href=&#34;https://github.com/atheriel/org-clock-csv&#34;&gt;available on GitHub&lt;/a&gt; and through
&lt;a href=&#34;http://melpa.org/#/org-clock-csv&#34;&gt;MELPA&lt;/a&gt;, parses all of the clock entries in an
&lt;code&gt;org-mode&lt;/code&gt; file and exports them to CSV format. At present the columns include
start and end dates, the task&amp;rsquo;s category, effort, and tags. Habits are also
given a flag.&lt;/p&gt;
&lt;p&gt;You can invoke the parser by calling &lt;code&gt;org-clock-csv&lt;/code&gt; in interactive mode, in
which case it will parse whatever you&amp;rsquo;ve got in &lt;code&gt;org-agenda-files&lt;/code&gt; and pop up a
buffer with the results. The function can also be called from lisp code with a
file argument, and there&amp;rsquo;s an &lt;code&gt;org-clock-csv-batch&lt;/code&gt; version that will dump the
CSV results to standard output (for use with Emacs in batch mode).&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re looking for inspiration on what to do with your shiny new data set,
&lt;a href=&#34;http://jdlm.info/articles/2016/07/04/cto-time-minute-by-minute.html&#34;&gt;here&amp;rsquo;s a recent post&lt;/a&gt;
(though it&amp;rsquo;s not &lt;code&gt;org-mode&lt;/code&gt; based) that poses some good questions.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;I did find the in-progress R package
&lt;a href=&#34;https://github.com/mutbuerger/orgclockr&#34;&gt;orgclockr&lt;/a&gt;, but its home-grown org
parser (in R) failed on my files. Since the
&lt;a href=&#34;http://orgmode.org/worg/dev/org-element-api.html&#34;&gt;best org parser&lt;/a&gt; is
already avaiable in Emacs, it made more sense to me to write an Emacs
package that outputs a universal format. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
    </content>
    
    
    <category term="data"/>
    <category term="emacs"/>
    <category term="projects"/>
  </entry>
  <entry>
    <title type="html">Custom Hexbin Functions with ggplot</title>
    
    <link href="https://unconj.ca/blog/custom-hexbin-functions-with-ggplot.html" rel="alternate"/>
    <published>2016-08-13T00:00:00Z</published>
    
    
    <updated>2016-08-13T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2016-08-13:blog/custom-hexbin-functions-with-ggplot.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;Recently, I wanted to create a map similar to &lt;a href=&#34;http://spatial.ly/2013/07/interactive-crime-map-london/&#34;&gt;James Cheshire&amp;rsquo;s crime map of London&lt;/a&gt;,
which shows the most common crimes commited in a rectangular grid of points laid
over London. Instead of using a rectangular grid, I wanted to use hexbins, but
it turns out that &lt;code&gt;ggplot&lt;/code&gt; needs a bit of prodding to do anything other than
simply count the number of observations in each bin.&lt;/p&gt;
&lt;p&gt;At the time I couldn&amp;rsquo;t find a good tutorial on writing custom hexbin functions,
so this post is a reasonably thorough explanation of what I&amp;rsquo;ve made work.&lt;/p&gt;
&lt;h2 id=&#34;getting-spatial-data&#34;&gt;Getting Spatial Data&lt;/h2&gt;
&lt;p&gt;To get these examples up and running, you&amp;rsquo;ll need some spatial data. I&amp;rsquo;m going
to use something similar to the data used in the original crime map of London:
crimes reported to the Metropolitan Police Department (of London) from May 2012
to April 2013. You can get the exact same extract I have used from the excellent
&lt;code&gt;data.police.uk&lt;/code&gt; website by following &lt;a href=&#34;https://data.police.uk/data/fetch/00f9f79f-3887-4dba-b21c-2484f4b05a55/&#34;&gt;this link&lt;/a&gt;.
The files come in one-month increments, each in their own folder. There are a
number of interesting columns, but for our purposes we only need the coordinates
and the type of crime. I&amp;rsquo;ve appended a quick bit of code to concatenate all of
them together and extract the relevant columns at the end of this post.&lt;/p&gt;
&lt;p&gt;You will also need a fairly recent (post version 2.0) of &lt;code&gt;ggplot2&lt;/code&gt;. To use
&lt;code&gt;geom_hex&lt;/code&gt; and related functions, you will also require the &lt;code&gt;hexbin&lt;/code&gt; package,
which I&amp;rsquo;ve loaded explicitly here. I&amp;rsquo;m personally a fan of &lt;code&gt;dplyr&lt;/code&gt; and the &lt;code&gt;%&amp;gt;%&lt;/code&gt;
operator, but its use here is purely to make working with the data easier.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dplyr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;warn.conflicts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hexbin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ggplot2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The data looks as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# load(&amp;#34;path/to/crimes.rda&amp;#34;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 10 x 5
##     Year Month Longitude Latitude                 Crime
##    &amp;lt;int&amp;gt; &amp;lt;int&amp;gt;     &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt;                &amp;lt;fctr&amp;gt;
## 1   2012     5  0.135866 51.58734 Anti-social behaviour
## 2   2012     5  0.134947 51.58806 Anti-social behaviour
## 3   2012     5  0.135866 51.58734 Anti-social behaviour
## 4   2012     5  0.134947 51.58806 Anti-social behaviour
## 5   2012     5  0.137065 51.58367 Anti-social behaviour
## 6   2012     5  0.134947 51.58806 Anti-social behaviour
## 7   2012     5  0.140192 51.58231 Anti-social behaviour
## 8   2012     5  0.134947 51.58806 Anti-social behaviour
## 9   2012     5  0.134947 51.58806 Anti-social behaviour
## 10  2012     5  0.134947 51.58806 Anti-social behaviour
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;creating-a-basic-spatial-hexbin-map&#34;&gt;Creating a Basic Spatial Hexbin Map&lt;/h2&gt;
&lt;p&gt;To start with, we can produce a traditional hexbin overlaid on a basemap (that
is, using something like Open Street Map or Google Maps as a &amp;ldquo;background&amp;rdquo;). The
&lt;code&gt;ggmap&lt;/code&gt; package is a handy way to get a basemap into your &lt;code&gt;ggplot&lt;/code&gt; maps. You can
get a basemap for London (as a &lt;code&gt;ggplot&lt;/code&gt; object) as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ggmap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# These are approximate coordinates for London.&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;london.ish&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;`left`&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;`bottom`&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;51.4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;`right`&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;`top`&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;51.6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;london.map&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ggmap&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;get_map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;location&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;london.ish&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                             &lt;span class=&#34;n&#34;&gt;maptype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;toner&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;source&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;stamen&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;basemap&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ggmap&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;ggmap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;london.map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;coord_equal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;labs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axis.text&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_blank&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# The data set actually contains a lot of crime reports from outside&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# of London itself. We&amp;#39;re not interested in these observations.&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Longitude&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;london.ish[1]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
           &lt;span class=&#34;n&#34;&gt;Longitude&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;london.ish[3]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
           &lt;span class=&#34;n&#34;&gt;Latitude&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;london.ish[2]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
           &lt;span class=&#34;n&#34;&gt;Latitude&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;london.ish[4]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which allows us to create a nice, traditional hexbin map:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;basic.hexmap&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;basemap&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_hex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Longitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Latitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                 &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cut&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;..value..&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;250&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                         &lt;span class=&#34;m&#34;&gt;1500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;Inf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))),&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bins&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.75&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;scale_fill_brewer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;palette&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;OrRd&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                      &lt;span class=&#34;n&#34;&gt;labels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;lt;100&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;100-250&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;250-500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                 &lt;span class=&#34;s&#34;&gt;&amp;#34;500-1000&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;1000-1500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                 &lt;span class=&#34;s&#34;&gt;&amp;#34;1500-2000&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;2000-2500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                 &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;gt;2500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;labs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Reported Crimes in London, by Location (2012-2013)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;basic.hexmap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk unnamed-chunk-4](./images/r-b6720d/unnamed-chunk-4-1.png)
&lt;/center&gt;
&lt;p&gt;I&amp;rsquo;ve binned the count data so that the map is a little more informative. (You
can read more about using the &lt;code&gt;cut&lt;/code&gt; function for this in &lt;a href=&#34;./not-all-population-maps-are-boring.html&#34;&gt;my earlier post on hexbins&lt;/a&gt;.)
If you look carefully you might notice that there are very few crimes in the
City of London &amp;mdash; I&amp;rsquo;m assuming that this is because they have their own police
force.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;geom_hex&lt;/code&gt; geometry works by using &lt;code&gt;stat_bin_hex&lt;/code&gt; to transform the source
data frame into another data frame with binned data. (This is where the magic
&lt;code&gt;..value..&lt;/code&gt; aesthetic that I used above comes from: it refers to a column in the
data frame that &lt;code&gt;stat_bin_hex&lt;/code&gt; outputs.) In fact you can use the statistic
directly to do some interesting things. Say, by using dots instead of hexagons,
but still maintaining the hexagonal tiling:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;dot.hexmap&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;basemap&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;stat_bin_hex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Longitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Latitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                     &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cut&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;..value..&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;250&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                               &lt;span class=&#34;m&#34;&gt;1500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;Inf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))),&lt;/span&gt;
                 &lt;span class=&#34;n&#34;&gt;geom&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;point&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bins&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.75&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                 &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;scale_colour_brewer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;palette&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;OrRd&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                        &lt;span class=&#34;n&#34;&gt;labels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;lt;100&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;100-250&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;250-500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                   &lt;span class=&#34;s&#34;&gt;&amp;#34;500-1000&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;1000-1500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                   &lt;span class=&#34;s&#34;&gt;&amp;#34;1500-2000&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;2000-2500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                   &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;gt;2500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;labs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Reported Crimes in London, by Location (2012-2013)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dot.hexmap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk unnamed-chunk-5](./images/r-b6720d/unnamed-chunk-5-1.png)
&lt;/center&gt;
&lt;p&gt;In fact this is precisely what the original crime map of London does &amp;mdash; only
with rectangular binning instead of hexagonal binning. Since Cheshire is a
&lt;a href=&#34;http://spatial.ly/2012/02/great-maps-ggplot2/&#34;&gt;self-admitted ggplot2 user himself&lt;/a&gt;,
I&amp;rsquo;m assuming the original map used &lt;code&gt;stat_bin_2d&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note that &lt;code&gt;stat_bin_hex&lt;/code&gt; gets a little confused when you use a different
geometry, which is why I&amp;rsquo;ve explicitly set &lt;code&gt;fill = NULL&lt;/code&gt; here. You get strange
legends otherwise.&lt;/p&gt;
&lt;h2 id=&#34;using-custom-binning-functions&#34;&gt;Using Custom Binning Functions&lt;/h2&gt;
&lt;p&gt;But what if we want to do something &lt;em&gt;other&lt;/em&gt; than just count up the number of
crimes in each hexagon? Suppose that in our data set, each row corresponded to
an arbitrary number of crimes of a given type at a given location. In other
words, each observation has a weight accompanying it. We can&amp;rsquo;t really use
&lt;code&gt;stat_bin_hex&lt;/code&gt; for this, but &lt;code&gt;ggplot&lt;/code&gt; provides another, more powerful interface
to computing statistics on a hexagonal grid: &lt;code&gt;stat_summary_hex&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;stat_summary_hex&lt;/code&gt; statistic expects two new things. First, it requires that
we explicitly identify the third dimension our data is organized by, the &lt;code&gt;z&lt;/code&gt;
aesthetic. And second, it requires us to pass a function that will be used to
compute the value at each hexagon in the grid from this &lt;code&gt;z&lt;/code&gt; aesthetic. This also
means that the &lt;code&gt;stat_bin_hex&lt;/code&gt; statistic we used above is equivalent to running
&lt;code&gt;stat_summary_hex&lt;/code&gt; with &lt;code&gt;fun = sum&lt;/code&gt; and a &lt;code&gt;z = 1L&lt;/code&gt; aesthetic.&lt;/p&gt;
&lt;p&gt;For example, suppose each row in our crime dataset referred to between one and
three individual crimes at a given location. We could aggregate into a
traditional hexbin map as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Count&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sample&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;nrow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;replace&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;summary.hexmap&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;basemap&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;stat_summary_hex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Longitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Latitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;z&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                         &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cut&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;..value..&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                    &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;250&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                      &lt;span class=&#34;m&#34;&gt;1500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;Inf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))),&lt;/span&gt;
                     &lt;span class=&#34;n&#34;&gt;fun&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                     &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bins&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.75&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                     &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;scale_fill_brewer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;palette&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;OrRd&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                      &lt;span class=&#34;n&#34;&gt;labels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;lt;100&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;100-250&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;250-500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                 &lt;span class=&#34;s&#34;&gt;&amp;#34;500-1000&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;1000-1500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                 &lt;span class=&#34;s&#34;&gt;&amp;#34;1500-2000&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;2000-2500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                 &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;gt;2500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;labs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Reported Crimes in London, by Location (2012-2013)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;summary.hexmap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk unnamed-chunk-6](./images/r-b6720d/unnamed-chunk-6-1.png)
&lt;/center&gt;
&lt;h2 id=&#34;when-stat_summary_hex-fails-use-hexbin-directly&#34;&gt;When &lt;code&gt;stat_summary_hex&lt;/code&gt; Fails, Use &lt;code&gt;hexbin&lt;/code&gt; Directly&lt;/h2&gt;
&lt;p&gt;There some limitations to &lt;code&gt;stat_summary_hex&lt;/code&gt;. For instance, suppose we were
just interested in non-drug crimes. The intuitive approach will fail:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;broken.hexmap&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;basemap&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;stat_summary_hex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Longitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Latitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;z&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Crime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                         &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cut&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;..value..&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                    &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;250&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                      &lt;span class=&#34;m&#34;&gt;1500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;Inf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))),&lt;/span&gt;
                     &lt;span class=&#34;n&#34;&gt;fun&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;z&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Drugs&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
                     &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bins&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.75&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                     &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;scale_fill_brewer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;palette&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;OrRd&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                      &lt;span class=&#34;n&#34;&gt;labels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;lt;100&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;100-250&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;250-500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                 &lt;span class=&#34;s&#34;&gt;&amp;#34;500-1000&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;1000-1500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                 &lt;span class=&#34;s&#34;&gt;&amp;#34;1500-2000&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;2000-2500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                 &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;gt;2500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;labs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Reported Crimes in London, by Location (2012-2013)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;broken.hexmap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk unnamed-chunk-7](./images/r-b6720d/unnamed-chunk-7-1.png)
&lt;/center&gt;
&lt;p&gt;What&amp;rsquo;s going on here? It turns out that &lt;code&gt;ggplot&lt;/code&gt;&amp;rsquo;s implementation (which you
can see &lt;a href=&#34;https://github.com/hadley/ggplot2/blob/f7cb8986a35f68e62a39991a6e19e071fe02c7ec/R/hexbin.R#L15&#34;&gt;here&lt;/a&gt;)
uses &lt;code&gt;tapply&lt;/code&gt;, so it actually creates one geometry for each level of our
&lt;code&gt;Crime&lt;/code&gt; factor. You can see this in that the alpha setting seems to be ignored.
In fact if you look closely you can see the layer below in some places.&lt;/p&gt;
&lt;p&gt;Thankfully, &lt;code&gt;ggplot&lt;/code&gt; is flexible enough for us to completely circumvent this
problem. Internally, &lt;code&gt;geom_hex&lt;/code&gt; calls out to the &lt;code&gt;hexbin&lt;/code&gt; function through &lt;code&gt;stat = &amp;quot;hex&amp;quot;&lt;/code&gt; and then draws hexagons according to the resulting data frame. We can
work around this by computing the intermediate statistic ourselves, and then
pass &lt;code&gt;stat = &amp;quot;identity&amp;quot;&lt;/code&gt; to &lt;code&gt;geom_hex&lt;/code&gt; instead (this is similar to how you would
disable &lt;code&gt;geom_bar&lt;/code&gt;&amp;rsquo;s binning if you were starting out with aggregate data).&lt;/p&gt;
&lt;p&gt;So what we really need is to join our data set with a column indicating which
hexagon a given row would fall in. That would allow us to compute arbitrary
contents for the hexagons from the original data set. Thankfully, the &lt;code&gt;hexbin&lt;/code&gt;
function provides a straightforward way of doing this by passing &lt;code&gt;IDs = TRUE&lt;/code&gt;
(otherwise the &lt;code&gt;cID&lt;/code&gt; slot is optional, since it can be very large).&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;hexbin&lt;/code&gt; function itself returns an S4 object with a number of other
interesting fields, chiefly those that can be used to create a data frame
containing the hexagon coordinates.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;crimes.hex&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hexbin&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;hexbin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Longitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Latitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;n&#34;&gt;xbins&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IDs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Deconstruct the relevant hexbin information into a dataset:&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;hexagons&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;data.frame&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hexbin&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;hcell2xy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crimes.hex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
                       &lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;crimes.hex&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                       &lt;span class=&#34;n&#34;&gt;count&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;crimes.hex&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;crimes.hex&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cID&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;nondrug.crime.hexagons&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Crime&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Drugs&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;group_by&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;summarise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;n&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;ungroup&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Cut here, instead of in the ggplot call (as above).&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crime.level&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cut&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;250&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                       &lt;span class=&#34;m&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                       &lt;span class=&#34;m&#34;&gt;2500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;Inf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
                             &lt;span class=&#34;n&#34;&gt;labels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;lt;100&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;100-250&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                        &lt;span class=&#34;s&#34;&gt;&amp;#34;250-500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;500-1000&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                        &lt;span class=&#34;s&#34;&gt;&amp;#34;1000-1500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;1500-2000&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                        &lt;span class=&#34;s&#34;&gt;&amp;#34;2000-2500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;gt;2500&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;right_join&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hexagons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;by&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;cell&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cell&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;crime.level&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;head&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nondrug.crime.hexagons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## # A tibble: 10 x 6
##     cell          x        y count crimes crime.level
##    &amp;lt;int&amp;gt;      &amp;lt;dbl&amp;gt;    &amp;lt;dbl&amp;gt; &amp;lt;int&amp;gt;  &amp;lt;int&amp;gt;      &amp;lt;fctr&amp;gt;
## 1      1 -0.2499860 51.40001    77     77        &amp;lt;100
## 2      2 -0.2416534 51.40001   117    116     100-250
## 3      3 -0.2333209 51.40001    54     50        &amp;lt;100
## 4      4 -0.2249883 51.40001    26     26        &amp;lt;100
## 5      5 -0.2166557 51.40001    29     29        &amp;lt;100
## 6      6 -0.2083232 51.40001    87     86        &amp;lt;100
## 7      7 -0.1999906 51.40001   136    132     100-250
## 8      8 -0.1916580 51.40001   336    318     250-500
## 9      9 -0.1833255 51.40001    23     23        &amp;lt;100
## 10    10 -0.1749929 51.40001   102    100        &amp;lt;100
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can now plot the &lt;code&gt;nondrug.crime.hexagons&lt;/code&gt; data frame directly, using
&lt;code&gt;geom_hex&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;manual.hexmap&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;basemap&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_hex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;crime.level&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;stat&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;identity&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.75&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nondrug.crime.hexagons&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;scale_fill_brewer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;palette&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;OrRd&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;labs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Non-drug Crimes in London, by Location (2012-2013)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;manual.hexmap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk unnamed-chunk-9](./images/r-b6720d/unnamed-chunk-9-1.png)
&lt;/center&gt;
&lt;p&gt;Using this approach it is possible to compute arbitrary data for each hex bin.&lt;/p&gt;
&lt;h2 id=&#34;postscript-cleaning-up-the-crime-data&#34;&gt;Postscript: Cleaning up the Crime Data&lt;/h2&gt;
&lt;p&gt;This snippet of code should extract all of the relevant data from the raw,
unzipped data extract:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dplyr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;warn.conflicts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Point R at the unzipped files:&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;setwd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;~/Downloads/b9490c7923e00e0e56ac3d2aa9f2b2a968935b15.zip Folder/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;csv.files&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;data_frame&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;month&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;year&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;rep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2012L&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;times&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;rep&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2013L&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;times&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;fmt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;year&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ifelse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;month&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;-0&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;month&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;-metropolitan-street.csv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;apply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;cat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Reading file:&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;row[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;file&amp;#39;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;raw.data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;read.csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;row[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;file&amp;#39;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stringsAsFactors&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;na.strings&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;colClasses&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;NULL&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;NULL&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;NULL&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;NULL&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;numeric&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;numeric&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                       &lt;span class=&#34;s&#34;&gt;&amp;#34;NULL&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;NULL&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;NULL&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;factor&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;NULL&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;NULL&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Year&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;as.integer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;row[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;year&amp;#39;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
                 &lt;span class=&#34;n&#34;&gt;Month&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;as.integer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;row[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;month&amp;#39;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
        &lt;span class=&#34;nf&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Year&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Month&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Longitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Latitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Crime&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Crime.type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;raw.data&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;do.call&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rbind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;csv.files&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;tbl_df&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;save&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;crimes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;file&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;~/Code/R/data/london-crimes/crimes.rda&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
     &lt;span class=&#34;n&#34;&gt;compress&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;xz&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For reference, the following is the output of my &lt;code&gt;sessionInfo()&lt;/code&gt; at the time of
writing:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;## R version 3.3.1 (2016-06-21)
## Platform: x86_64-apple-darwin14.3.0 (64-bit)
## Running under: OS X 10.10.3 (Yosemite)
## 
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
## 
## attached base packages:
## [1] methods   stats     graphics  grDevices utils     datasets  base     
## 
## other attached packages:
## [1] ggmap_2.6.1   ggplot2_2.1.0 hexbin_1.27.1 dplyr_0.5.0   stringr_1.0.0
## [6] digest_0.6.10 knitr_1.13   
## 
## loaded via a namespace (and not attached):
##  [1] Rcpp_0.12.6         magrittr_1.5        maps_3.1.1         
##  [4] munsell_0.4.3       colorspace_1.2-6    geosphere_1.5-5    
##  [7] lattice_0.20-33     rjson_0.2.15        R6_2.1.2           
## [10] jpeg_0.1-8          plyr_1.8.4          tools_3.3.1        
## [13] grid_3.3.1          gtable_0.2.0        png_0.1-7          
## [16] DBI_0.5             assertthat_0.1      tibble_1.1         
## [19] RJSONIO_1.3-0       reshape2_1.4.1      mapproj_1.2-4      
## [22] formatR_1.4         codetools_0.2-14    evaluate_0.9       
## [25] sp_1.2-3            stringi_1.1.1       RgoogleMaps_1.2.0.7
## [28] scales_0.4.0        proto_0.3-10
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Since this post relies on certain implementation details of &lt;code&gt;ggplot2&lt;/code&gt; and
&lt;code&gt;hexbin&lt;/code&gt;, it may break with future versions of either library.&lt;/p&gt;
    </content>
    
    
    <category term="data"/>
    <category term="r"/>
    <category term="visualization"/>
  </entry>
  <entry>
    <title type="html">Linting Prose in Emacs</title>
    
    <link href="https://unconj.ca/blog/linting-prose-in-emacs.html" rel="alternate"/>
    <published>2016-02-10T00:00:00Z</published>
    
    
    <updated>2016-02-10T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2016-02-10:blog/linting-prose-in-emacs.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;Recently, I came across the &lt;a href=&#34;http://proselint.com&#34;&gt;Proselint&lt;/a&gt; project, which
aspires to be something like a &amp;ldquo;linter&amp;rdquo; for written English prose. It differs
from spelling or grammar checker in that it is primarily focused on logic and
style, taking its advice from the work of many prominent writers on writing.&lt;/p&gt;
&lt;p&gt;The project seems to be a little rough around the edges (code blocks seem to
make it struggle, for example), but it&amp;rsquo;s also perfectly usable in its current
form. It&amp;rsquo;s available as a Python package, so you can &lt;code&gt;pip install proselint&lt;/code&gt; to
get the command-line tool, &lt;code&gt;proselint&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Thanks to the &lt;a href=&#34;http://www.flycheck.com&#34;&gt;Flycheck&lt;/a&gt; framework it&amp;rsquo;s comically easy
to get this imported into a Emacs writing environment. The following snippet
will get you up and running in text and markdown modes:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-elisp&#34; data-lang=&#34;elisp&#34;&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;flycheck-define-checker&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;proselint&lt;/span&gt;
  &lt;span class=&#34;s&#34;&gt;&amp;#34;A linter for prose.&amp;#34;&lt;/span&gt;
  &lt;span class=&#34;nb&#34;&gt;:command&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;proselint&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;source-inplace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
  &lt;span class=&#34;nb&#34;&gt;:error-patterns&lt;/span&gt;
  &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;warning&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;line-start&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;file-name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;line&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;column&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;: &amp;#34;&lt;/span&gt;
	    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;one-or-more&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;any&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))))&lt;/span&gt;
	    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;line-end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
  &lt;span class=&#34;nb&#34;&gt;:modes&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;text-mode&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;markdown-mode&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;gfm-mode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;

&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;add-to-list&lt;/span&gt; &lt;span class=&#34;ss&#34;&gt;&amp;#39;flycheck-checkers&lt;/span&gt; &lt;span class=&#34;ss&#34;&gt;&amp;#39;proselint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Proselint won&amp;rsquo;t focus on checking your grammar and spelling. But it &lt;em&gt;will&lt;/em&gt; point
out that referring to my very unique sense of humour commits both a subtle
language error, and a not-so-subtle error of style:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./images/proselint.png&#34; alt=&#34;Proselint through Flycheck in Action&#34;&gt;&lt;/p&gt;
&lt;p&gt;Every lint in Proselint is named after the authority to whom it appeals: in
these two examples, Mark Twain and David Foster Wallace. While my sentence is
grammatically correct, these two authors would take issue with it. Wallace
points out that &amp;ldquo;very unique&amp;rdquo; doesn&amp;rsquo;t really make sense &amp;mdash; a thing is either
unique or not. And Twain seems to take issue with the usage of &amp;ldquo;very&amp;rdquo; in
general.&lt;/p&gt;
&lt;p&gt;If this kind of feedback appeals to you, Proselint might be worth a try. Given
the simplicity of the Flycheck-based approach, I don&amp;rsquo;t think there&amp;rsquo;s a need for
a seperate &lt;code&gt;proselint.el&lt;/code&gt; package at the moment, but perhaps someone should
submit a small one to the Proselint project itself,
&lt;a href=&#34;https://github.com/amperser/proselint/tree/master/plugins&#34;&gt;which appears to accept plugins&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve also heard of the
&lt;a href=&#34;https://github.com/bnbeckwith/writegood-mode&#34;&gt;writegood-mode&lt;/a&gt; and
&lt;a href=&#34;https://github.com/sachac/artbollocks-mode&#34;&gt;artbollocks-mode&lt;/a&gt; packages, which
address similar issues.&lt;/p&gt;
    </content>
    
    
    <category term="emacs"/>
  </entry>
  <entry>
    <title type="html">Expressing L-systems in Rust</title>
    
    <link href="https://unconj.ca/blog/expressing-l-systems-in-rust.html" rel="alternate"/>
    <published>2015-06-06T00:00:00Z</published>
    
    
    <updated>2015-06-06T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2015-06-06:blog/expressing-l-systems-in-rust.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;I thought I&amp;rsquo;d jump on the Rust blogging bandwagon. Specifically, I&amp;rsquo;ve been
toying with &lt;a href=&#34;https://github.com/atheriel/lsystem&#34;&gt;a new library&lt;/a&gt; to define and
iterate over L-systems in a unique and Rust-inspired fashion. It&amp;rsquo;s been very
rewarding to fool around with a type system so foreign to my roots in duck- and
weakly-typed languages.&lt;/p&gt;
&lt;p&gt;If you haven&amp;rsquo;t heard of L-systems before,
&lt;a href=&#34;https://www.google.ca/search?q=l-system&amp;amp;tbm=isch&#34;&gt;they&amp;rsquo;re mostly used to make pretty pictures&lt;/a&gt;.
I was able to create a little animation of the first seven iterations of an
L-system that draws Penrose tiles (below).&lt;/p&gt;
&lt;center&gt;
![Penrose Tile L-system](/images/penrose.gif)
&lt;/center&gt;
&lt;p&gt;L-systems have put them to a variety of different uses, including modelling
&lt;a href=&#34;http://algorithmicbotany.org/papers/#abop&#34;&gt;plants and trees&lt;/a&gt;,
&lt;a href=&#34;https://www.cs.purdue.edu/homes/aliaga/cs535-12/lectures/grammars/proc-mod-bldgs.pdf&#34;&gt;buildings and cities&lt;/a&gt;,
and all manner of interesting
&lt;a href=&#34;http://10klsystems.wordpress.com/examples/&#34;&gt;geometric constructions&lt;/a&gt;.
They hold their fascination in part because of the way in which a very small
number of basic components and rules can evolve in startling ways over time.
In other words, L-systems put
&lt;a href=&#34;http://en.wikipedia.org/wiki/Emergence&#34;&gt;emergence&lt;/a&gt; on display.&lt;/p&gt;
&lt;h2 id=&#34;leveraging-rusts-syntax-for-implementation&#34;&gt;Leveraging Rust&amp;rsquo;s Syntax for Implementation&lt;/h2&gt;
&lt;p&gt;Formally, an &lt;a href=&#34;http://en.wikipedia.org/wiki/L-system&#34;&gt;L-system&lt;/a&gt; consists of
three things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;An alphabet of symbols,&lt;/li&gt;
&lt;li&gt;An intial starting point (called an &lt;em&gt;axiom&lt;/em&gt;) composed of letters of this
alphabet; and&lt;/li&gt;
&lt;li&gt;A set of rules (called &lt;em&gt;productions&lt;/em&gt;) for transforming sets of letters into
one another.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I thought it might be neat to see what it looked like if one were to use a
&lt;code&gt;type&lt;/code&gt; as the alphabet, and pattern matching (inside of a closure) to express
the productions. It turns out that Rust&amp;rsquo;s syntax makes this is a nice way to
build up not only the kinds of L-systems I defined above, but also more
advanced parametric and stochastic L-systems as well.&lt;/p&gt;
&lt;p&gt;As an L-system evolves over time, each successive &lt;em&gt;iteration&lt;/em&gt; uses the
productions to replace the symbols in the axiom with new symbols, and the
result then becomes the new axiom for the next iteration. The concept of
iteration in L-systems also suggests a natural expression in Rust: an iterator
type, which responds to calls to &lt;code&gt;next()&lt;/code&gt; by internally mutating a vector
according to a production function.&lt;/p&gt;
&lt;p&gt;This is the basic outline of the implementation: start with a vector of some
arbitrary type, use pattern matching to express productions, and then allow
iteration over the vector to produce successive axioms.&lt;/p&gt;
&lt;h2 id=&#34;lindenmayers-algae&#34;&gt;Lindenmayer&amp;rsquo;s Algae&lt;/h2&gt;
&lt;p&gt;The original application that inspired the invention of L-systems is modelling
the growth of algae cells. According to Lindenmayer, these cells are in one of
two distinct states, reproduction (usually denoted &amp;ldquo;A&amp;rdquo;) or growth (usually
denoted &amp;ldquo;B&amp;rdquo;). In Rust, we can represent these states with a type, specifically
an &lt;code&gt;enum&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#[deriving(Clone, Show, Eq, PartialEq)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;enum&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Algae&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;/** Reproduction State */&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;/** Growth State */&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In order to capture how a group of algae cells grows and changes over time,
Lindenmayer proposed that algae cells that are in the growth state transition
to being in the reproductive state after a set period. In this same period, a
cell in the reproductive state will birth a new cell, which starts in the
growth state. These two processes can be represented using a simple function
that makes use of Rust&amp;rsquo;s &lt;code&gt;match&lt;/code&gt; construct:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;algae_rule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;input&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;Algae&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nb&#34;&gt;Vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we take the &lt;code&gt;Algae&lt;/code&gt; type as representing the L-system&amp;rsquo;s alphabet, these two
pieces are all that we need to define an L-system:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lsystem&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;LSystem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;algae&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LSystem&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Although this time I&amp;rsquo;ve used a closure instead of referencing the &lt;code&gt;algae_rule&lt;/code&gt;
function directly. In the current version of the library, the &lt;code&gt;LSystem&lt;/code&gt; type
itself is an &lt;code&gt;Iterator&lt;/code&gt;, which means we can capture the notion of iteration as
it pertains to L-systems in a very idiomatic way. For instance, to check that
the &lt;code&gt;n = 4&lt;/code&gt; case matches Lindenmayer&amp;rsquo;s &amp;ldquo;ABAAB&amp;rdquo; string:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;algae_n4&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;algae&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nth&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;unwrap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Confirm that it matches Lindenmayer&amp;#39;s fifth iteration.
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;assert_eq&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;algae_n4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;           &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Algae&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course, you could also use some form of &lt;code&gt;for n in algae { ... }&lt;/code&gt;, but keep
in mind that this is an infinite loop when dealing with &lt;code&gt;LSystem&lt;/code&gt;, so you&amp;rsquo;d
have to &lt;code&gt;break&lt;/code&gt; out of it somehow.&lt;/p&gt;
&lt;h2 id=&#34;an-implementation&#34;&gt;An Implementation&lt;/h2&gt;
&lt;p&gt;It actually took me quite a while to hammer out an exact implementation for
these ideas &amp;mdash; all of the backpedalling in
&lt;a href=&#34;https://github.com/atheriel/lsystem/commits/master&#34;&gt;the commit history&lt;/a&gt; is a
testament to this. But it ended up being quite simple now that Rust has the
&lt;code&gt;FnMut&lt;/code&gt; trait:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;LSystem&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;F&lt;/span&gt;: &lt;span class=&#34;nb&#34;&gt;FnMut&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nb&#34;&gt;Vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axiom&lt;/span&gt;: &lt;span class=&#34;nb&#34;&gt;Vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rules&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;F&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;F&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LSystem&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;F&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;F&lt;/span&gt;: &lt;span class=&#34;nb&#34;&gt;FnMut&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nb&#34;&gt;Vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;/// Creates a new representation of an L-system with the given axiom and
&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;/// production rules.
&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axiom&lt;/span&gt;: &lt;span class=&#34;nb&#34;&gt;Vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rules&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;F&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;LSystem&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;F&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LSystem&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axiom&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;axiom&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rules&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;rules&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The closure (or &lt;code&gt;fn&lt;/code&gt;) is actually called during iteration. I experimented with
a number of ways to turn an &lt;code&gt;LSystem&lt;/code&gt; into a iterator, including a top-level
function and an &lt;code&gt;LSystemIterator&lt;/code&gt; that was created with a call to an &lt;code&gt;iter()&lt;/code&gt;
method. In the end, I decided just to implement the &lt;code&gt;Iterator&lt;/code&gt; trait for the
key struct directly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;F&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Iterator&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LSystem&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;F&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;where&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;: &lt;span class=&#34;nb&#34;&gt;Clone&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;F&lt;/span&gt;: &lt;span class=&#34;nb&#34;&gt;FnMut&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nb&#34;&gt;Vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Item&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;/// Yield the next iteration of the L-system by rewriting the current
&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;/// axiom&amp;#39;s contents using the productions.
&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;next&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nb&#34;&gt;Option&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// To handle the &amp;#34;n = 0&amp;#34; case, we return the current state of the
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// iterator by value, and then rewrite the internal vector in
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// preparation of the next state.
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axiom&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;clone&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Apply the production rules to the axiom to produce a new axiom for
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// the iteration level.
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;new_axiom&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Vec&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;element&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axiom&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;drain&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(..)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;new_axiom&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;extend&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rules&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;element&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;into_iter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;());&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axiom&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;new_axiom&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Update: Thanks to &lt;a href=&#34;http://www.reddit.com/user/matthieum&#34;&gt;u/matthiem&lt;/a&gt; for some
nice improvements over the original implementation.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;the-turtle-interpretation-of-l-systems&#34;&gt;The &amp;ldquo;Turtle&amp;rdquo; Interpretation of L-systems&lt;/h2&gt;
&lt;p&gt;You might be asking yourself &amp;ldquo;what do I &lt;em&gt;do&lt;/em&gt; with an L-system?&amp;rdquo; at this point.
That is, what does the vector of symbols that each interation produces actually
mean? In Lindenmayer&amp;rsquo;s algae model, we could look at the vector of symbols and
see it as a culture of cells, but that doesn&amp;rsquo;t hold for other examples.&lt;/p&gt;
&lt;p&gt;If you followed any of the links above, you might have noticed that L-systems
are often associated with
&lt;a href=&#34;http://en.wikipedia.org/wiki/Turtle_graphics&#34;&gt;turtle graphics&lt;/a&gt;. The essential
idea is that a string of symbols can be sequentially &amp;ldquo;interpreted&amp;rdquo; as a series
of drawing commands&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Once again, this has a very nice representation in Rust:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mod&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;turtle&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// Note that this is only a small subset of more complete Turtle graphics
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// implementations.
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;enum&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Turtle&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;	    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Forward&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;u32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;u32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Right&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;u32&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Push&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Pop&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;pub&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;trait&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TurtleInterpretation&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;	    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to_turtle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Turtle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That is, the &lt;code&gt;Turtle&lt;/code&gt; algebraic type represents turtle graphics commands, and
any type can have a &amp;ldquo;turtle interpretation&amp;rdquo; by implementing a simple &lt;code&gt;trait&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example, we can create a version of the
&lt;a href=&#34;http://en.wikipedia.org/wiki/L-system#Example_5:_Sierpinski_triangle&#34;&gt;Sierpinski triangle&lt;/a&gt;
with the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;extern&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;crate&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lsystem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lsystem&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;LSystem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;use&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lsystem&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;turtle&lt;/span&gt;::&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Turtle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TurtleInterpretation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;draw&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;TurtleInterpretation&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt;: &lt;span class=&#34;nb&#34;&gt;Vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;/* see below */&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#[derive(Clone)]&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;enum&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Sierpinski&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Plus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Minus&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;impl&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TurtleInterpretation&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to_turtle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span class=&#34;nc&#34;&gt;Turtle&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;			&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Turtle&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Forward&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;			&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;     &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Turtle&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Forward&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;			&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Plus&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Turtle&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;			&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Minus&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Turtle&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Right&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;mut&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LSystem&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;new&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// A -&amp;gt; B-A-B
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Minus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;		                      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Minus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// B -&amp;gt; A+B+A
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Plus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;B&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;		                      &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Plus&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Sierpinski&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;A&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// + and - are constants.
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;		&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;	&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;draw&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nth&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;unwrap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;());&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The last piece of code we need is a function that will take a &lt;code&gt;Vec&amp;lt;T: Turtle&amp;gt;&lt;/code&gt;
and &lt;code&gt;draw()&lt;/code&gt; it to the screen. I didn&amp;rsquo;t really want to write any graphics code,
so here&amp;rsquo;s a way to cheat:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;k&#34;&gt;fn&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;draw&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;: &lt;span class=&#34;nc&#34;&gt;TurtleInterpretation&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt;: &lt;span class=&#34;nb&#34;&gt;Vec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;import turtle\n\nturtle.speed(0)\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;command&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;iter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;command&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;to_turtle&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Turtle&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Forward&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;turtle.forward({})&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Turtle&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Left&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;turtle.left({})&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Turtle&lt;/span&gt;::&lt;span class=&#34;n&#34;&gt;Right&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;   &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;turtle.right({})&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;val&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;            &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;println&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;\nturtle.exitonclick()\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It turns out that there&amp;rsquo;s a turtle graphics implementation distributed with
Python &amp;mdash; so this little &lt;code&gt;draw()&lt;/code&gt; function will write a complete Python
program to draw your L-system to &lt;code&gt;stdin&lt;/code&gt; (which you can pipe to &lt;code&gt;python&lt;/code&gt;). I
usually just run something like the following in my shell to test them:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;$ ./sierpinski &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; python -
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Sneaky, eh? There&amp;rsquo;s a much, much more complete version of such a &lt;code&gt;draw()&lt;/code&gt;
function included in the script I used to create the Penrose tiles above, which
can be found in the
&lt;a href=&#34;https://github.com/atheriel/lsystem/blob/master/examples/&#34;&gt;examples directory of the project&lt;/a&gt;.
All of the heavy lifting for creating the &lt;code&gt;.gif&lt;/code&gt; itself is done by
ImageMagick&amp;rsquo;s &lt;code&gt;convert&lt;/code&gt; utility, because I don&amp;rsquo;t think there&amp;rsquo;s a Rust image
library that will handle Postscript files at the moment.&lt;/p&gt;
&lt;p&gt;A possible improvement to the library in the future might be output to the new
turtle graphics implementation in Rust, which was posted to Reddit
&lt;a href=&#34;http://www.reddit.com/r/rust/comments/387rwr/rurtle_turtle_graphics_in_rust/&#34;&gt;a few days ago&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Comments on the implementation details are very welcome! There were also some
good comments on
&lt;a href=&#34;http://www.reddit.com/r/rust/comments/38ujcr/blog_expressing_lsystems_in_rust_comments_code/&#34;&gt;the Reddit thread&lt;/a&gt;.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;L-systems are often expressed &lt;em&gt;only&lt;/em&gt; in this form. This is a bit of a
mistake, as the algae example illustrates. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
    </content>
    
    
    <category term="pcg"/>
    <category term="projects"/>
    <category term="rust"/>
  </entry>
  <entry>
    <title type="html">Not All Population Maps Are Boring</title>
    
    <link href="https://unconj.ca/blog/not-all-population-maps-are-boring.html" rel="alternate"/>
    <published>2014-12-02T00:00:00Z</published>
    
    
    <updated>2014-12-02T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2014-12-02:blog/not-all-population-maps-are-boring.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;As the &lt;a href=&#34;http://xkcd.com/1138/&#34;&gt;venerable xkcd comic&lt;/a&gt; points out, unadjusted
geographic data often ends up looking like a population map. Normally, this
makes it kind of boring, since it doesn&amp;rsquo;t tell you anything new.&lt;/p&gt;
&lt;p&gt;Except, of course, when a visualizing the population is exactly what you had in
mind. I discovered recently that the Australian government keeps track of every
public toilet in the country, for example — and what better way is there
to learn about Australian geography than through such an important public
utility?&lt;/p&gt;
&lt;center&gt;
![Australia, In Public Toilets](/images/australia-in-public-toilets.png)
&lt;/center&gt;
&lt;p&gt;As usual, the remainder of this post is a technical discussion of how I created
the graphic above. It was a neat opportunity to make use of hexbinning, and I&amp;rsquo;m
quite fond of the end result. I haven&amp;rsquo;t yet figured out a way to add a &amp;ldquo;shadow&amp;rdquo;
made of hexagons to indicate the overall shape of Australia, though I would
like to. The fully reproducible code can be found
&lt;a href=&#34;https://github.com/atheriel/visualizations/tree/master/australian-toilets&#34;&gt;in my visualization repository on Github&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;using-hex-bins-in-ggplot2&#34;&gt;Using Hex Bins in ggplot2&lt;/h2&gt;
&lt;p&gt;You can grab the data on Australia toilets
&lt;a href=&#34;http://data.gov.au/dataset/national-public-toilet-map&#34;&gt;here&lt;/a&gt;.
Each entry in the &lt;code&gt;.csv&lt;/code&gt; file contains quite a lot of other interesting
information, but for now I&amp;rsquo;m most interested in the &lt;code&gt;Longitude&lt;/code&gt; and &lt;code&gt;Latitude&lt;/code&gt;
fields. I&amp;rsquo;ve used the brilliant &lt;code&gt;dplyr&lt;/code&gt; package to rearrange and select what I
need, as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dplyr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;warn.conflicts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;quiet&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;toilets&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;read.csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;~/Code/R/data/toiletmap.csv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;header&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stringsAsFactors&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;mutate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;long&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Longitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lat&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Latitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&amp;gt;%&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;select&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ToiletID&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;long&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The hex binning features of &lt;code&gt;ggplot2&lt;/code&gt; rely on the &lt;code&gt;hexbin&lt;/code&gt; package, so you may
need to run &lt;code&gt;install.packages(&amp;quot;hexbin&amp;quot;)&lt;/code&gt; before the following code will work.
But it&amp;rsquo;s actually quite simple to get them working:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ggplot2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;quiet&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;ggplot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;toilets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;long&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_hex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;coord_equal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk toilet-hexbin](images/r-b27dc3c2/toilet-hexbin.png) 
&lt;/center&gt;
&lt;p&gt;This looks pretty good. But it can be reasonaby difficult to compare different
places on a continuous scale, so I decided to break the bins in levels. A very
useful base R function for me here was &lt;code&gt;cut()&lt;/code&gt;, which does exactly this: it
breaks a continuous variable into a factor. I chose seven levels, because I
think that&amp;rsquo;s about the most one can digest really easily. To do this, I made
use of &lt;code&gt;stat_binhex&lt;/code&gt; as opposed to &lt;code&gt;geom_hex&lt;/code&gt; (much as you might use
&lt;code&gt;stat_density&lt;/code&gt; instead of &lt;code&gt;geom_density&lt;/code&gt; when you want more control). It&amp;rsquo;s easy
to add a nicer colour scale as well using the RColorBrewer palettes, too.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;ggplot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;toilets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;long&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;stat_binhex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
        &lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cut&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;..count..&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;100&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                                    &lt;span class=&#34;m&#34;&gt;500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;Inf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;coord_equal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;labs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;scale_fill_brewer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;palette&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;OrRd&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;labels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;lt;5 &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;5-9 &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;10-49 &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;50-99 &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                   &lt;span class=&#34;s&#34;&gt;&amp;#34;100-499 &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;500-999 &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;1000+  &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk toilet-hexbin2](images/r-b27dc3c2/toilet-hexbin2.png) 
&lt;/center&gt;
&lt;h2 id=&#34;adding-points-of-interest&#34;&gt;Adding Points of Interest&lt;/h2&gt;
&lt;p&gt;Not surprisingly, the highest concentrations of toilets are found in the
largest urban areas. I thought the map might be more interesting if I layered
over the labels for these cities, so I looked up the list of the largest cities
in Australia (via
&lt;a href=&#34;http://en.wikipedia.org/wiki/List_of_cities_in_Australia_by_population&#34;&gt;Wikipedia&lt;/a&gt;)
and then extracted the longitude and latitude information from the site&amp;rsquo;s links
to GeoHack. This gave me the following data frame:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;poi&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;data.frame&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Perth&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Sydney&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Melbourne&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Brisbane&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Adelaide&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;s&#34;&gt;&amp;#34;Alice\nSprings&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Darwin&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Hobart\n(Tasmania)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;long&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;115.858889&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;151.209444&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;144.963056&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;153.027778&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;138.601&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;133.87&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;m&#34;&gt;130.833333&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;147.325&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;lat&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;-31.952222&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-33.859972&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-37.813611&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-27.467917&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-34.929&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-23.7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;m&#34;&gt;-12.45&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-42.880556&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which can just be overlaid on the previous ggplot object using &lt;code&gt;geom_text&lt;/code&gt;. To
get away from the &amp;ldquo;plot&amp;rdquo; feeling, I also removed most of the theme elements.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;grid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;quiet&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# For the unit() function.&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;long&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                  &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;poi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;panel.background&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_rect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;gray90&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;plot.background&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_rect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;gray90&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
          &lt;span class=&#34;c1&#34;&gt;# Remove titles, ticks, gridlines, and borders.&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;axis.text&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_blank&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;axis.title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_blank&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;axis.ticks&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_blank&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;panel.grid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_blank&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;panel.border&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_blank&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
          &lt;span class=&#34;c1&#34;&gt;# Set the legend background.&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;legend.background&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_rect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;legend.key&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_rect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
          &lt;span class=&#34;c1&#34;&gt;# Set margins so that the graphic fills the whole space.&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;plot.margin&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;line&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 

&lt;span class=&#34;nf&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk toilet-hexbin3](images/r-b27dc3c2/toilet-hexbin3.png) 
&lt;/center&gt;
&lt;p&gt;There were some other minor adjustments I made (to the legend&amp;rsquo;s position and
the transparency of the hexbins, for example), but that&amp;rsquo;s the gist of my
approach. To get a sense of how I incorporated fonts and created the
title/subtitle, you can check out the fully reproducible code
&lt;a href=&#34;https://github.com/atheriel/visualizations/tree/master/australian-toilets&#34;&gt;on Github&lt;/a&gt;.&lt;/p&gt;
    </content>
    
    
    <category term="data"/>
    <category term="r"/>
    <category term="visualization"/>
  </entry>
  <entry>
    <title type="html">Visualizing Health Expenditure using Spie Charts (and R)</title>
    
    <link href="https://unconj.ca/blog/visualizing-health-expenditure-using-spie-charts-and-r.html" rel="alternate"/>
    <published>2014-10-11T00:00:00Z</published>
    
    
    <updated>2014-10-11T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2014-10-11:blog/visualizing-health-expenditure-using-spie-charts-and-r.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;Continuing with the theme of my last post, I wanted to put an interesting
visualization together using some publically available data. The result is the
following (somewhat surprising) graphic:&lt;/p&gt;
&lt;center&gt;
![health-spending-infovis](/images/spending-spie-final.png)
&lt;/center&gt;
&lt;p&gt;One of the looming issues in Canadian public policy is how to address the fact
that our population is ageing, and that this will mean a larger burden on many
of the social services that are more heavily consumed by those who are older.
But just how uneven is the consumption of health services? The above should
give you some idea of why this is viewed as a looming problem.&lt;/p&gt;
&lt;p&gt;The remainder of this post is a technical discussion of how I created the
visualization. I&amp;rsquo;m not quite satisfied with the overall approach (I think it
takes quite a while before you can really &lt;em&gt;read&lt;/em&gt; the graphic), but it does
serve as a good technical demonstration of what can be accomplished in R.&lt;/p&gt;
&lt;h2 id=&#34;creating-a-spie-chart-with-ggplot2&#34;&gt;Creating a &amp;ldquo;Spie&amp;rdquo; Chart with ggplot2&lt;/h2&gt;
&lt;p&gt;A spie chart is really just a way of comparing two pie charts. The width of
each slice corresponds to its share by one measure, and its area (or, in some
formulations, its height, corresponds to its share by another). I originally
found the concept while exploring &lt;a href=&#34;http://www.datavis.ca/gallery/bright-ideas.php&#34;&gt;DataVis&lt;/a&gt;.
A version of the the paper that introduced the concept is available &lt;a href=&#34;http://www.cs.huji.ac.il/~feit/papers/Spie03TR.pdf&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In order to get the Canadian health spending data into a format suitable for
comparison with this chart, we need need to play around with it a bit. CIHI
publishes their complete tables for free &lt;a href=&#34;https://secure.cihi.ca/estore/productSeries.htm?pc=PCC52&#34;&gt;here&lt;/a&gt;,
but none of it was in precisely the format that I wanted, so I extracted the
relevant information from Table E.1.14 and Appendix C.17 and created the
following &lt;code&gt;pop_exp_canada_2011.csv&lt;/code&gt; file to work with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;bin,pop,exp,sex
&amp;lt;1,192.49,1737.42,F
1-4,738.24,1117.42,F
5-9,885.96,1091.74,F
10-14,924.04,1200.01,F
15-19,1072.69,1823.61,F
20-24,1169.13,2345.44,F
25-29,1193.84,3176.77,F
30-34,1174.74,3504.91,F
35-39,1140.41,2994.82,F
40-44,1189.54,2860.62,F
45-49,1364.98,3522.20,F
50-54,1334.70,3963.40,F
55-59,1193.13,4113.49,F
60-64,1040.40,4473.18,F
65-69,790.72,4687.53,F
70-74,603.58,4842.44,F
75-79,503.05,5587.23,F
80-84,410.18,6525.53,F
85-89,283.02,7068.76,F
90+,172.18,4698.45,F
&amp;lt;1,201.30,2055.33,M
1-4,777.30,1251.80,M
5-9,939.64,1253.51,M
10-14,975.94,1303.69,M
15-19,1123.67,1656.40,M
20-24,1235.04,1770.19,M
25-29,1229.32,1853.98,M
30-34,1174.23,1898.48,M
35-39,1147.82,2026.09,M
40-44,1204.91,2454.87,M
45-49,1384.03,3280.49,M
50-54,1332.97,3942.38,M
55-59,1161.09,4361.40,M
60-64,999.08,4889.40,M
65-69,744.85,5187.12,M
70-74,539.84,5026.25,M
75-79,416.40,5207.42,M
80-84,294.40,4821.01,M
85-89,158.38,3526.42,M
90+,66.76,1594.15,M
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first thing to do is reorganize the data. We want the data for women to run
in the reverse order, so that Women &amp;lt;1 are next to Men &amp;lt;1. This is purely an
aesthetic consideration; you can experiment with the spie chart that is
produced when skipping this step.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Data culled form Appendix C.17 and Table E.1.14 of the CIHI report&amp;#39;s data&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;read.csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;~/Code/R/data/pop_exp_canada_2011.csv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;header&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# (Optional) Change the levels from &amp;#34;F&amp;#34; and &amp;#34;M&amp;#34; to more complete labels:&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;levels&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Women&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Men&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Reorganize the data (we can skip the factor column &amp;#34;sex&amp;#34;, since it does not&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# make a difference):&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin[1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;20&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;rev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin[1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;20&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exp[1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;20&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;rev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exp[1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;20&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pop[1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;20&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;rev&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pop[1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;20&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we need to convert the population data into shares (percentages). We also
need to compute the cumulative population share so that we can properly
position the entries along the x-axis. Finally, we calculate the radius of the
expenditure for a given slice of the population using the formula from the
original paper:&lt;/p&gt;
&lt;p&gt;$$ r_{outer}^2 = \frac{outer_i}{\sum outer_i} \frac{inner_i}{\sum inner_i} $$&lt;/p&gt;
&lt;p&gt;Which implies an inner radius of 1. (To understand where this number comes from,
remember that the area of a slice of a circle is given by (\theta r^2), where
(\theta) is the angle.)&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Calculate the population percentage and cumulative percentage for each entry:&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;popshare&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pop&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cumpop&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cumsum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;popshare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# And the expenditure share as well&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;expshare&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Compute the radius&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r_exp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;expshare&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;popshare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now we create the plot itself. A pie chart is really just a bar chart in
polar coordinates with the width of the bars equal to the share of the value
for that category, so we can start with a bar chart:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ggplot2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;bars&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;ggplot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cumpop&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;popshare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# The &amp;#34;inner&amp;#34; pie plot, with radius 1, is washed out by setting the alpha&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_bar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;popshare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;color&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stat&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;identity&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# The &amp;#34;outer&amp;#34; pie plot uses the radius calculated earlier&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_bar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;popshare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;expshare&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;popshare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;#y = r_exp),&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;color&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;grey10&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stat&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;identity&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Add a dotted line at the radius = 1 point to emphasize it&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;segment&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lineend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;round&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;Inf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;Inf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;yend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bars&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;figure/bars.png&#34; alt=&#34;plot of chunk bars&#34;&gt;&lt;/p&gt;
&lt;p&gt;This really illustrates how a spie chart is constructed. The dotted line is the
&amp;ldquo;break-even&amp;rdquo; point: below it, the expenditure of those groups is less than
their share of the population, and above it those groups are consuming a share
larger than their representation in the population. Note also that their are in
fact two bar charts here, a pale one where all bars of of height 1 and a solid
one over top.&lt;/p&gt;
&lt;p&gt;To transform this into a spie chart we need to make two adjustments. The first
is the conversion to polar coordinates (imagine taking each end of the x-axis
and squeezing it to a point), and the second is to rescale the y-axis so that
the area (and not the height) of the slices corresponds to the relative shares
of the groups. Fortunately, this second step is also quite simple: it boils
down to taking the square root of each y entry.&lt;/p&gt;
&lt;p&gt;We can do this quite simply using ggplot:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;spie&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;bars&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;coord_polar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;theta&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;x&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;scale_y_sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;scale_x_continuous&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;labels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                       &lt;span class=&#34;n&#34;&gt;breaks&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cumpop&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;popshare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;labs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Age Group and Sex&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Ratio of Expenditure to Population Size&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Sex&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme_bw&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axis.text.x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;angle&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spie&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;figure/spie.png&#34; alt=&#34;plot of chunk spie&#34;&gt;&lt;/p&gt;
&lt;p&gt;And with the addition of the labels we&amp;rsquo;ve created a simple spie chart. Of
course it is quite ugly &amp;mdash; there are far too many labels for the groups &amp;mdash;
but this is the starting point.&lt;/p&gt;
&lt;h2 id=&#34;creating-an-information-visualization&#34;&gt;Creating an &amp;ldquo;Information Visualization&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;Moving away from a statistical graphic to a pretty infographic, or
&lt;a href=&#34;&#34;&gt;information visualization&lt;/a&gt;, requires some modifications to the plot.
Traditionally, the advice was to export this from R and into Inkscape or some
other drawing program in order to add annotations, nicer titles, and so on. But
if you&amp;rsquo;re like me, and enjoy the idea of creating visualizations purely
programmatically, then there are ways to accomplish this tidying up in R alone.&lt;/p&gt;
&lt;p&gt;To start with, I&amp;rsquo;ve used the same approach as before as the base plot, but
removed all of the axes and labels. This gives us a base object with which to
build up the visualization:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;grid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# For the units() function&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ggplot2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;base&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;ggplot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cumpop&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;popshare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r_exp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_bar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;popshare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;color&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stat&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;identity&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;alpha&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_bar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;width&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;popshare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;color&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;grey10&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stat&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;identity&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;segment&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lineend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;round&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;Inf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;Inf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;yend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;coord_polar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;theta&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;x&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;scale_x_continuous&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;labels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                       &lt;span class=&#34;n&#34;&gt;breaks&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cumpop&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;spie.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;popshare&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;scale_fill_brewer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;palette&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Pastel1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;labs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme_bw&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;panel.grid&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_blank&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;axis.title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_blank&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;axis.text&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_blank&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;axis.ticks&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_blank&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;legend.position&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;none&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;panel.border&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_rect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;plot.margin&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;units&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;line&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;base&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;figure/base.png&#34; alt=&#34;plot of chunk base&#34;&gt;&lt;/p&gt;
&lt;p&gt;Since I wanted to construct something of a narrative for this information, I
decided to annotate some of the interesting features of the plot. When using
ggplot2, the &lt;code&gt;annotate&lt;/code&gt; function facilitates this. Unfortunately, because the
plot is in polar (square root) coordinates, this complicates placement. I just
tweaked values by eye instead of doing things systematically. This gives&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;final&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;base&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Arrow to the 90+ group, and a text blurb:&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;segment&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.94&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.9925&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;6.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.05&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;yend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;6.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;arrow&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;arrow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ends&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;last&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;line&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.935&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;6.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.05&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;If we take the ratio of the share of public health&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;spending to the share of the population for&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;five-year age groups, we spend at more&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;than 6:1 on those over 90.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sep&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Arrow to the 80-84 group, and a text blurb:&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;segment&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.03&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.095&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;4.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;yend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;4.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;arrow&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;arrow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ends&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;first&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;line&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;4.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; 
             &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;And more than 4:1 on those over 80.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Arrow to the 65-69 group, and a text blurb:&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;segment&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.855&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.93&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;yend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;arrow&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;arrow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ends&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;last&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;line&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.85&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; 
             &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;In fact by 65 the ratio is already 2:1.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Text blurbs:&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;segment&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.31&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.275&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.05&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;yend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;arrow&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;arrow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ends&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;first&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;line&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.27&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.16&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Only below age 55 is the ratio less than 1:1.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;(The break-even point is illustrated by the&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;pale inner circle.)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sep&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Arrow to the inner circle and text blurb:&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;segment&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.65&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.62&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;yend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.05&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;arrow&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;arrow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ends&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;last&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;line&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;In fact most of the remainder cost less than&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;50% of their share. (Women are more&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;expensive in their youth primarily&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;because of childbirth.)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sep&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Babies text and arrow:&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;segment&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.495&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.455&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.53&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;yend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.83&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;arrow&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;arrow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ends&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;first&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;line&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.45&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  
             &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;(Babies themselves are expensive, too.)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Explaining the graph itself:&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.55&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  
             &lt;span class=&#34;n&#34;&gt;fontface&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;italic&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Age increases in five-year intervals as you move&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;up the graph, with the addition of 90+ and &amp;lt;1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;groups at the top and bottom, respectively.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;n&#34;&gt;sep&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.05&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;fontface&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;italic&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Women are in red, men are in purple.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;figure/make-final.png&#34; alt=&#34;plot of chunk make-final&#34;&gt;&lt;/p&gt;
&lt;p&gt;The other obvious addition is to add a proper title and a caption on the bottom
of the image (containing, for example, sources and authorship). A good way of
doing this is with the &lt;code&gt;arrangeGrob&lt;/code&gt; provided by the &lt;code&gt;gridExtra&lt;/code&gt; package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gridExtra&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;arrangeGrob&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;final&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;textGrob&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
        &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;The Pressures of an Ageing Population:&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
              &lt;span class=&#34;s&#34;&gt;&amp;#34;Public Health Spending in Canada&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.01&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;npc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;gp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;gpar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fontsize&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fontface&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;bold&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;textGrob&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.01&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;npc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;npc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;gp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;gpar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fontsize&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lineheight&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.9&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
            &lt;span class=&#34;s&#34;&gt;&amp;#34;A. Jacobs :: unconj.ca\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
            &lt;span class=&#34;s&#34;&gt;&amp;#34;Data: Canadian Institute for Health Information, 2013\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
            &lt;span class=&#34;s&#34;&gt;&amp;#34;You may redistribute this graphic under the terms of &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
            &lt;span class=&#34;s&#34;&gt;&amp;#34;the CC-by-SA license.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sep&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&#34;figure/unnamed-chunk-1.png&#34; alt=&#34;plot of chunk unnamed-chunk-1&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;fonts&#34;&gt;Fonts&lt;/h2&gt;
&lt;p&gt;The nature of working with the PNG drivers when producing images is that you
are severely limited by the selection of fonts available. One clever way of
alleviating this is provided by the &lt;code&gt;showtext&lt;/code&gt; and &lt;code&gt;sysfonts&lt;/code&gt; packages, which
simply draw text objects as polygons and lines instead of text &amp;mdash; and thus
avoid the font problem. I have not yet got &lt;code&gt;showtext&lt;/code&gt; working with &lt;code&gt;knitr&lt;/code&gt;,
so the following standalone code is used to produce the image at the top of
this post. Since the scaling is a little different, I&amp;rsquo;ve had to tweak the
&lt;code&gt;final&lt;/code&gt; object slightly. I&amp;rsquo;ve also added a subtitle. It&amp;rsquo;s true that Minion
and Myriad are a little cliché, but they seemed like the most obvious choices
to start with.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sysfonts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;require&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;showtext&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;font.add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;myriad&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;regular&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;MyriadPro-Regular.otf&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;bold&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;MyriadPro-Bold.otf&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;italic&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;MyriadPro-It.otf&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;font.add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;minion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;regular&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;MinionPro-Regular.otf&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;bold&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;MinionPro-Bold.otf&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;italic&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;MinionPro-It.otf&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;final&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;base&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Arrow to the 90+ group, and a text blurb:&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;segment&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.94&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.9925&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;6.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.05&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;yend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;6.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;arrow&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;arrow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ends&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;last&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;line&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.935&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;6.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.05&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;family&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;minion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;If we take the ratio of the share of public health&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;spending to the share of the population for&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;five-year age groups, we spend at more&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;than 6:1 on those over 90.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sep&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Arrow to the 80-84 group, and a text blurb:&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;segment&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.03&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.095&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;4.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;yend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;4.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;arrow&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;arrow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ends&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;first&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;line&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;4.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; 
             &lt;span class=&#34;n&#34;&gt;family&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;minion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;And more than 4:1 on those over 80.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Arrow to the 65-69 group, and a text blurb:&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;segment&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.855&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.93&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;yend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;arrow&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;arrow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ends&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;last&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;line&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.85&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;2.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; 
             &lt;span class=&#34;n&#34;&gt;family&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;minion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;In fact by 65 the ratio is already 2:1.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Text blurbs:&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;segment&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.31&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.275&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.05&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;yend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;arrow&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;arrow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ends&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;first&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;line&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.27&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.16&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;family&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;minion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Only below age 55 is the ratio less than 1:1.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;(The break-even point is illustrated by the&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;pale inner circle.)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sep&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Arrow to the inner circle and text blurb:&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;segment&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.65&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.62&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;yend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sqrt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.05&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;arrow&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;arrow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ends&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;last&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;line&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;family&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;minion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;In fact most of the remainder cost less than&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;50% of their share. (Women are more&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;expensive in their youth primarily&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;because of childbirth.)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sep&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Babies text and arrow:&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;segment&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;linetype&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.495&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.455&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.53&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;yend&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.83&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;arrow&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;arrow&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ends&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;first&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;line&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.45&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1.8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  
             &lt;span class=&#34;n&#34;&gt;family&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;minion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;(Babies themselves are expensive, too.)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Explaining the graph itself:&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.55&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;  
             &lt;span class=&#34;n&#34;&gt;family&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;minion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lineheight&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.95&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fontface&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;italic&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Age increases in five-year intervals as you move&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;up the graph, with the addition of 90+ and &amp;lt;1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;s&#34;&gt;&amp;#34;groups at the top and bottom, respectively.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                           &lt;span class=&#34;n&#34;&gt;sep&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;annotate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.05&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;family&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;minion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lineheight&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.95&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fontface&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;italic&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
             &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Women are in red, men are in purple.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;png&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;output5.png&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;width&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;7&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;300&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;height&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;7&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;300&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;res&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;300&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;showtext.begin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;arrangeGrob&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;final&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;theme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;family&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;minion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;textGrob&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;The Pressures of an Ageing Population:&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                        &lt;span class=&#34;s&#34;&gt;&amp;#34;Public Health Spending in Canada&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
                  &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;The width of the slice corresponds to the population&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                        &lt;span class=&#34;s&#34;&gt;&amp;#34;size, and its area to the share of government health&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                        &lt;span class=&#34;s&#34;&gt;&amp;#34;spending devoted to that group.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.01&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.01&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;npc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;-2.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;line&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;gp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;gpar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fontsize&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;15&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fontfamily&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;myriad&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;minion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
                  &lt;span class=&#34;n&#34;&gt;fontface&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;bold&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;italic&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lineheight&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.9&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;sub&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;textGrob&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.01&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;npc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;npc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;hjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;vjust&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;gp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;gpar&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fontsize&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fontfamily&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;minion&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lineheight&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.9&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;label&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
            &lt;span class=&#34;s&#34;&gt;&amp;#34;A. Jacobs :: unconj.ca\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
            &lt;span class=&#34;s&#34;&gt;&amp;#34;Data: Canadian Institute for Health Information, 2013\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
            &lt;span class=&#34;s&#34;&gt;&amp;#34;You may redistribute this graphic under the terms of &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
            &lt;span class=&#34;s&#34;&gt;&amp;#34;the CC-by-SA license.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sep&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;showtext.end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;dev.off&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
    </content>
    
    
    <category term="data"/>
    <category term="r"/>
    <category term="visualization"/>
  </entry>
  <entry>
    <title type="html">Choropleth Maps with R and ggplot2</title>
    
    <link href="https://unconj.ca/blog/choropleth-maps-with-r-and-ggplot2.html" rel="alternate"/>
    <published>2014-09-05T00:00:00Z</published>
    
    
    <updated>2014-09-05T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2014-09-05:blog/choropleth-maps-with-r-and-ggplot2.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;This post is meant to be a short intro on how to create visualizations like the
following using R and &lt;a href=&#34;http://ggplot2.org/&#34;&gt;ggplot2&lt;/a&gt;:&lt;/p&gt;
&lt;center&gt;
![intro-map](/images/r-f380bbe4/final-map-1.png)
&lt;/center&gt;
&lt;p&gt;&lt;ins&gt;Update (February 6, 2017):&lt;/ins&gt; I&amp;rsquo;ve updated the content of this post to
be much more modern, taking advantage of developments in the spatial package
ecosystem and in the capabilities of &lt;code&gt;ggplot2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To get through this tutorial, you&amp;rsquo;ll need the following packages:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;suppressMessages&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rgeos&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;maptools&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ggplot2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The first thing you need to get your hands on is some representation of the
polygons on a map. There are many formats for these polygons, but one of the
more common ones is the &lt;code&gt;.shp&lt;/code&gt; format used by ArcGIS. The &lt;code&gt;maptools&lt;/code&gt; package
enables opening and manipulating objects created from this format, so you&amp;rsquo;ll
need to get your hands on both that and its prerequisite, &lt;code&gt;rgeos&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;ins&gt;Update (February 6, 2017):&lt;/ins&gt; In the past I recommended &lt;code&gt;gpclib&lt;/code&gt;, but
the &lt;code&gt;rgeos&lt;/code&gt; library is now the preferred approach. It also has a more permissive
license.&lt;/p&gt;
&lt;p&gt;A nice scale to work at in Canada is the level of the forward sortation areas
(FSAs) defined by the first three digits of a postal code. Until very recently
the exact borders of these areas was data you had to pay for, but now
Statistics Canada makes it available on the Census website, &lt;a href=&#34;http://www12.statcan.gc.ca/census-recensement/2011/geo/bound-limit/bound-limit-2011-eng.cfm&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Fair warning: it&amp;rsquo;s quite a large file, and will take some time to downlaod. Of
course, all of the FSAs in Canada is a bit too much to deal with, so I&amp;rsquo;ll focus
just on those that encompass the city of Toronto, which all begin with the
letter &amp;ldquo;M&amp;rdquo;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# fsas &amp;lt;- maptools::readShapeSpatial(&amp;#34;path/to/gfsa000b11a_e.shp&amp;#34;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;toronto.fsas&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fsas&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;[substr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fsas&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CFSAUID&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#39;M&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;]&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# The shapefile takes up quite a lot of memory, and we no longer need it all,&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# so you can delete it if you like:&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;rm&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fsas&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We have to turn the object that &lt;code&gt;maptools&lt;/code&gt; produces into something that can be
plotted in the &lt;code&gt;ggplot2&lt;/code&gt; paradigm, which reguires a &lt;code&gt;data.frame&lt;/code&gt; object. To do
this, we can use the &lt;code&gt;ggplot2::fortify()&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ggplot2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;fortify&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;toronto.fsas&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;region&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;CFSAUID&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Turn the generated &amp;#34;id&amp;#34; chr column into a correctly-labelled factor variable&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fsa&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;factor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;id&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Toronto is actually pretty great about making lots of interesting data
available online. They provide the number of licensed dogs and cats in the city
by FSA &lt;a href=&#34;http://www1.toronto.ca/wps/portal/contentonly?vgnextoid=0a7e1f46f71fb310VgnVCM10000071d60f89RCRD&amp;amp;vgnextchannel=75d6e03bb8d1e310VgnVCM10000071d60f89RCRD&#34;&gt;here&lt;/a&gt;,
although it needs to be cleaned up a little before you can use it directly. It
needs to be merged into the map data:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# pets &amp;lt;- read.csv(&amp;#34;path/to/pets.csv&amp;#34;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Merge the map data and the pet data into something we&amp;#39;ll plot&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;plot.data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;merge&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;by&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;fsa&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we can use &lt;code&gt;ggplot2&lt;/code&gt; to plot the polygons, and fill them with a gradient
based on the number of dogs. Note that you must &lt;code&gt;group&lt;/code&gt; the polygons, otherwise
they might not be drawn out in the correct order (try omitting it and see).
Another key parameter is the &lt;code&gt;coord_equal()&lt;/code&gt; coordinate modification: since
we&amp;rsquo;re dealing with map data, if the scaling of the x and y axis are not the
same the map will be arbitrarily distorted.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m glossing over the details of map projections here &amp;mdash; in this case, the
city is small enough that a latitude = longitude presentation will look just
fine.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;ggplot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plot.data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;long&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;group&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;group&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_polygon&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;coord_equal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk first-map](/images/r-f380bbe4/first-map-1.png)
&lt;/center&gt;
&lt;p&gt;It&amp;rsquo;s that easy! Of course, the default &lt;code&gt;ggplot2&lt;/code&gt; theme is really meant for
presenting data, and might not look that great with a map. The built-in
&lt;code&gt;theme_void()&lt;/code&gt; will strip away most of this extraneous framing, although I tend
to tweak it a little as well.&lt;/p&gt;
&lt;p&gt;&lt;ins&gt;Update (February 6, 2017):&lt;/ins&gt; Bin your spatial data, and use &lt;code&gt;viridis&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I strongly believe that you usually want to bin data for choropleth maps, since
it can be very difficult to judge fine colour differences. The
&lt;code&gt;ggplot2::cut_number()&lt;/code&gt; function will find bins roughly equal in size, which is
a good place to start.&lt;/p&gt;
&lt;p&gt;Unfortunately, the built-in colours for discrete scales are horrible not only
for a final presentation, but also for your own exploratory work. You&amp;rsquo;re better
off using one of the ColorBrewer palettes (available through the built-in
&lt;code&gt;scale_fill_brewer()&lt;/code&gt; function), and you should also check out the carefully
tuned palettes from the &lt;code&gt;viridis&lt;/code&gt; package.&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s try this again, with these changes:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;viridis&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;ggplot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plot.data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;long&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;group&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;group&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
       &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cut_number&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_polygon&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;color&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;grey10&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;coord_equal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;viridis&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;scale_fill_viridis&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;discrete&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;labs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Registered Dogs (Toronto, 2013)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme_void&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;legend.position&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;bottom&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;panel.background&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_rect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;#cccccc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk second-map](/images/r-f380bbe4/second-map-1.png)
&lt;/center&gt;
&lt;p&gt;Which looks much better. Normally we&amp;rsquo;d be done here, but the sage advice of
Randall Munroe is worth keeping in mind:&lt;/p&gt;
&lt;center&gt;&lt;a href=&#34;http://xkcd.com/1138/&#34;&gt;&lt;img src=&#34;http://imgs.xkcd.com/comics/heatmap.png&#34; alt=&#34;xkcd Heatmap&#34;&gt;&lt;/a&gt;&lt;/center&gt;
&lt;p&gt;So we can improve the meaningfulness of this map by adjusting for population.
Luckily, Statistics Canada actually publishes population data at the FSA-level,
and even more luckily they provide data on the number of private dwellings that
are occupied by their usual owners. This last number is particularly
interesting because it is the level at which you would expect pet ownership to
occur. You can find the data &lt;a href=&#34;http://www12.statcan.gc.ca/census-recensement/2011/dp-pd/hlt-fst/pd-pl/Table-Tableau.cfm?LANG=Eng&amp;amp;T=1201&amp;amp;S=22&amp;amp;O=A&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As with most StatsCan-provided CSV files, you will need to clean it up a bit
before using it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# pop &amp;lt;- read.csv(&amp;#34;path/to/fsa_pop.csv&amp;#34;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# We don&amp;#39;t really need the rest of this...&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;pop&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;population&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;pop&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;indian&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;pop&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dwellings&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Merge the data into the dataset we&amp;#39;re already using&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;plot.data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;merge&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plot.data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pop&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;by&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;fsa&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Calculate the density of dogs per private dwelling&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;plot.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dog.density&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plot.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dog&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;plot.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dwellings.usual&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And now we can plot our population-adjusted map using the theme from before:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;dog.map&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ggplot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plot.data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;long&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;group&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;group&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                      &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cut_number&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dog.density&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_polygon&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;color&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;gray10&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;coord_equal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;viridis&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;scale_fill_viridis&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;discrete&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;labs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Registered Dogs per Private Dwelling (Toronto, 2013)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme_void&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;legend.position&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;bottom&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;panel.background&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_rect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;#cccccc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;dog.map&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk third-map](/images/r-f380bbe4/third-map-1.png)
&lt;/center&gt;
&lt;p&gt;Notice that the numbers are quite small. We might want to convert to per-1000
units later.&lt;/p&gt;
&lt;h2 id=&#34;style-points-better-longitude--latitude-labels&#34;&gt;Style Points: Better Longitude &amp;amp; Latitude Labels&lt;/h2&gt;
&lt;p&gt;In case you need to explicitly show the coordinates of your spatial data, we can
ensure that they are formatted nicely by passing a custom formatting function to
the &lt;code&gt;labels&lt;/code&gt; option on the x and y scale. These functions must take a vector of
inputs and return a vector of labels, and we can write one to handle each of
longitude and latitude quite easily:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Converts a numeric array to an array of latitude labels&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;latitude&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;paste0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;digits&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;° &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ifelse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;N&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;S&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Converts a numeric array to an array of longitude labels&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;longitude&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; 
    &lt;span class=&#34;nf&#34;&gt;paste0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;digits&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;° &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ifelse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;E&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;W&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;dog.map&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;scale_y_continuous&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;labels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;latitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;scale_x_continuous&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;labels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;longitude&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;axis.text&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;#333333&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk labelled-map](/images/r-f380bbe4/labelled-map-1.png)
&lt;/center&gt;
&lt;h2 id=&#34;style-points-adding-a-compass-rose&#34;&gt;Style Points: Adding a Compass Rose&lt;/h2&gt;
&lt;p&gt;&lt;ins&gt;Update (February 6, 2017):&lt;/ins&gt; Before &lt;code&gt;ggsn&lt;/code&gt; existed, I used to do this
manually by creating a grob from a vector image using the &lt;code&gt;grImport&lt;/code&gt; package.
This is no longer necessary.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;ggsn&lt;/code&gt; &lt;a href=&#34;http://oswaldosantos.github.io/ggsn/&#34;&gt;package&lt;/a&gt; makes it possible to
add scale bars and compass rose symbols to &lt;code&gt;ggplot&lt;/code&gt; objects.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ggsn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;dog.map&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ggsn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;north&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plot.data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;location&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;bottomright&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;symbol&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk rose-map](/images/r-f380bbe4/rose-map-1.png)
&lt;/center&gt;
&lt;h2 id=&#34;style-points-adding-a-drop-shadow&#34;&gt;Style Points: Adding a Drop Shadow&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s a little trick for adding a drop shadow: we just draw the polygons
filled with grey and shifted slightly southeast, and then draw the actual
map polygons with the correct fill on top (which I learned &lt;a href=&#34;http://www.r-bloggers.com/creating-inset-map-with-ggplot2/&#34;&gt;here&lt;/a&gt;).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;ggplot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plot.data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;long&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;group&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;group&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
                      &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cut_number&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dog.density&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_polygon&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;long&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.005&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lat&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.002&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
                 &lt;span class=&#34;n&#34;&gt;color&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;grey50&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;grey50&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_polygon&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;color&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;gray10&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;coord_equal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;viridis&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;scale_fill_viridis&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;discrete&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;labs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Registered Dogs per Private Dwelling (Toronto, 2013)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme_void&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;legend.position&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;bottom&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;panel.background&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_rect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;#cccccc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk shadow-map](/images/r-f380bbe4/shadow-map-1.png)
&lt;/center&gt;
&lt;h2 id=&#34;finishing-touches-better-fonts-and-nicer-labels&#34;&gt;Finishing Touches: Better Fonts and Nicer Labels&lt;/h2&gt;
&lt;p&gt;&lt;ins&gt;Update (February 6, 2017):&lt;/ins&gt; As of &lt;code&gt;ggplot2&lt;/code&gt; version 2.2, subtitles and
captions are officially supported.&lt;/p&gt;
&lt;p&gt;For standalone graphics, it is conventional to point to your data sources
somewhere, often below. You can do this fairly easily with the &lt;code&gt;caption&lt;/code&gt; label.
I also like to add authorship and licensing information.&lt;/p&gt;
&lt;p&gt;In order to get &amp;ldquo;nicer&amp;rdquo; labels, I&amp;rsquo;m also going to bin the data manually.&lt;/p&gt;
&lt;p&gt;Adopting &lt;code&gt;Arial Narrow&lt;/code&gt; as the font-of-the-day, the image at the top of this
post can be generated as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;n&#34;&gt;plot.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dogs.per.1000&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;factor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;cut&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plot.data&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dog.density&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;45&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;90&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;120&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)),&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;labels&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Under 30&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;30 to 44&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;45 to 59&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;60 to 89&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;90 to 120&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;ggplot&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plot.data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;long&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;group&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;group&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dogs.per.1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_polygon&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;aes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;long&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.005&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;lat&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.002&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
                 &lt;span class=&#34;n&#34;&gt;color&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;grey50&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;grey50&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;geom_polygon&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;color&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;grey10&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;coord_equal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Add the compass rose.&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;ggsn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;north&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;plot.data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;location&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;bottomleft&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;symbol&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;viridis&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;scale_fill_viridis&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;option&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;viridis&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;discrete&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;TRUE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Set the labels to NULL so that no space is allocated for them&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;labs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NULL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Registered Dogs per Toronto Home&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;subtitle&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Density per 1000 Private Dwellings, 2013&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
         &lt;span class=&#34;n&#34;&gt;caption&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;paste&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;A. Jacobs :: unconj.ca&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;s&#34;&gt;&amp;#34;Data: Toronto Animal Services (2014) &amp;amp; Statistics Canada (2013)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;span class=&#34;s&#34;&gt;&amp;#34;You may redistribute this graphic under the terms of the CC-by-SA license.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;sep&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme_void&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;
    &lt;span class=&#34;nf&#34;&gt;theme&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;family&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;Arial Narrow&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;plot.title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;face&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;bold&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;plot.margin&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;unit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;in&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;panel.border&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_rect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;fill&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;NA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;colour&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;#cccccc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;legend.text&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;element_text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;size&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
          &lt;span class=&#34;n&#34;&gt;legend.position&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0.9&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0.25&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;center&gt;
![plot of chunk final-map](/images/r-f380bbe4/final-map-1.png)
&lt;/center&gt;
&lt;p&gt;Which looks pretty good to me!&lt;/p&gt;
    </content>
    
    
    <category term="data"/>
    <category term="r"/>
    <category term="visualization"/>
  </entry>
  <entry>
    <title type="html">Fiddling Around with DEA Models</title>
    
    <link href="https://unconj.ca/blog/fiddling-around-with-dea-models.html" rel="alternate"/>
    <published>2014-05-12T00:00:00Z</published>
    
    
    <updated>2014-05-12T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2014-05-12:blog/fiddling-around-with-dea-models.html</id>
    
    <content type="html" xml:lang="en">
      &lt;!-- &#34;In which I take a very preliminary stab at recreating a data envelopment
analysis approach. Possibly this article will be expanded in the future to
include a more creative application.&#34; --&gt;
&lt;p&gt;Measuring performance is a tricky business. Two of the most annoying drawbacks
of applying regression analysis (as used in most simple econometric approaches)
to these kinds of problems are the requirement to specify a functional form for
the production function (which we can wave away by admitting that our results
are only a &amp;ldquo;best linear approximation&amp;rdquo; that work around the mean) and the
inability to measure the impact of inputs on several outputs similtaneously.&lt;/p&gt;
&lt;p&gt;These are two problems that
&lt;a href=&#34;http://en.wikipedia.org/wiki/Data_envelopment_analysis&#34;&gt;data envelopment analysis&lt;/a&gt;
(DEA) tries to address. In essence, it looks at the relative ability of actors
(or &amp;ldquo;decision-making units&amp;rdquo;) to turn inputs into outputs, and then measures how
far away from the &amp;ldquo;frontier&amp;rdquo; of the most efficient actors the rest of the lot
are. This avoids making many of the very restrictive assumptions (Cobb-Douglas,
anyone?) we usually employ when discussing production functions.&lt;/p&gt;
&lt;p&gt;All of this sounded pretty interesting, so I thought I&amp;rsquo;d try out some of these
models. The
&lt;a href=&#34;http://www.clemson.edu/economics/faculty/wilson/software/fear/fear.html&#34;&gt;FEAR&lt;/a&gt;
package for the R programming language seems like a popular tool to for this
kind of analysis; however, I also discovered the newer
&lt;a href=&#34;http://cran.r-project.org/web/packages/Benchmarking/&#34;&gt;Benchmarking&lt;/a&gt; package,
which has the added benefit of being free even for commercial use.&lt;/p&gt;
&lt;p&gt;&amp;hellip; but mostly it was because FEAR does not yet compile properly on OS X for R
vesion 3.1.0+, and I didn&amp;rsquo;t want to try and patch it. So:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;install.packages&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Benchmarking&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It wasn&amp;rsquo;t entirely clear how to actually check that I was computing efficiencies
correctly, so I pulled some data out of a textbook&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; that also provided the
&amp;ldquo;answer&amp;rdquo;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dmu	input1	input2	output1	output2	ccr
1	0.7150	1.7996	0.7618	1.2239	0.432
2	1.0036	1.2616	1.5441	0.6716	0.709
3	0.0126	0.9276	1.3270	0.3433	1.000
4	0.4339	0.7792	0.3600	0.5075	0.419
5	1.7455	0.2783	1.0560	1.0000	1.000
6	1.5061	0.9276	0.7990	0.5821	0.448
7	0.5313	1.2059	1.1862	1.7612	0.952
8	1.8513	0.7978	1.0885	1.9104	0.865
9	1.9796	1.6698	1.6517	1.1493	0.570
10	0.2211	0.3525	0.2258	0.8507	1.000
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then ran a very simple script to see if I could reproduce the results of a
DEA model with constant returns to scale (this is often called the CCR model,
hence the name of the last column above):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-r&#34; data-lang=&#34;r&#34;&gt;&lt;span class=&#34;nf&#34;&gt;library&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Benchmarking&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;test1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;read.table&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;dea-test1.tsv&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;header&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;T&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;test1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;input1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;test1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;input2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nrow&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ncol&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;matrix&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;test1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;output1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;test1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;output2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nrow&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ncol&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;dea&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RTS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;crs&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ORIENTATION&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eff&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;## [1] 0.4319693 0.7091446 1.0000000 0.4194153 1.0000000 0.4485119 0.9519665 0.8653230 0.5701125 1.0000000
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which seems to match up with the final column in the example data nicely.&lt;/p&gt;
&lt;p&gt;A few minor details about the script: the &lt;code&gt;dea&lt;/code&gt; function provided by the
Benchmarking package defaults to much more nuanced assumptions about returns to
scale, etc, so you need to set the &lt;code&gt;RTS&lt;/code&gt; argument explicitly for simpler models;
further, the &lt;code&gt;ORIENTATION = 1&lt;/code&gt; arguments request the computation of output-based
efficiencies. I&amp;rsquo;ve obviously saved the tab-separated data above as
&lt;code&gt;dea-test1.tsv&lt;/code&gt;.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Specifically, this is from Table 3 in Sarkis, Joseph. 2002. &amp;ldquo;Preparing
Your Data for DEA&amp;rdquo; in &lt;em&gt;Productivity Analysis in the Service Sector with Data
Envelopment Analysis, 2nd Edition&lt;/em&gt;, ed. Necmi Avkiran. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

    </content>
    
    
    <category term="data"/>
    <category term="econ"/>
    <category term="r"/>
  </entry>
  <entry>
    <title type="html">Managing Complex Research Workflows with Make</title>
    
    <link href="https://unconj.ca/blog/managing-complex-research-workflows-with-make.html" rel="alternate"/>
    <published>2014-04-26T00:00:00Z</published>
    
    
    <updated>2014-04-26T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2014-04-26:blog/managing-complex-research-workflows-with-make.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;If you&amp;rsquo;re doing any kind of empirical work in Economics, you probably have a
huge, messy folder containing a mix of&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Data files (&lt;code&gt;.csv&lt;/code&gt;, &lt;code&gt;.dta&lt;/code&gt;, &lt;code&gt;.xlsx&lt;/code&gt;, etc.) in various states of merge-ness and
cleanliness.&lt;/li&gt;
&lt;li&gt;Scripts for creating graphs &amp;amp; figures, producing summary statistics, and
computing models. Probably written for Stata, R, or the Pandas data stack&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
&lt;li&gt;Files containing written work. These are usually &lt;code&gt;.doc(x)&lt;/code&gt; files, but I&amp;rsquo;ve
seen lots of LaTeX lately as well, and being a plain-text format, this is a
huge boon to reproducible research.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A really simple research workflow (start with data, make some figures, make some
summary statistics, and run some models) might look like the following:&lt;/p&gt;
&lt;center&gt;
![An Econ Workflow](./images/econ-workflow.png)
&lt;/center&gt;
&lt;p&gt;But of course that&amp;rsquo;s not clear when looking at the &lt;code&gt;.zip&lt;/code&gt; file you send your
coauthor.&lt;/p&gt;
&lt;p&gt;(In case anyone is wondering about the file extensions, the &lt;code&gt;.do&lt;/code&gt; extensions are
for Stata, which is a popular statistics package among economists&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;, and the
&lt;code&gt;.R&lt;/code&gt; extensions are for R, which is a very popular programming
language/statistics package for everyone else. R probably makes the nicer graphs
of the two&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;.)&lt;/p&gt;
&lt;p&gt;I have a good friend who deals with all of this by creating a single &lt;code&gt;.do&lt;/code&gt; file
to run all of the other Stata, R, and pdflatex scripts&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;, and then simply
commenting out the sections she doesn&amp;rsquo;t want to run. I used to do essentially
the same thing with a Bash script, and back when I used R exclusively I used
&lt;a href=&#34;http://yihui.name/knitr/&#34;&gt;knitr&lt;/a&gt; (which I&amp;rsquo;ll discuss a little bit at the end).&lt;/p&gt;
&lt;p&gt;The problem with these approaches (despite being somewhat inelegant, except
possibly in the case of knitr) is that they don&amp;rsquo;t really incorporate the notion
of &lt;em&gt;dependencies&lt;/em&gt;. If you look back at the diagram above, you&amp;rsquo;ll see that if,
say, you modify the script to produce the tables, &lt;em&gt;then everything that relies
on the tables must be compiled/re-run&lt;/em&gt;. So in this example, &lt;code&gt;table1-data.tex&lt;/code&gt;,
&lt;code&gt;paper.tex&lt;/code&gt;, and &lt;code&gt;paper.pdf&lt;/code&gt; &amp;mdash; and, importantly, &lt;em&gt;only&lt;/em&gt; those things &amp;mdash; would
need to be updated. That kind of interdependency is very hard to capture in a
simple master &amp;ldquo;build&amp;rdquo; script.&lt;/p&gt;
&lt;p&gt;An alternative that I&amp;rsquo;ve been toying with recently is to use the venerable Unix
tool &amp;ldquo;make&amp;rdquo;&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;. Make requires that you write a small file (almost always called
&lt;code&gt;Makefile&lt;/code&gt;, with no extension) outlining the &amp;ldquo;targets&amp;rdquo; your project produces,
and the &amp;ldquo;dependencies&amp;rdquo; each of them require. The syntax looks like the
following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;nv&#34;&gt;VARIABLE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;
&lt;span class=&#34;c&#34;&gt;# Comment
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;[target]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; [&lt;span class=&#34;n&#34;&gt;dependency&lt;/span&gt;1 &lt;span class=&#34;n&#34;&gt;dependency&lt;/span&gt;2 ...]
	&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;command&lt;/span&gt; to run&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;VARIABLE&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;etc&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So for our project above, you might have a simple &lt;code&gt;Makefile&lt;/code&gt; containing&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;c&#34;&gt;# First, clean the data using the cleanup script:
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;data-cleaned.dta&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;csv&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cleanup&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;do&lt;/span&gt;
	stata-se -b &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;cleanup.do&amp;#34;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;# Next, produce the two tables from the cleaned data:
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;table1-data.tex&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;-&lt;span class=&#34;n&#34;&gt;cleaned&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;dta&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sumstats&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;do&lt;/span&gt;
	stata-se -b &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;sumstats.do&amp;#34;&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;table2-data.tex&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;-&lt;span class=&#34;n&#34;&gt;cleaned&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;dta&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;estimates&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;do&lt;/span&gt;
	stata-se -b &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;estimates.do&amp;#34;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;# Next, produce the three figures. The &amp;#39;%&amp;#39; character can be used as a wildcard:
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;f%.pdf&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;-&lt;span class=&#34;n&#34;&gt;cleaned&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;dta&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;make_figs&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;R&lt;/span&gt;
	Rscript &lt;span class=&#34;s2&#34;&gt;&amp;#34;make_figs.R&amp;#34;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;# Finally, produce the paper (which relies on complete figures and tables):
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;paper.pdf&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;paper&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;tex&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;1.&lt;span class=&#34;n&#34;&gt;pdf&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;2.&lt;span class=&#34;n&#34;&gt;pdf&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;3.&lt;span class=&#34;n&#34;&gt;pdf&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;table&lt;/span&gt;1-&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;tex&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;table&lt;/span&gt;2-&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;tex&lt;/span&gt;
	pdflatex &lt;span class=&#34;s2&#34;&gt;&amp;#34;paper.tex&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, the structure of &amp;ldquo;targets&amp;rdquo; and &amp;ldquo;dependencies&amp;rdquo; is very explicit.
If we want to produce one (or more) of the targets we can call Make with, for
example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ make f1.pdf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will check the rule for producing &lt;code&gt;f1.pdf&lt;/code&gt;, which relies on
&lt;code&gt;data-cleaned.dta&lt;/code&gt; and &lt;code&gt;make_figs.R&lt;/code&gt;. Since there is a rule for the former, it
will try to produce &lt;code&gt;data-cleaned.dta&lt;/code&gt; &lt;em&gt;first&lt;/em&gt;, then produce &lt;code&gt;f1.pdf&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;What happens if we call &lt;code&gt;make f1.pdf&lt;/code&gt; again? Make checks if the file exists (it
does, we just created it), and then exits without doing any redundant work.&lt;/p&gt;
&lt;p&gt;This is all quite convenient, but hardly worth switching to Make for. But wait!
It gets better. Suppose we edit the &lt;code&gt;cleanup.do&lt;/code&gt; file. And ask Make to produce
&lt;code&gt;f1.pdf&lt;/code&gt; again. Make will check if &lt;code&gt;f1.pdf&lt;/code&gt; exists. It does (we just made it).
Next, it will check if the files that were used to produce &lt;code&gt;f1.pdf&lt;/code&gt; have been
updated since &lt;code&gt;f1.pdf&lt;/code&gt; was created. They were not. Next, Make will check if any
of the files used to make &lt;em&gt;those&lt;/em&gt; files were updated since &lt;code&gt;f1.pdf&lt;/code&gt;. And therein
lies the magic of Make&amp;rsquo;s dependency-based structure: Make will realize that
&lt;code&gt;cleanup.do&lt;/code&gt; is newer than &lt;code&gt;f1.pdf&lt;/code&gt;, and it will re-generate &lt;code&gt;data-cleaned.dta&lt;/code&gt;
as a result before re-generating &lt;code&gt;f1.pdf&lt;/code&gt;, because these are the files that
depend on &lt;code&gt;cleanup.do&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;By convention, most Makefiles also include an &lt;code&gt;all&lt;/code&gt; target to create the
&amp;ldquo;default&amp;rdquo; output (for us, the final paper), and a &lt;code&gt;clean&lt;/code&gt; target that removes
all generated files. So in this case we should probably add the following to the
top of the file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;nf&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;paper&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;pdf&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;clean&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;
	rm *.pdf table*-data.tex data-cleaned.dta

&lt;span class=&#34;nf&#34;&gt;.PHONY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;clean&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are a couple of neat features of Make on display here&lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;. Notice that not
all targets require dependencies (in this case, &lt;code&gt;clean&lt;/code&gt;), and that not all
targets have to specify a command (in this case, &lt;code&gt;all&lt;/code&gt; does not). In addition,
I&amp;rsquo;ve added the special &lt;code&gt;.PHONY&lt;/code&gt; target, which tells Make that the &lt;code&gt;clean&lt;/code&gt; and
&lt;code&gt;all&lt;/code&gt; targets don&amp;rsquo;t actually produce files called &lt;code&gt;all&lt;/code&gt; and &lt;code&gt;clean&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, to check if everything works from scratch.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ make clean
$ make
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When you don&amp;rsquo;t specify a target for Make, it looks for the first target
specified (that doesn&amp;rsquo;t start with &lt;code&gt;.&lt;/code&gt;). Since we added &lt;code&gt;all&lt;/code&gt; at the top, it
process this target.&lt;/p&gt;
&lt;h2 id=&#34;more-examples-reproducible-data-sources&#34;&gt;More Examples: Reproducible Data Sources&lt;/h2&gt;
&lt;p&gt;In the first example, I sort of assumed you just started with your &lt;code&gt;data.csv&lt;/code&gt;.
More often than not, however, you have to make it from a variety of sources, and
part of doing reproducible research is documenting your sources in the code. So
you might have something that can be visualized with&lt;/p&gt;
&lt;center&gt;
![A Date Workflow](./images/data-workflow.png)
&lt;/center&gt;
&lt;p&gt;One way you might encode this is with&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;c&#34;&gt;# Get first data source from the internet
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;data-1.dta&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;csv_to_dta&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;py&lt;/span&gt;
	wget http://www.somedatasource.org/datsets/awesome.csv
	python csv_to_dta.py --output&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;data-1.dta awesome.csv

&lt;span class=&#34;c&#34;&gt;# Scrape the second data source using some Python script
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;data-2.dta&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;scrape_site&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;py&lt;/span&gt;
	python scrape_site.py --output&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;data-2.dta &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://www.somedatasource.org/info/results.html&amp;#34;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;# Merge the datasets using a Stata script
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;data-merged.dta&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;-1.&lt;span class=&#34;n&#34;&gt;dta&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;-2.&lt;span class=&#34;n&#34;&gt;dta&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;merge&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;do&lt;/span&gt;
	stata-se -b &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;merge.do&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;a href=&#34;https://www.gnu.org/software/wget/&#34;&gt;Wget&lt;/a&gt; is an useful tool for downloading
files from the command line, by the way. Also, while you don&amp;rsquo;t have to write web
scrapers (or file format converts) in Python, it&amp;rsquo;s probably the easiest way to
do so.&lt;/p&gt;
&lt;h2 id=&#34;more-examples-making-your-project-more-portable&#34;&gt;More Examples: Making Your Project (More) Portable&lt;/h2&gt;
&lt;p&gt;One problem you might encounter with Makefiles is hard-coding in the programs to
compile the scrips. For example, while Stata is called &lt;code&gt;stata-se&lt;/code&gt; on my machine,
it may be simply &lt;code&gt;stata&lt;/code&gt; on your machine. A good way of simplifying the
find-and-replace problem this entails is to define a variable at the top of the
file, say &lt;code&gt;STATA&lt;/code&gt;, that anyone can use to adapt the file to their environment
with minimal effort, e.g.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;c&#34;&gt;# Change this to the location of your Stata executable:
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;STATA&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; stata-se

&lt;span class=&#34;err&#34;&gt;...&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;# First, clean the data using the cleanup script:
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;data-cleaned.dta&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;csv&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cleanup&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;do&lt;/span&gt;
	&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;STATA&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; -b &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;cleanup.do&amp;#34;&lt;/span&gt;

&lt;span class=&#34;c&#34;&gt;# Next, produce the two tables from the cleaned data:
&lt;/span&gt;&lt;span class=&#34;c&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;table1-data.tex&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;-&lt;span class=&#34;n&#34;&gt;cleaned&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;dta&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sumstats&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;do&lt;/span&gt;
	&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;STATA&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; -b &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;sumstats.do&amp;#34;&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;table2-data.tex&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;-&lt;span class=&#34;n&#34;&gt;cleaned&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;dta&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;estimates&lt;/span&gt;.&lt;span class=&#34;n&#34;&gt;do&lt;/span&gt;
	&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;STATA&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; -b &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;estimates.do&amp;#34;&lt;/span&gt;

&lt;span class=&#34;err&#34;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And so on with Python, etc. If your research works with the same script over and
over again (say, a web scraper), but another researcher might replace just this
file (say, replacing &lt;code&gt;scrape.py&lt;/code&gt; with &lt;code&gt;fastscrape.py&lt;/code&gt;), then you could have
something like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span class=&#34;nv&#34;&gt;PYTHON&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; python
&lt;span class=&#34;nv&#34;&gt;SCRAPER&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; fastscrape.py

&lt;span class=&#34;nf&#34;&gt;data-1.dta&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;SCRAPER&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
	&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;PYTHON&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;SCRAPER&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; --output&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;data-1.dta --source&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;http://www.somedatasoure.org/datasets/awesome1.dta&amp;#34;&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;data-2.dta&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;SCRAPER&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;
	&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;PYTHON&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;SCRAPER&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt; --output&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;data-2.dta --source&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;http://www.somedatasoure.org/datasets/awesome2.dta&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And so on.&lt;/p&gt;
&lt;h2 id=&#34;a-word-about-make-vs-knitr&#34;&gt;A Word About Make vs. Knitr&lt;/h2&gt;
&lt;p&gt;Knitr is a tool that allows you to embed runnable R code in LaTeX or Markdown
files so that the code is run and the figures/tables/etc are produced when the
document is compiled (LaTeX to &lt;code&gt;.pdf&lt;/code&gt;, Markdown to &lt;code&gt;.html&lt;/code&gt;). It&amp;rsquo;s a widely-used
tool for literate programming and research papers. I think this is really neat,
but eventually I switched away from it and towards using things like Make
because literate programming/knitr is sort of limited to linear approaches, and
might not reflect more modular projects. It also tends to hang if part of your
project takes a while to run (Matlab simulations, anyone?), which can be a pain
in the ass when you need to wait 10 minutes to see what the new paragraph you
wrote actually looks like in the final PDF. This is exactly the same problem
iPython notebooks have &amp;mdash; great for a step-by-step explanation, but not so
great for a paper where it might actually take a while for things to run.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;It is possible that you are using excel for all of this, but if that&amp;rsquo;s the
case you&amp;rsquo;re probably not interested in this article to begin with. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;On a related Stata note, if you&amp;rsquo;re trying to output tables and regression
results from Stata, the user-written
&lt;a href=&#34;http://repec.org/bocode/e/estout/esttab.html&#34;&gt;esttab&lt;/a&gt; package can be quite
useful. Running &lt;code&gt;esttab&lt;/code&gt; or &lt;code&gt;estout&lt;/code&gt; with the &lt;code&gt;booktabs fragment&lt;/code&gt; options
work very nicely in my opinion. &lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;At least in conjunction with &lt;a href=&#34;http://ggplot2.org/&#34;&gt;ggplot2&lt;/a&gt;, anyway.
&lt;code&gt;install.packages(&amp;quot;ggplot2&amp;quot;)&lt;/code&gt;, please. &lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Pro Stata tip: you can use &lt;code&gt;shell&lt;/code&gt; to exectue unix-style commands from
within Stata. So for example to compile a downstream LaTeX document you can
use &lt;code&gt;shell pdflatex paper.tex&lt;/code&gt;. &lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Make is available on all Unix-like systems (Mac OS X, Linux, BSDs), and
there is also
&lt;a href=&#34;http://gnuwin32.sourceforge.net/packages/make.htm&#34;&gt;a version available for Windows&lt;/a&gt;. &lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:6&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;Also, note that &lt;code&gt;rm&lt;/code&gt; is the Unix command for removing files, and the &lt;code&gt;*&lt;/code&gt;
character serves as a wildcard when using that program. &lt;a href=&#34;#fnref:6&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
    </content>
    
    
    <category term="data"/>
    <category term="econ"/>
    <category term="reproducible research"/>
  </entry>
  <entry>
    <title type="html">Parsing tape data with Python</title>
    
    <link href="https://unconj.ca/blog/parsing-tape-data-with-python.html" rel="alternate"/>
    <published>2014-02-18T00:00:00Z</published>
    
    
    <updated>2014-02-18T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2014-02-18:blog/parsing-tape-data-with-python.html</id>
    
    <content type="html" xml:lang="en">
      &lt;!-- summary: Python is really good a certain things R and Stata are not intuitively strong with. One of those things is string and file manipulation, which I recently had to deal with when going through some National Health Institute data. Luckily, I was able to create a nice system for converting older tape data to ``.csv`` files in Python. --&gt;
&lt;p&gt;Recently I had to use an older dataset that hadn&amp;rsquo;t been nicely sanitized into
something that Stata or Pandas could understand. In particular, I was working
with the NHANES I Epidemiologic Follow-up Study&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, which has data available
only in the original tape format from the 1980s and early 1990s. An individual
record from one of the smaller files looks like this (scroll right for the full
effect):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;9220809          511     12           0112         996102410232091442411  1 2      9                                                         486 21400520   230031142750215185031486 0                                                                                                                                                           03 42750486 051850
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Where every number might be a single variable or part of a multi-column
variable. For example, the first two digits are the year the individual died,
followed by a five-digit identification number. In other words, it&amp;rsquo;s impossible
to decipher without digging into the original documentation. This kind of data
is very hard to read into a statistics package (or Excel, for the less
ambitious) in this format &amp;mdash; but never to fear! It turns out to be quite simple
to parse these files in Python and output something that more high-level tools
&lt;em&gt;can&lt;/em&gt; understand.&lt;/p&gt;
&lt;p&gt;For reference, I&amp;rsquo;m going to be using the public data files and documentation
provided by the Centers for Disease Control
&lt;a href=&#34;http://www.cdc.gov/nchs/nhanes/nhefs/nhefspuf.htm&#34;&gt;on their website&lt;/a&gt;. In
particular, I&amp;rsquo;ll use
&lt;a href=&#34;ftp://ftp.cdc.gov/pub/Health_Statistics/NCHS/Datasets/NHEFS/N92mort.txt&#34;&gt;the data&lt;/a&gt;
from the 1992 NHEFS Mortality survey and
&lt;a href=&#34;http://www.cdc.gov/nchs/data/nhanes/nhefs/1992mort.pdf&#34;&gt;its accompanying documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;extracting-a-simple-variable&#34;&gt;Extracting a simple variable&lt;/h2&gt;
&lt;p&gt;What we really want to do is convert the column(s) that correspond to a
particular variable into something that we can move around in Python (or output
so we can use it with another program). The documentation for the &lt;code&gt;education&lt;/code&gt;
field, for example, looks like this::&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   Tape  Field
   Pos.  Size   Variable Description and Codes

52-53      2    Education

                  00        ...  No formal education
                  01-08     ...  Years of elementary school
                  09        ...  1 year of high school
                  10        ...  2 years of high school
                  11        ...  3 years of high school
                  12        ...  4 years of high school
                  13        ...  1 year of college
                  14        ...  2 years of college
                  15        ...  3 years of college
                  16        ...  4 years of college
                  17        ...  5 or more years of college
                  99        ...  Not stated

                  (Note: This information is only available for deaths
                  occurring in 1989 and later.  For earlier years, this
                  field will be blank.)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Parsing a line with this kind of documentation in Python is really quite easy if
you make use of slicing. It&amp;rsquo;s likely that you don&amp;rsquo;t need to differentiate
between &amp;lsquo;Not stated&amp;rsquo; and &amp;lsquo;missing due to being before 1989&amp;rsquo;, so the &lt;code&gt;blank&lt;/code&gt; and
&lt;code&gt;99&lt;/code&gt; entries are the same from your perspective. Since a CSV file usually
represents missing data with an empty string, we can extract the &lt;code&gt;education&lt;/code&gt;
variable from a line in the tape with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;51&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;53&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;  &amp;#39;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;99&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;elif&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;00&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lstrip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Although there are of other ways to accomplish this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# If you need to remove the leading zeros and don&amp;#39;t mind converting str -&amp;gt; int -&amp;gt; str&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;51&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;53&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;  &amp;#39;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;99&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Using `replace`; leaves in the leading zeros&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;51&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;53&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;replace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;replace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;99&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Another simple example might be the &lt;code&gt;sex&lt;/code&gt; variable:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   Tape  Field
   Pos.  Size   Variable Description and Codes

   59      1    Sex

                  1         ...  Male
                  2         ...  Female
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;which can be extracted from a line and converted to a dummy variable for female
participants with&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Represent with 0 = male, 1 = female&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;female&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;58&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;converting-categorical-variables-to-dummy-variables&#34;&gt;Converting categorical variables to dummy variables&lt;/h2&gt;
&lt;p&gt;Often it may be of interest to convert a categorical variable like &lt;code&gt;race&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   Tape  Field
   Pos.  Size   Variable Description and Codes

   62      1    Race Recode #1 (*)

                  1         ...  White
                  2         ...  Races other than white or black
                  3         ...  Black
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Into a series of dummy variables (i.e. &lt;code&gt;white&lt;/code&gt;, &lt;code&gt;black&lt;/code&gt;, &lt;code&gt;other_race&lt;/code&gt;). This is
also fairly easy to do with some ternary operators:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;n&#34;&gt;white&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;61&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;black&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;61&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;3&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;other_race&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;61&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;2&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As a slightly more complex example, consider the entries for marital status:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;   Tape  Field
   Pos.  Size   Variable Description and Codes

   77      1    Marital Status

                  1         ...  Never married, single
                  2         ...  Married
                  3         ...  Divorced
                  4         ...  Widowed
                  8         ...  Marital status not on certificate
                  9         ...  Marital status not stated
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We might want the dummies for &lt;code&gt;married&lt;/code&gt;, &lt;code&gt;widowed&lt;/code&gt;, &lt;code&gt;divorced&lt;/code&gt;, and &lt;code&gt;single&lt;/code&gt; to
be empty (as opposed to zero) when we have either of the last two conditions.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;76&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;8&amp;#39;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;76&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;9&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;married&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;single&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;divorced&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;widowed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;single&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;76&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;married&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;76&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;2&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;divorced&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;76&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;3&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;widowed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;76&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;4&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;the-full-example&#34;&gt;The full example&lt;/h2&gt;
&lt;p&gt;If we stuff all of this into a single function that will extract variables from
a line, it might look something like the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;convert_record_to_csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;# Identifier used by the survey&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;seqnum&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lstrip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    
    &lt;span class=&#34;c1&#34;&gt;# Year and month of death (day is not always provided)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;y_death&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;19&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%s&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;m_death&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;54&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;56&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
    
    &lt;span class=&#34;c1&#34;&gt;# Sex&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;female&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;58&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;# Marriage&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;76&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;8&amp;#39;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;or&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;76&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;9&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;married&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;single&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;divorced&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;widowed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;single&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;76&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;married&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;76&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;2&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;divorced&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;76&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;3&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;widowed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;76&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;4&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;# Education&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;51&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;53&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;  &amp;#39;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;99&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;# Autopsy&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;autopsy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;83&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;0&amp;#39;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;autopsy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;autopsy&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;83&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;8&amp;#39;&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;83&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;9&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;# Race&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;white&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;61&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;black&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;61&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;3&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;other_race&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;61&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;2&amp;#39;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;, &amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;join&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seqnum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y_death&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;m_death&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;female&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;educ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;autopsy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;white&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;black&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;other_race&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;single&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;married&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;divorced&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;widowed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)])&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can then write a pretty simple script to convert the raw tape data (provided
by the CDC as &lt;code&gt;N92mort.txt&lt;/code&gt;) into a &lt;code&gt;.csv&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;N92mort.txt&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;out.csv&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    
    &lt;span class=&#34;c1&#34;&gt;# Write column names, as per CSV convention&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;seqnum, y_death, m_death, female, educ, autopsy, white, black, other_race, single, married, divorced, widowed&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    
    &lt;span class=&#34;c1&#34;&gt;# Loop over each line in the source file&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;enumerate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;source&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;dest&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;convert_record_to_csv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;Exception&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;c1&#34;&gt;# It may be helpful for debugging to know which line the parser failed at&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Failed at record &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%d&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;.&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course, I&amp;rsquo;m not parsing every single variable in the data set (there are over
400 columns in the mortality data alone, and more than 4000 in the interview
data), but in principle this same method could be used.&lt;/p&gt;
&lt;section class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34; role=&#34;doc-endnote&#34;&gt;
&lt;p&gt;National Center for Health Statistics. &lt;em&gt;Data File Documentation, NHANES I
Epidemiologic Followup Study (NHEFS)&lt;/em&gt;, National Center for Health
Statistics. Hyattsville, Maryland. &lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;

    </content>
    
    
    <category term="data"/>
    <category term="python"/>
  </entry>
  <entry>
    <title type="html">Moving to Pelican</title>
    
    <link href="https://unconj.ca/blog/moving-to-pelican.html" rel="alternate"/>
    <published>2014-02-12T00:00:00Z</published>
    
    
    <updated>2014-02-12T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2014-02-12:blog/moving-to-pelican.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;I recently moved the site over to &lt;a href=&#34;http://blog.getpelican.com/&#34;&gt;Pelican&lt;/a&gt;.
Although I liked Octopress, it wasn&amp;rsquo;t working exactly like I wanted it to, and
I&amp;rsquo;m not comfortable enough working with Ruby to modify it. Since Python has
become my go-to language for most things these days, it made sense to move to
what seems to be the most popular static site generator written in that
language. For posteriority&amp;rsquo;s sake, the following is a guide based on the steps I
took to get it working. I&amp;rsquo;ve also included most of my configuration files and a
short program for creating new posts.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation&lt;/h2&gt;
&lt;p&gt;First, you will need to install Python. Then, you will need &lt;code&gt;pip&lt;/code&gt;, which is
used to install third-party Python programs and modules. Once you have both of
these, you can run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ pip install pelican
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;from a terminal. This shouldn&amp;rsquo;t take too long, since Pelican is written in pure
Python and has few dependencies. Now, navigate to where you&amp;rsquo;d like to put your
blog (say, the directory &lt;code&gt;myblog&lt;/code&gt;) and run::&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ pelican-quickstart
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will ask you several questions. Generally, if you don&amp;rsquo;t understand the
question, just answer &lt;code&gt;n&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;configuration--theme&#34;&gt;Configuration &amp;amp; Theme&lt;/h2&gt;
&lt;p&gt;My configuration file at the moment looks something like the following&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;n&#34;&gt;AUTHOR&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Aaron Jacobs&amp;#39;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;AUTHOR_EMAIL&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;atheriel@gmail.com&amp;#39;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;SITENAME&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Unconstant Conjunction&amp;#39;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;SITEURL&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;TAGLINE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;most python and pcg&amp;#39;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;DEFAULT_CATEGORY&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Uncategorized&amp;#39;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;DEFAULT_LANG&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;u&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;en&amp;#39;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;SUMMARY_MAX_LENGTH&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;120&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Feed generation is usually not desired when developing&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;FEED_ALL_ATOM&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;None&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;CATEGORY_FEED_ATOM&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;None&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;TRANSLATION_FEED_ATOM&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;None&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Social widget&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;SOCIAL&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;github&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;https://github.com/atheriel&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;DEFAULT_PAGINATION&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Uncomment following line if you want document-relative URLs when developing&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;RELATIVE_URLS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;True&lt;/span&gt;

&lt;span class=&#34;c1&#34;&gt;# Theme -- Pure Single&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;THEME&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;pure-single&amp;#39;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;CSS_FILE&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;pure.css&amp;#39;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;COVER_IMG_URL&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;http://dnqgz544uhbo8.cloudfront.net/_/fp/img/home/11.WVgzJf1Jz5x9uuR7KjWjXw.jpg&amp;#39;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;PROFILE_IMG_URL&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;https://1.gravatar.com/avatar/eee1ad9206b3858a0ff49ade9983d8f4?s=128&amp;#39;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;MENUITEMS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;About&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;/pages/about-me.html&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Archives&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;archives.html&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;m using a modified version of the
&lt;a href=&#34;https://github.com/PurePelicanTheme/pure-single&#34;&gt;Pure theme&lt;/a&gt;, which I&amp;rsquo;ve placed
in the &lt;code&gt;pure-single&lt;/code&gt; directory. Note that you&amp;rsquo;ll need to fill in the &lt;code&gt;SITEURL&lt;/code&gt;
with your own domain.&lt;/p&gt;
&lt;h2 id=&#34;creating-new-posts&#34;&gt;Creating New Posts&lt;/h2&gt;
&lt;p&gt;Unlike Octopress, Pelican doesn&amp;rsquo;t come with a prepackaged solution to creating
new posts and pages. To remedy this, I whipped up a small program to do so,
which I&amp;rsquo;ve also published as a &lt;a href=&#34;https://gist.github.com/atheriel/8966411&#34;&gt;gist&lt;/a&gt;.
The script expects to reside in the root directory of your blog; the code should
be pretty self-explanatory if you want to modify this, however. Notice that the
configuration file above contains an &amp;ldquo;About Me&amp;rdquo; page &amp;ndash; you can create one for
yourself with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ python newpost.py &lt;span class=&#34;s1&#34;&gt;&amp;#39;About Me&amp;#39;&lt;/span&gt; --page
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The full script is as follows. Note that it uses &lt;a href=&#34;http://docopt.org&#34;&gt;Docopt&lt;/a&gt;
instead of the hell that is &lt;code&gt;argparse&lt;/code&gt;, which you may need to install
beforehand.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;ch&#34;&gt;#!/usr/bin/env python&lt;/span&gt;

&lt;span class=&#34;vm&#34;&gt;__doc__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&amp;#39;
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;Create a new post/page.
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;Usage:
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;  newpost.py &amp;lt;title&amp;gt; [--page] [-t &amp;lt;tag&amp;gt;...]
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;  newpost.py -h | --help | --version
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;Options:
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;  --page           Create a &amp;#39;page&amp;#39; as opposed to a &amp;#39;post&amp;#39;.
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;  -t, --tags       Specify the tags for the page/post.
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;  -v, --version    Show version information and exit.
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;  -h, --help       Show this help and exit.
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;template&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&amp;#39;{title}
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;{title_underline}
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;:date: {date}
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;:tags: {tags}
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;:author: {author}
&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;

&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;os&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sys&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;os.path&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;datetime&lt;/span&gt; 
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;docopt&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;docopt&lt;/span&gt;

&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;pelicanconf&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# To get the blog author&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;docopt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__doc__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;today&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;date&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;today&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    
    &lt;span class=&#34;c1&#34;&gt;# Locate the blog directory and check that `content` exists&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;cwd&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dirname&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;realpath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;vm&#34;&gt;__file__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;assert&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exists&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cwd&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;/content&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    
    &lt;span class=&#34;c1&#34;&gt;# Generate a file from title + date in the blog&amp;#39;s content directory&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;--page&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;join&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cwd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;content/{0}-{1}.rst&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;today&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;title&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lower&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;replace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;-&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;replace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exists&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cwd&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;/content/pages&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mkdir&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cwd&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;/content/pages&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;join&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cwd&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;content/pages/{0}.rst&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;title&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lower&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;replace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;-&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;replace&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;
    
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;os&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;path&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exists&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Error: A file for that title already exists.&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;exit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;template&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;title&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;title&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;title_underline&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;#&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;title&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]),&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;tags&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;, &amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;join&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;t&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;lower&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;t&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;tag&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]])&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;tag&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;None&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;date&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;today&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;author&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pelicanconf&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AUTHOR&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
    </content>
    
    
    <category term="meta"/>
    <category term="python"/>
  </entry>
  <entry>
    <title type="html">Writing a Web Scraper</title>
    
    <link href="https://unconj.ca/blog/writing-a-web-scraper.html" rel="alternate"/>
    <published>2014-01-27T00:00:00Z</published>
    
    <updated>2014-02-12T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2014-01-27:blog/writing-a-web-scraper.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;Okay, so I know everyone&amp;rsquo;s written some kind of web scraper in their time, but
I&amp;rsquo;m still proud of myself for
&lt;a href=&#34;https://github.com/atheriel/galleryscraper&#34;&gt;my own take on the subject&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Recently, I saw an
&lt;a href=&#34;http://pythonadventures.wordpress.com/2013/11/08/extracting-relevant-images-from-xxx-galleries-using-text-clustering/&#34;&gt;interesting&lt;/a&gt;
post on Reddit that provided some source code for scraping images based on the
similarity of their names. This might be useful for downloading all of the
images in a gallery (for example, if you want to keep something posted on Imgur)
without having to follow all of the links by hand. However, there was quite a
lot of it missing, it relied on some random site, and it was bad at handling all
kinds of common use cases: for example, thumbnails.&lt;/p&gt;
&lt;p&gt;So I rewrote it. And expanded it. Massively. The current usage output is&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Usage:
  galleryscraper.py URL DIR [--threads N --log-level N -q -s]
  galleryscraper.py -h | --help | --version

Options:
      --threads N        the number of threads to use [default: 4]
  -V, --log-level N      the level of info logged to the console, which can be
                         one of INFO, DEBUG, or WARNING [default: INFO]
  -s, --skip-duplicates  ignore files that have been downloaded already
  -q, --quiet            suppress output to console
  -v, --version          show program&#39;s version number and exit
  -h, --help             show this help message and exit
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In particular, I worked out a clever way of dealing with thumbnails. Often, a
gallery of thumbnails each link to a page containing ads, etc, with one large
image (the one you actually want) in the centre. So I figured if one found the
image on the page with the largest &lt;code&gt;content-length&lt;/code&gt;, this would be the image in
mind. This technique seems to work extremely well.&lt;/p&gt;
&lt;p&gt;Mostly, this was an opportunity to learn about some gaps in my programming
experience. First and foremost is how HTML requests actually work (success), but
I also learned a lot of parallelization and Python decorators. I made use of the
excellent (and pretty standard at this point) Python libraries
&lt;a href=&#34;http://docs.python-requests.org/&#34;&gt;Requests&lt;/a&gt; and
&lt;a href=&#34;http://www.crummy.com/software/BeautifulSoup/&#34;&gt;BeautifulSoup&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The script itself has a couple of interesting features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;I write really, really well-documented code. It helps me keep track of what
goes on, explain (and the improve) my approach, and it often comes in handy
when I got back and try to figure out what&amp;rsquo;s going on. This should make it
really easy to read the code itself.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The script contains no classes. Everything is a function, and functions are
designed to have manageable side effects. I certainly haven&amp;rsquo;t been converted
to functional programming, but I have become pretty irritated by the
everything-must-be-a-class paradigm. This script is essentially a big function
that turns a web page into a directory of images. If anyone&amp;rsquo;s interested in
the things that go into accomplishing that, they might just benefit from the
functions in the script itself. I&amp;rsquo;ve also seen the light that is
&lt;code&gt;namedtuples&lt;/code&gt;, which makes the return value of more complex functions much
more manageable.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I learned to love decorators. No, seriously. I had never really thought of a
use for them before, but here such uses turned up in abundance. I&amp;rsquo;m under the
impression that this will have a big impact on how I think about writing code
in Python going forward.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My favourite decorator at the moment:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;sessional&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;    Decorator that maintains the same session for URL requests within the given
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;    function. It relies on the wrapped function taking a ``session`` keyword
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;    argument. At the moment this is only used for the safe_request function,
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;    but if timeouts are not a problem it can be used to wrap all of the other
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;    functions that make requests instead.
&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;    &amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;session&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;requests&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Session&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;session&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mount&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;http://&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;HTTPAdapter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;max_retries&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;session&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;headers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;User-Agent&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11&amp;#39;&lt;/span&gt;
    
    &lt;span class=&#34;nd&#34;&gt;@wraps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;newfunc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kwargs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;c1&#34;&gt;# Replace sessions in the function&amp;#39;s (kw) arguments&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;kwargs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;session&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;session&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;KeyError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;pass&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;kwargs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;newfunc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course, there are still some edge cases. The script works very well most of
the time, but some things are still tripping it up. Usually this is due to the
images you want having different names, for example when some kind of random
hash is appended to them.&lt;/p&gt;
&lt;p&gt;In the future, I may make the script accept a file of URLs and directories,
similar to how &lt;code&gt;crontab&lt;/code&gt; works. I&amp;rsquo;m also looking in to working out when the
page linked to by the thumbnail has multiple sizes of image &amp;ndash; i.e. the &lt;em&gt;Small -
Medium - Large - Original&lt;/em&gt; header &amp;ndash; and getting the image of the desired size.&lt;/p&gt;
    </content>
    
    
    <category term="projects"/>
    <category term="python"/>
  </entry>
  <entry>
    <title type="html">IRC Hybrid on Arch Linux</title>
    
    <link href="https://unconj.ca/blog/irc-hybrid-on-arch-linux.html" rel="alternate"/>
    <published>2013-12-01T00:00:00Z</published>
    
    
    <updated>2013-12-01T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2013-12-01:blog/irc-hybrid-on-arch-linux.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;I recently tried to get an IRC server working on an installation of Arch Linux,
and it failed to work &amp;ldquo;out of the box&amp;rdquo;. Below are the steps I took to get it
working, including the work I did to get an SSL connection up and running.&lt;/p&gt;
&lt;p&gt;First, get the package from the AUR::&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ &lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; ~/builds &lt;span class=&#34;c1&#34;&gt;# or wherever else you like to put builds&lt;/span&gt;
$ curl -O https://aur.archlinux.org/packages/ir/ircd-hybrid/ircd-hybrid.tar.gz
$ tar -xvzf ircd-hybrid.tar.gz &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; ircd-hybrid
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As of writing, simply installing this will cause the daemon to fail because it
cannot find the &lt;code&gt;.la&lt;/code&gt; files for the modules. To fix this you need to prevent the
&lt;code&gt;.la&lt;/code&gt; files from being removed. Open the &lt;code&gt;PKGBUILD&lt;/code&gt; file and add:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;options=(&amp;quot;libtool&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;then build and install the package:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ makepkg -s
$ pacman -U ircd-hybrid-8.1.1-5-x86_64.pkg.tar.xz
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;you should now be able to run the service with &lt;code&gt;systemctl start ircd-hybrid&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;setting-up-ssl&#34;&gt;Setting up SSL&lt;/h2&gt;
&lt;p&gt;I mostly lifted this from the guide
&lt;a href=&#34;http://www.electropepper.org/item/irc-server-ssl-services-how-to-build-your-own%3E&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To set up the server to run over SSL, you need to create the certificates and
keys as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ &lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; /etc/ircd-hybrid/ssl
$ openssl genrsa -out rsa.key &lt;span class=&#34;m&#34;&gt;2048&lt;/span&gt;
$ openssl req -new -days &lt;span class=&#34;m&#34;&gt;365&lt;/span&gt; -x509 -key rsa.key -out cert.pem
$ openssl dhparam -out dhparam.pem &lt;span class=&#34;m&#34;&gt;2048&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Fair warning: the last command can take several minutes to run. Afterwards you
will need to make these files visible to the &lt;code&gt;ircd&lt;/code&gt; user, since this is the user
associated with the daemon::&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ &lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; ..
$ chown -hR ircd ssl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The next is to enable SSL correctly in the &lt;code&gt;/etc/ircd-hybrid/ircd.conf&lt;/code&gt; file. In
the &lt;code&gt;listen&lt;/code&gt; section make sure to have the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;host = &amp;quot;0.0.0.0&amp;quot;;
#port = 6667; /* Only include this line if you want to allow non-SSL connections on another port. */
flags = ssl;
port = 6697;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can modify the port number; &lt;code&gt;6697&lt;/code&gt; seems to be the standard, and is used by
Freenode. In the &lt;code&gt;serverinfo&lt;/code&gt; section, make sure to indicate the location of the
files that you&amp;rsquo;ve just created::&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;rsa_private_key_file = &amp;quot;/etc/ircd-hybrid/ssl/rsa.key&amp;quot;;
ssl_certificate_file = &amp;quot;/etc/ircd-hybrid/ssl/cert.pem&amp;quot;;
ssl_dh_param_file = &amp;quot;/etc/ircd-hybrid/ssl/dhparam.pem&amp;quot;;
ssl_server_method = tlsv1, sslv3;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once these changes have been made, save the configuration file and restart the
daemon with &lt;code&gt;systemctl start ircd-hybrid&lt;/code&gt;. You can check if the service is
properly exposed to the outside world with &lt;code&gt;netstat -an | grep -i &#39;6697&#39;&lt;/code&gt;, which
should give a result like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tcp        0      0 0.0.0.0:6697            0.0.0.0:*               LISTEN
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;if the port you are using is indeed &lt;code&gt;6697&lt;/code&gt;.&lt;/p&gt;
    </content>
    
    
    <category term="linux"/>
    <category term="irc"/>
  </entry>
  <entry>
    <title type="html">Using More Interesting Random Values in Procedural Content</title>
    
    <link href="https://unconj.ca/blog/using-more-interesting-random-values-in-procedural-content.html" rel="alternate"/>
    <published>2013-10-16T00:00:00Z</published>
    
    
    <updated>2013-10-16T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2013-10-16:blog/using-more-interesting-random-values-in-procedural-content.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;This post is an inquiry into some of the drawbacks with using the &lt;code&gt;random()&lt;/code&gt;
function to generate all your random values, and discusses the circumstances in
which the Beta distribution might prove a compelling alternative. It is written
with procedural games in mind, there is no expectation that the reader know what
a &amp;lsquo;distribution&amp;rsquo; is, and all of the code examples are written in Python.&lt;/p&gt;
&lt;h2 id=&#34;the-shortcomings-of-the-uniform-distribution&#34;&gt;The Shortcomings of the Uniform Distribution&lt;/h2&gt;
&lt;p&gt;Most of the time I see tutorials on generating procedural content, whenever a
random value is needed a call is made to the default generator (in Python, this
is probably the one from the &lt;code&gt;random&lt;/code&gt; module). So if we want to have a random
number of chests in a room, you might see something like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;random&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;r&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;101&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;randint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;## 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which gives a number of chests in {1, 2, 3}, with an equal chance of each. Or,
we might trigger an event with 90% probability with something like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;101&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;random&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
	&lt;span class=&#34;k&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Event happened.&amp;#39;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
	&lt;span class=&#34;k&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Event did not happen.&amp;#39;&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;## Event happened.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In a setting where we might want to have an enemy with a variable amount of
health, you could see something like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;102&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;monster_health&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3000&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;randint&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;## monster_health = 4148&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But inevitably, these examples are constructed to use random values from
&lt;em&gt;uniform&lt;/em&gt; distributions. That is, every integer in the range of &lt;code&gt;a&lt;/code&gt; to &lt;code&gt;b&lt;/code&gt; has
an equal chance of being output by the &lt;code&gt;randint(a,b)&lt;/code&gt; function, and the mean
value is exactly &lt;code&gt;a + b / 2&lt;/code&gt;. So, in the example above, we can expect the
average monster to have about 4500 health, and expect to see monsters with
4000-4500 health exactly as often as those with 4500-5000. But what if you
wanted most monsters to have a health value close to 4500, and only a few with
low values near 4000 or high values near 5000? This becomes a very difficult
thing to do with only the uniformly-distributed &lt;code&gt;r.random()&lt;/code&gt; and &lt;code&gt;r.randint()&lt;/code&gt;
functions very quickly.&lt;/p&gt;
&lt;h2 id=&#34;maybe-the-normal-distribution-is-the-answer&#34;&gt;Maybe the Normal Distribution is the Answer?&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;ve ever been exposed to any introductory statistics, you&amp;rsquo;ve probably
heard of the &lt;em&gt;normal&lt;/em&gt; (or Gaussian) distribution, which might get us exactly
what we want. A random function that gets its values from a normal distribution
has most values clustered close to a specified mean, with a specified spread (or
variance). It is quite easy to ensure that, for example, 99.7% of the values
will fall within the range 4000-5000, with 68% of them falling within the range
of about 4350-4650. Sounds great, right?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;103&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;monster_health_list&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;xrange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
	&lt;span class=&#34;n&#34;&gt;monster_health_list&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gauss&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mu&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4500&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sigma&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;500&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;monster_health&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;## [4681, 4475, 4447, 4234, 4514, 4565, 4432, 4449, 4242, 4735]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The reason the &lt;code&gt;sigma&lt;/code&gt; parameter is &lt;code&gt;500 / 3&lt;/code&gt; in this case is because for normal
distributions, 99.7% of values far within three &amp;lsquo;sigmas&amp;rsquo; of the mean (which is
called &lt;code&gt;mu&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;So far, so good. However, normal distributions have the inconvenient property of
returning &lt;strong&gt;any&lt;/strong&gt; value on occasion. It would be quite possible (although
improbable) for a player to run into a monster with negative health, or a health
value of 50,000. So if you&amp;rsquo;re going to use the normal distribution, make sure to
have some checks for these unlikely cases.&lt;/p&gt;
&lt;p&gt;Yet a normal distribution may leave some things to be desired. Say we wanted
monsters to have health values in the range 4000-4500 more often than 4500-5000?
Or we wanted most monsters to have health values in the low 4000s or high 4000s,
but very few in between? If the latter scenario doesn&amp;rsquo;t seem that desirable,
consider an analogous problem: we want to generate a random number of monsters
for each room in our dungeon, but want most rooms to be either empty or
relatively full &amp;ndash; with few &amp;lsquo;easy&amp;rsquo; rooms in between.&lt;/p&gt;
&lt;p&gt;All of these problems can be solved using the remarkable
&lt;a href=&#34;http://en.wikipedia.org/wiki/Beta_distribution%3E&#34;&gt;Beta distribution&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-beta-distribution-and-why-you-should-use-it&#34;&gt;The Beta Distribution and Why You Should Use It&lt;/h2&gt;
&lt;p&gt;The Beta distribution takes two parameters &amp;ndash; &lt;code&gt;alpha&lt;/code&gt; and &lt;code&gt;beta&lt;/code&gt; &amp;ndash; and outputs
values between 0 and 1. This means we don&amp;rsquo;t need to worry about occasionally
producing extremely large or small values. Also, the mean is always &lt;code&gt;alpha / (alpha + beta)&lt;/code&gt;, so it is easy to figure out what the average value will be.&lt;/p&gt;
&lt;p&gt;What makes the Beta distribution interesting is that the two parameters give it
a wide variety of &amp;lsquo;shapes&amp;rsquo;. It is because of the flexibility of the Beta
distribution to take on different &amp;lsquo;shapes&amp;rsquo; that it can be so useful:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;When &lt;code&gt;alpha = beta = 1&lt;/code&gt;, the Beta distribution is identical to the uniform
distribution. That is, it will produce the same values as the &lt;code&gt;random()&lt;/code&gt;
function.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When &lt;code&gt;alpha = beta&lt;/code&gt;, the mean is exactly 0.5, and there is a equal chance that
values will fall above and below the mean. As &lt;code&gt;alpha&lt;/code&gt; and &lt;code&gt;beta&lt;/code&gt; grow larger,
values move closer and closer to the mean.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When &lt;code&gt;alpha &amp;gt; beta&lt;/code&gt;, more values will be generated below the mean, and vice
versa.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When &lt;code&gt;alpha &amp;lt; 1&lt;/code&gt; and/or &lt;code&gt;beta &amp;lt; 1&lt;/code&gt;, more values will be generated near 0 and 1
than near the mean. As &lt;code&gt;alpha&lt;/code&gt; or &lt;code&gt;beta&lt;/code&gt; gets closer and closer to zero, it
becomes more and more unlikely that values away from 0 and 1 will be
generated.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Beta distribution is extremely popular in some fields of (social) science,
and so it is no surprise that the standard library has an implementation in the
&lt;code&gt;random&lt;/code&gt; module, the function &lt;code&gt;betavariate(alpha, beta)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The problem I proposed with filling rooms in a dungeon with monsters could be
solved with code as simple as the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# A dungeon has ten rooms, with up to 50 monsters in each.&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# We want most rooms to have a large number of monsters in&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# them, or be almost empty.&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;107&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;monsters_in_rooms&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;xrange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
	&lt;span class=&#34;n&#34;&gt;monsters_in_rooms&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;betavariate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mf&#34;&gt;0.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;monsters_in_rooms&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;## [0, 49, 45, 49, 5, 49, 0, 48, 0, 25]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice that since &lt;code&gt;betavariate()&lt;/code&gt; returns values between 0 and 1, I simply
multiplied by the number I actually wanted. The parameters are &lt;code&gt;alpha = beta = 0.1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To get more monsters with 4000-4250 health than 4250-5000 health, try:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Monsters have an average of 4500 health. With alpha = 1&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# and beta = 3, the betavariate() will return values with&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# a mean of 0.25. So we multiply by 1000, and add 4000.&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;105&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;health_list&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;xrange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;15&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
	&lt;span class=&#34;n&#34;&gt;health_list&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;betavariate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;health&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;## [4054, 4023, 4430, 4172, 4415, 4253, 4045, 4135, 4056, 4035, 4005, 4172, 4072, 4296, 4395]&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;health&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;15&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;## 4170&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you wanted values closer to &lt;code&gt;4250&lt;/code&gt; itself, simply increase &lt;code&gt;alpha&lt;/code&gt; and &lt;code&gt;beta&lt;/code&gt;
without changing their ratio.&lt;/p&gt;
&lt;p&gt;And finally, to get something like the normal distribution solution we had
earlier, try:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Monsters have an average of 4500 health, with a range of&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;# 4000-5000. So we multiply by 1000, and add 4000.&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;115&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;health_list&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;xrange&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
	&lt;span class=&#34;n&#34;&gt;health_list&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;betavariate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;health_list&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;## [4194, 4571, 4162, 4334, 4564, 4551, 4324, 4363, 4450, 4193]&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;print&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;sum&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;health_list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;15&lt;/span&gt;
&lt;span class=&#34;c1&#34;&gt;## 4370&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In a future post I will show how to use the Dirichlet distribution to solve
another kind problem that shows up in procedural content generation.&lt;/p&gt;
    </content>
    
    
    <category term="pcg"/>
    <category term="python"/>
  </entry>
  <entry>
    <title type="html">An Update on the Libnoise Wrapper</title>
    
    <link href="https://unconj.ca/blog/an-update-on-the-libnoise-wrapper.html" rel="alternate"/>
    <published>2013-10-02T00:00:00Z</published>
    
    
    <updated>2013-10-02T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2013-10-02:blog/an-update-on-the-libnoise-wrapper.html</id>
    
    <content type="html" xml:lang="en">
      &lt;center&gt;
![NoisyPy Perlin Demo](./images/noisypy-perlin.png)
&lt;/center&gt;
&lt;p&gt;I&amp;rsquo;ve gotten a good chunk of the Libnoise wrapper working. And despite several
sessions of head-against-wall bugs, my SIP and &lt;code&gt;disutils&lt;/code&gt; setup seems to be
working nicely. Some of the C++ code in &lt;code&gt;noiseutils.h&lt;/code&gt; (which comes with the
Libnoise examples) is quite outdated, so I wrote several of my own output
functions in pure C++. This also gave me the opportunity to write exporters to
OpenGL textures, which seem to work seamlessly with
&lt;a href=&#34;http://www.pyglet.org/&#34;&gt;Pyglet&lt;/a&gt;. I should have a whole directory of examples
up and running shortly, drawing from the standard Libnoise examples and as well
as demonstrations of OpenGL textures.&lt;/p&gt;
&lt;p&gt;At the moment, the code to produce the image in this post looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;noisypy.modules&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;nmods&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;noisypy.util&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;nutil&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nmods&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Perlin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;113&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nmods&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ScaleBias&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SetSourceModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;p&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;scale&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.5&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bias&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.5&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nmods&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Clamp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bounds&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SetSourceModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;nutil&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;noisemap_image&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;512&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;512&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;filename&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;lolnoise.pgm&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;which produces identical results to analagous code written in C++. This is an
illustration of the wonderful interface that libnoise provides, and of how I
think it has translated nicely to Python. I&amp;rsquo;ve decided to call the library
&lt;code&gt;noisypy&lt;/code&gt;, and it should appear on GitHub in the near future.&lt;/p&gt;
    </content>
    
    
    <category term="pcg"/>
    <category term="projects"/>
    <category term="python"/>
  </entry>
  <entry>
    <title type="html">Setting up GDB for Debugging Python on OS X</title>
    
    <link href="https://unconj.ca/blog/setting-up-gdb-for-debugging-python-on-os-x.html" rel="alternate"/>
    <published>2013-09-30T00:00:00Z</published>
    
    
    <updated>2013-09-30T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2013-09-30:blog/setting-up-gdb-for-debugging-python-on-os-x.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;&lt;em&gt;Note: this post can be read as a series of terminal commands if you&amp;rsquo;re not
interested in the intervening explanations.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Recently, I started writing a Python extension that wraps the procedural
generation library &lt;a href=&#34;http://libnoise.sourceforge.net/&#34;&gt;libnoise&lt;/a&gt; using
&lt;a href=&#34;http://riverbankcomputing.co.uk/software/sip/intro&#34;&gt;SIP&lt;/a&gt;-generated code, and
encountered the inevitable segfaults. It didn&amp;rsquo;t take long to establish that the
error was somewhere in my C++ code, but I couldn&amp;rsquo;t figure out where exactly it
was. A couple of searches online revealed that the way to go about finding these
things was to use a proper debugger, and because the GNU Debugger &amp;ndash; ``gdb` &amp;ndash;
supports Python, that seemed to be the way to go.&lt;/p&gt;
&lt;p&gt;Getting it working was not, however, particularly straightforward. &lt;code&gt;gdb&lt;/code&gt;
supports debugging Python code as of version 7. Unfortunately, Apple&amp;rsquo;s version
of &lt;code&gt;gdb&lt;/code&gt; is currently sitting at 6.3. So all I had to do was get a newer
version, right? Wrong.&lt;/p&gt;
&lt;p&gt;Assuming you have Homebrew &amp;ndash; if you don&amp;rsquo;t, go read about it &amp;ndash; you can get a
newer version of gdb from there. Since gdb is sort of a compiler, it&amp;rsquo;s not
available in the main Homebrew repository (there&amp;rsquo;s a policy you can read
&lt;a href=&#34;https://github.com/mxcl/homebrew/wiki/Custom-GCC-and-cross-compilers%3E&#34;&gt;on the wiki&lt;/a&gt;),
so you&amp;rsquo;ll have to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ brew tap homebrew/dupes
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;first, and then run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ brew install gdb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You&amp;rsquo;ll notice immediately that if you run &lt;code&gt;gdb --version&lt;/code&gt; in a terminal you&amp;rsquo;ll
see:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;GNU gdb 6.3.50-20050815 (Apple version gdb-1822) (Sun Aug  5 03:00:42 UTC 2012)
Copyright 2004 Free Software Foundation, Inc.
...
This GDB was configured as &amp;quot;x86_64-apple-darwin&amp;quot;.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(That&amp;rsquo;s right, the Apple version is circa 2004&amp;hellip;) Since you now have two
versions of &lt;code&gt;gdb&lt;/code&gt; installed, the shell will by default start the one in
&lt;code&gt;/usr/bin&lt;/code&gt;, while your Homebrew&amp;rsquo;d version is located in &lt;code&gt;/usr/local/bin&lt;/code&gt;. There
are a few ways to fix this. One is to edit the order of the paths in
&lt;code&gt;/etc/paths&lt;/code&gt;; you could, if you wanted, copy over the system version of &lt;code&gt;gdb&lt;/code&gt;,
too. However, both of these solutions may run you into other problems,
particularly if you use XCode, which depends on Apple&amp;rsquo;s version of &lt;code&gt;gdb&lt;/code&gt; for
debugging. I haven&amp;rsquo;t actually tried deleting the system &lt;code&gt;gdb&lt;/code&gt;, but I suspect you
could screw some related things up this way. Instead, I prefer the simple
renaming method::&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ mv /usr/local/bin/gdb /usr/local/bin/gdb7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which allows you to run &lt;code&gt;gdb7 --version&lt;/code&gt; and get the expected::&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;GNU gdb (GDB) 7.6.1
Copyright (C) 2013 Free Software Foundation, Inc.
...
This GDB was configured as &amp;quot;x86_64-apple-darwin12.5.0&amp;quot;.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So far, so good. Unfortunately, debuggers need to inspect the internals of other
processes, which programs aren&amp;rsquo;t normally allowed to do. So in order to really
use gdb you need to give it permission to do this. Follow the instructions on
the &lt;code&gt;gdb&lt;/code&gt; website &lt;a href=&#34;https://sourceware.org/gdb/wiki/BuildingOnDarwin&#34;&gt;here&lt;/a&gt; to
create a certificate, and then run::&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ codesign -s gdb-cert gdb7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now it&amp;rsquo;s time to test debugging Python code, which should be as easy as &lt;code&gt;gdb7 python&lt;/code&gt;. However, this gives:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;quot;/usr/bin/python&amp;quot;: not in executable format: File format not recognized
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;on OS X Mountain Lion. The reason? The system python executable is a &amp;lsquo;fat&amp;rsquo;
binary, meaning it can run on multiple system archtectures, i.e.:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ file /usr/bin/python
/usr/bin/python: Mach-O universal binary with &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt; architectures
/usr/bin/python &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; architecture i386&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;:	Mach-O executable i386
/usr/bin/python &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; architecture x86_64&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;:	Mach-O 64-bit executable x86_64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Unfortunately, &lt;code&gt;gdb&lt;/code&gt; does not support debugging fat binaries (at least according
to their mailing list). So you&amp;rsquo;ll have to extract the right system architecture
using the &lt;code&gt;lipo&lt;/code&gt; (hah!) program. If you have an Intel Mac running a 64-bit
operating system (the mostly likely), that means the &amp;ldquo;x86_64&amp;rdquo; one. As a side
note, the &lt;code&gt;python&lt;/code&gt; program will actually call on the specific version of Python
when you launch it, meaning that the executable you&amp;rsquo;re really interested in is
&lt;code&gt;/usr/bin/python2.7&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ file /usr/bin/python2.7
/usr/bin/python2.7: Mach-O universal binary with &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt; architectures
/usr/bin/python2.7 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; architecture i386&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;:	Mach-O executable i386
/usr/bin/python2.7 &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; architecture x86_64&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;:	Mach-O 64-bit executable x86_64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From which we can extract a &amp;ldquo;thin&amp;rdquo;, architecture-specific binary (I&amp;rsquo;ve called
&lt;code&gt;python64&lt;/code&gt;) as follows::&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ lipo /usr/bin/python2.7 -thin x86_64 -output /usr/bin/python64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can now run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ gdb7 python64
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And see that:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Reading symbols from /usr/bin/python64...(no debugging symbols found)...done.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As expected. I&amp;rsquo;m not quite sure what &lt;code&gt;gdb&lt;/code&gt; means when it says that python does
not have debugging symbols &amp;ndash; backtraces seem to work fine anyway. To verify
that it works, try something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;$ gdb7 python64
...
&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;gdb&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; run test.py
Starting program: /usr/bin/python64 test.py

Program received signal SIGTRAP, Trace/breakpoint trap.
0x00007fff5fc01028 in ?? &lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;gdb&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;
Continuing.
Hello, world!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that for some reason, Python &lt;em&gt;always&lt;/em&gt; sends a SIGTRAP before it begins
executing the script. Don&amp;rsquo;t worry, just &lt;code&gt;continue&lt;/code&gt;. If you want to find out why
your program segfaults, you can run &lt;code&gt;bt&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Program received signal SIGSEGV, Segmentation fault.
0x000000010003441a in PyErr_Occurred () from /System/Library/Frameworks/Python.framework/Versions/2.7/Python
(gdb) bt
#0  0x000000010003441a in PyErr_Occurred () from /System/Library/Frameworks/Python.framework/Versions/2.7/Python
#1  0x000000010003a81b in _PyArg_NoKeywords () from /System/Library/Frameworks/Python.framework/Versions/2.7/Python
#2  0x0000000100039c91 in _PyArg_NoKeywords () from /System/Library/Frameworks/Python.framework/Versions/2.7/Python
#3  0x0000000100038c43 in PyArg_Parse () from /System/Library/Frameworks/Python.framework/Versions/2.7/Python
#4  0x0000000100038f0d in PyArg_ParseTuple () from /System/Library/Frameworks/Python.framework/Versions/2.7/Python
#5  0x0000000100493335 in meth_Clamp_SetBounds () from /Users/Aaron/Code/Python/simplex-test/noisypy/noisypy.so
#6  0x00000001000136c6 in PyObject_Call () from /System/Library/Frameworks/Python.framework/Versions/2.7/Python
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Which located the error pretty quickly my wrapper of &lt;code&gt;Clamp.SetBounds()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Happy debugging!&lt;/p&gt;
    </content>
    
    
    <category term="osx"/>
    <category term="python"/>
  </entry>
  <entry>
    <title type="html">Building Libnoise on OS X</title>
    
    <link href="https://unconj.ca/blog/building-libnoise-on-os-x.html" rel="alternate"/>
    <published>2013-09-29T00:00:00Z</published>
    
    
    <updated>2013-09-29T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2013-09-29:blog/building-libnoise-on-os-x.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;Although it is very old (and unmaintained since 2007),
&lt;a href=&#34;http://libnoise.sourceforge.net/&#34;&gt;Libnoise&lt;/a&gt; is a great library for procedural
generation of pseudorandom noise. It provides a wonderfully intuitive way of
chaining together various layers and styles of noise that I&amp;rsquo;ve never seen
matched, even in newer implementations. It also supports seeds (which I
require), and is largely feature-complete. I&amp;rsquo;ve used some of the Java and XNA
ports in the past, but in the last few days started getting interested in using
the original C++ code, partly because I&amp;rsquo;m wondering if it can be converted into
a Python extension.&lt;/p&gt;
&lt;p&gt;Since the original Makefile is problematic, someone has gone to the trouble of
converting it to &lt;code&gt;cmake&lt;/code&gt;, so you can run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;$ git clone git@github.com:eXpl0it3r/libnoise.git
$ &lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; libnoise
$ cmake .
$ make &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; make install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To install the static library on your system. This seems to work on OS X
Mountain Lion. You can compile a few of the examples (in the &lt;code&gt;examples&lt;/code&gt;
directory) to try them out. Everyone&amp;rsquo;s favourite is the &lt;code&gt;worms.cpp&lt;/code&gt; demo, but
since it uses OpenGL, you&amp;rsquo;ll have to change&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;gl/gl.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;glut.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;at the top of the file to&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;OpenGL/gl.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;#include&lt;/span&gt; &lt;span class=&#34;cpf&#34;&gt;&amp;lt;GLUT/glut.h&amp;gt;&lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;due to the locations of those libraries on OS X. You can then compile this
using (yes, I know it&amp;rsquo;s a hell of a command):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;$ g++ /System/Library/Frameworks/GLUT.framework/GLUT /System/Library/Frameworks/OpenGL.framework/OpenGL -o worms.o worms.cpp -llibnoise
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Run it (you may have to &lt;code&gt;chmod +x worms.o&lt;/code&gt; first) with:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;$ ./worms.o
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;which opens up a lovely window with some wriggling worms. It should look
something like this:&lt;/p&gt;
&lt;center&gt;
![The Libnoise Worms]({filename}/images/libnoise-worms.png)
&lt;/center&gt;
&lt;p&gt;Most of the other examples make use of the &lt;code&gt;noiseutils.cpp&lt;/code&gt; file, so they can
be compiled and run with something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;$ g++ -o wood.o texturewood.cpp noiseutils.cpp -llibnoise &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ./wood.o
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The most interesting example is probably to be found in &lt;code&gt;complexplanet.cpp&lt;/code&gt;.
Although it takes about three full minutes to run on my computer (poor
performance has always been the criticism of libnoise), it does produce the
kind of image that got me interested in procedural generation to begin with:&lt;/p&gt;
&lt;center&gt;
![Libnoise Terrain]({filename}/images/libnoise-terrain.png)
&lt;/center&gt;
    </content>
    
    
    <category term="osx"/>
    <category term="pcg"/>
  </entry>
  <entry>
    <title type="html">Logic in Maven Archetypes</title>
    
    <link href="https://unconj.ca/blog/logic-in-maven-archetypes.html" rel="alternate"/>
    <published>2013-04-18T00:00:00Z</published>
    
    
    <updated>2013-04-18T00:00:00Z</updated>
    
    <author>
      <name>Aaron Jacobs</name>
    </author>
    
    
    
    
    
    <id>tag:unconj.ca,2013-04-18:blog/logic-in-maven-archetypes.html</id>
    
    <content type="html" xml:lang="en">
      &lt;p&gt;Time for a &lt;em&gt;real&lt;/em&gt; first post. Recently, I&amp;rsquo;ve been working on creating a Maven
archetype for &lt;a href=&#34;http://www.spout.org%3E&#34;&gt;a certain open-source project&lt;/a&gt;, and
discovered to my delight that archetypes actually support a limited kind of
logic. If it&amp;rsquo;s not immediately obvious why that would be useful, consider that
you can make use of this logic to, for example, optionally add a dependency
based on a custom parameter.&lt;/p&gt;
&lt;p&gt;Making use of the fact that Maven builds its archetypes using Apache&amp;rsquo;s
&lt;a href=&#34;http://velocity.apache.org/&#34;&gt;Velocity template engine&lt;/a&gt;, you can embed
statements reminiscent of C-style preprocessor directives in any file in the
archetype. To add an optional dependency, try embedding the logic below in the
&lt;code&gt;pom.xml&lt;/code&gt; file&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;dependencies&amp;gt;
	...
#if (${includeNetty} == &#39;true&#39; || ${includeNetty} == &#39;yes&#39; || ${includeNetty} == &#39;y&#39;)
	&amp;lt;dependency&amp;gt;
		&amp;lt;groupId&amp;gt;io.netty&amp;lt;/groupId&amp;gt;
		&amp;lt;artifactId&amp;gt;netty&amp;lt;/artifactId&amp;gt;
		&amp;lt;version&amp;gt;3.4.6.Final&amp;lt;/version&amp;gt;
		&amp;lt;scope&amp;gt;compile&amp;lt;/scope&amp;gt;
	&amp;lt;/dependency&amp;gt;
#end
&amp;lt;/dependencies&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This will work provided, of course, that you&amp;rsquo;ve defined &lt;code&gt;includeNetty&lt;/code&gt; like so
in your &lt;code&gt;archetype-metadata.xml&lt;/code&gt; file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;requiredProperties&amp;gt;
    &amp;lt;requiredProperty key=&amp;quot;includeNetty&amp;quot;&amp;gt; 
     	&amp;lt;defaultValue&amp;gt;false&amp;lt;/defaultValue&amp;gt;
    &amp;lt;/requiredProperty&amp;gt; 
&amp;lt;/requiredProperties&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The above snippet becomes&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;dependencies&amp;gt;
	...
	&amp;lt;dependency&amp;gt;
		&amp;lt;groupId&amp;gt;io.netty&amp;lt;/groupId&amp;gt;
		&amp;lt;artifactId&amp;gt;netty&amp;lt;/artifactId&amp;gt;
		&amp;lt;version&amp;gt;3.4.6.Final&amp;lt;/version&amp;gt;
		&amp;lt;scope&amp;gt;compile&amp;lt;/scope&amp;gt;
	&amp;lt;/dependency&amp;gt;
&amp;lt;/dependencies&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;when &lt;code&gt;-DincludeNetty&lt;/code&gt; is set to &lt;code&gt;true&lt;/code&gt; (or &lt;code&gt;yes&lt;/code&gt;, or &lt;code&gt;y&lt;/code&gt;, in keeping with
Maven-style commands), and&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;dependencies&amp;gt;
	...
&amp;lt;/dependencies&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;when it is false (or, really, anything but &lt;code&gt;true&lt;/code&gt;, &lt;code&gt;yes&lt;/code&gt;, or &lt;code&gt;y&lt;/code&gt;).
Unfortunately, this trick doesn&amp;rsquo;t work to optionally include whole files &amp;ndash;
there isn&amp;rsquo;t currently a way to do that at all in Maven,
&lt;a href=&#34;http://jira.codehaus.org/browse/ARCHETYPE-274%3E&#34;&gt;although the feature has been suggested&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;avoid-leading-whitespace&#34;&gt;Avoid leading whitespace&lt;/h2&gt;
&lt;p&gt;Just a tip: when embedding these preprocessing commands, don&amp;rsquo;t put any
whitespace before the &lt;code&gt;#&lt;/code&gt; character, otherwise it will be included in the
output. This snippet&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;properties&amp;gt;
	&amp;lt;project.build.sourceEncoding&amp;gt;UTF-8&amp;lt;/project.build.sourceEncoding&amp;gt;
	&amp;lt;currentYear&amp;gt;2013&amp;lt;/currentYear&amp;gt;
	#if (${includeNetty} == &amp;quot;true&amp;quot;)
	&amp;lt;nettyVersion&amp;gt;3.4.6.Final&amp;lt;/nettyVersion&amp;gt;
	#end	
&amp;lt;properties&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;harmless though it looks, will actually output&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;properties&amp;gt;
	&amp;lt;project.build.sourceEncoding&amp;gt;UTF-8&amp;lt;/project.build.sourceEncoding&amp;gt;
	&amp;lt;currentYear&amp;gt;2013&amp;lt;/currentYear&amp;gt;
		&amp;lt;nettyVersion&amp;gt;3.4.6.Final&amp;lt;/nettyVersion&amp;gt;
	&amp;lt;properties&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;due to the leading whitespace, which can be extremely annoying if you actually
care about nicely formatted &lt;code&gt;pom.xml&lt;/code&gt; files.&lt;/p&gt;
    </content>
    
    
    <category term="java"/>
    <category term="maven"/>
  </entry>
</feed>
