<p><div><div><div><div data-width="100" data-show-faces="false" data-send="true" data-layout="button_count" data-height="21" data-href="https://www.r-bloggers.com/cartograms-of-new-zealand-census-data/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://ellisp.github.io/blog/2017/04/23/cartograms"> Peter's stats stuff - R</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>I’ve been trying to catch up with mapping functionality in R and its extended ecoverse, so might do a few posts on this in the next month or so. First up (more or less by accident) is <a target="_blank" rel="nofollow" href="https://en.wikipedia.org/wiki/Cartogram">cartograms</a> – maps where some other numeric variable is substituted for land area, while still trying to preserve regions’ basic shapes and relative locations.</p>
<p>Cartograms are particularly useful as a variant on choropleth maps (regions’ fill colour specified based on a numeric variable) for socio-economic comparison. Straight choropleth maps can give a misleading comparison between large sparsely populated areas and small densely populated areas (ie cities). This is a problem for statistical maps of New Zealand, for example, with the Auckland City and Regional Council making up a quarter of the country’s population but much less of its area.</p>
<p>In this post, I use illustrative data from the 2013 New Zealand Census by Statistics New Zealand. Last year I took their “meshblock” census data set and re-shaped it into the <a target="_blank" rel="nofollow" href="http://ellisp.github.io/blog/2016/08/04/nzcensus-gam-elastic-lm"><code>nzcensus</code> R package</a>; only available from GitHub (as it’s too large for CRAN). In the process of preparing today’s blog post I made some small additions to the variables in that package – numbers of dwellings, households and individuals, and cartogram outlines of New Zealand regions (and I hope to follow up with other spatial categories.)</p>
<h2>Rectangles</h2>
<p>My first exploration into this was via the <code>recmap</code> R package, which does rectangular cartograms. These are a simplified version that just needs to know the centres of regions, the numeric variable you want their size to be proportionate to, and aspect ratios for rectangles. Here’s the out-of-the box version, showing the proportion of individuals who are receiving unemployment benefits on census night 2013:</p>
<p><img width="100%" src="http://ellisp.github.io/img/0094-rect.svg"></p>
<p>Note that the proportion of all people receiving benefits is <em>lower</em> than the unemployment rate because there is a different denominator.</p>
<p>This is an interesting start, but I don’t find this that satisfactory for New Zealand’s 16 regions; and the result is even less satisfactory for 67 Territorial Authorities. The algorithm is quick, but the rectangles just don’t cut it for today’s high expectations of data visualisation; and the adjacency of various regions has been lost (most significantly, Wellington relegated to the bottom of the map, rather than the middle where it more intuitively belongs). There are ways to over-ride both of these issues, but I’ll put <code>recmap</code> aside for now – potentially but not immediately useful for my purposes.</p>
<p>Here’s the code for those rectangles, plus some helper functions for colour palettes and legends I’ll use throughout the post:</p>
<figure>
<pre><code data-lang="r"><span># Install the latest version of the nzcensus package if not already installed:
</span><span>devtools</span><span>::</span><span>install_github</span><span>(</span><span>&quot;ellisp/nzelect/pkg2&quot;</span><span>)</span><span>
</span><span># Install Ministry of Business, Innovation and Employment's NZ maps package,
# only needed for region_simpl, used to illustrate a &quot;normal&quot; map.
</span><span>devtools</span><span>::</span><span>install_github</span><span>(</span><span>&quot;nz-mbie/mbiemaps-public/pkg&quot;</span><span>)</span><span>
</span><span>library</span><span>(</span><span>recmap</span><span>)</span><span>
</span><span>library</span><span>(</span><span>nzcensus</span><span>)</span><span>
</span><span>library</span><span>(</span><span>tidyverse</span><span>)</span><span>
</span><span>library</span><span>(</span><span>viridis</span><span>)</span><span>
</span><span>library</span><span>(</span><span>mbiemaps</span><span>)</span><span> </span><span># Helper functions:
</span><span>colour_scale</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>x</span><span>,</span><span> </span><span>palette</span><span> </span><span>=</span><span> </span><span>viridis</span><span>(</span><span>100</span><span>)){</span><span>
</span><span>levs</span><span> </span><span>&lt;-</span><span> </span><span>round</span><span>(</span><span>x</span><span> </span><span>/</span><span> </span><span>max</span><span>(</span><span>x</span><span>,</span><span> </span><span>na.rm</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span> </span><span>*</span><span> </span><span>length</span><span>(</span><span>palette</span><span>))</span><span>
</span><span>return</span><span>(</span><span>as.character</span><span>(</span><span>palette</span><span>[</span><span>levs</span><span>]))</span><span>
</span><span>}</span><span>
</span><span>make_legend</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>x</span><span>,</span><span> </span><span>palette</span><span> </span><span>=</span><span> </span><span>viridis</span><span>(</span><span>100</span><span>),</span><span> </span><span>title</span><span> </span><span>=</span><span> </span><span>NULL</span><span>,</span><span> </span><span>location</span><span> </span><span>=</span><span> </span><span>&quot;right&quot;</span><span>,</span><span> </span><span>multiplier</span><span> </span><span>=</span><span> </span><span>100</span><span>,</span><span> </span><span>digits</span><span> </span><span>=</span><span> </span><span>1</span><span>,</span><span> </span><span>...</span><span>){</span><span>
</span><span>y</span><span> </span><span>&lt;-</span><span> </span><span>seq</span><span>(</span><span>from</span><span>=</span><span> </span><span>min</span><span>(</span><span>x</span><span>),</span><span> </span><span>to</span><span> </span><span>=</span><span> </span><span>max</span><span>(</span><span>x</span><span>),</span><span> </span><span>length.out</span><span> </span><span>=</span><span> </span><span>5</span><span>)</span><span>
</span><span>levsy</span><span> </span><span>&lt;-</span><span> </span><span>round</span><span>(</span><span>y</span><span> </span><span>/</span><span> </span><span>max</span><span>(</span><span>x</span><span>,</span><span> </span><span>na.rm</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span> </span><span>*</span><span> </span><span>length</span><span>(</span><span>palette</span><span>))</span><span>
</span><span>legend</span><span>(</span><span>location</span><span>,</span><span> </span><span>legend</span><span> </span><span>=</span><span> </span><span>round</span><span>(</span><span>y</span><span> </span><span>*</span><span> </span><span>multiplier</span><span>,</span><span> </span><span>digits</span><span>),</span><span> </span><span>pch</span><span> </span><span>=</span><span> </span><span>15</span><span>,</span><span> </span><span>col</span><span> </span><span>=</span><span> </span><span>palette</span><span>[</span><span>levsy</span><span>],</span><span> </span><span>text.col</span><span> </span><span>=</span><span> </span><span>palette</span><span>[</span><span>levsy</span><span>],</span><span>
</span><span>bty</span><span> </span><span>=</span><span> </span><span>&quot;n&quot;</span><span>,</span><span> </span><span>title</span><span> </span><span>=</span><span> </span><span>title</span><span>,</span><span> </span><span>...</span><span>)</span><span>
</span><span>title</span><span>(</span><span>xlab</span><span> </span><span>=</span><span> </span><span>&quot;Source: Statistics New Zealand Census 2013, in nzcensus R package&quot;</span><span>,</span><span>
</span><span>adj</span><span> </span><span>=</span><span> </span><span>1</span><span>,</span><span> </span><span>col.lab</span><span> </span><span>=</span><span> </span><span>&quot;grey50&quot;</span><span>,</span><span> </span><span>cex.lab</span><span> </span><span>=</span><span> </span><span>0.8</span><span>)</span><span>
</span><span>}</span><span>
</span><span>#=========rectangle cartogram==========
</span><span>tmp</span><span> </span><span>&lt;-</span><span> </span><span>with</span><span>(</span><span>filter</span><span>(</span><span>REGC2013</span><span>,</span><span> </span><span>!</span><span>grepl</span><span>(</span><span>&quot;Area Outside&quot;</span><span>,</span><span> </span><span>REGC2013_N</span><span>)),</span><span> </span><span>data.frame</span><span>(</span><span>x</span><span> </span><span>=</span><span> </span><span>WGS84Longitude</span><span>,</span><span>
</span><span>y</span><span> </span><span>=</span><span> </span><span>WGS84Latitude</span><span>,</span><span>
</span><span>dx</span><span> </span><span>=</span><span> </span><span>12</span><span>,</span><span>
</span><span>dy</span><span> </span><span>=</span><span> </span><span>8</span><span>,</span><span>
</span><span>z</span><span> </span><span>=</span><span> </span><span>ResidentPop2013</span><span>,</span><span>
</span><span>name</span><span> </span><span>=</span><span> </span><span>gsub</span><span>(</span><span>&quot; Region&quot;</span><span>,</span><span> </span><span>&quot;&quot;</span><span>,</span><span> </span><span>as.character</span><span>(</span><span>REGC2013_N</span><span>)),</span><span>
</span><span>value</span><span> </span><span>=</span><span> </span><span>PropUnemploymentBenefit2013</span><span>,</span><span>
</span><span>stringsAsFactors</span><span> </span><span>=</span><span> </span><span>FALSE</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>colour</span><span> </span><span>=</span><span> </span><span>colour_scale</span><span>(</span><span>value</span><span>))</span><span>
</span><span>tmp</span><span> </span><span>%>%</span><span>
</span><span>recmap</span><span>()</span><span> </span><span>%>%</span><span>
</span><span>plot</span><span>(</span><span>col.text</span><span> </span><span>=</span><span> </span><span>&quot;grey10&quot;</span><span>,</span><span> </span><span>col</span><span> </span><span>=</span><span> </span><span>tmp</span><span>[,</span><span> </span><span>&quot;colour&quot;</span><span>],</span><span> </span><span>border</span><span> </span><span>=</span><span> </span><span>&quot;white&quot;</span><span>)</span><span>
</span><span>title</span><span>(</span><span>main</span><span> </span><span>=</span><span> </span><span>&quot;Unemployment by region; regions sized by usual resident population&quot;</span><span>)</span><span>
</span><span>make_legend</span><span>(</span><span>tmp</span><span>$</span><span>value</span><span>,</span><span> </span><span>title</span><span> </span><span>=</span><span> </span><span>&quot;Proportion of all individuals\non unemployment benefit&quot;</span><span>,</span><span>
</span><span>location</span><span> </span><span>=</span><span> </span><span>&quot;left&quot;</span><span>,</span><span> </span><span>cex</span><span> </span><span>=</span><span> </span><span>0.8</span><span>)</span></code></pre>
</figure>
<h2>ScapeToad and cartograms</h2>
<p>Turning a shapefile into a cartogram is a serious job for serious GIS software, and there’s no obvious way to do it from R. However, the <a target="_blank" rel="nofollow" href="http://scapetoad.choros.ch/">ScapeToad</a> software (written in Java) is freely available under a GPL license and is simple to operate. I’ve half started a project for R and ScapeToad to interact but I doubt it will get far or be worthwhile.</p>
<p>ScapeToad imports layers from an ESRI format shapefile, and then reshapes the borders for you based on a numeric variable that is included as part of the polygon-level data in that shapefile. R works adequately for reading and writing shapefiles, and of course is unparalleled for managing numeric data in general. The cartogram calculation is easy to specify in ScapeToad but is computationally intensive (at the time of writing, my laptop has been whirring away at the Territorial Authority level for four hours…). I’ve added <a target="_blank" rel="nofollow" href="https://github.com/ellisp/nzelect/blob/master/prep/create-cartograms.R">a step to the build for the <code>nzcensus</code> R package</a> that saves a cartogram version of New Zealand’s regional council boundaries, with size proportional to “usual resident population”. I hope to do the same for Territorial Authority, Area Unit and Mesh Block down the track, but for now only the regional council level is complete. Because I’ve done the work in advance, there’s no need to install ScapeToad to use the map in <code>nzcensus</code>.</p>
<p>Here’s an example end result:</p>
<p><img width="100%" src="http://ellisp.github.io/img/0094-reg-cart.svg"></p>
<p>Auckland, and the north island in general, are distorted to appear much larger than their geographic region, whereas other regions (particularly the West Coast of the south island) are shrunk; yet the map remains recognisably New Zealand. In contrast, in the traditional choropleth map on the right, the colour of Auckland is simply not prominent enough given its importance in socio-economic terms.</p>
<p>The R code to produce this from an existing cartogram set of boundaries (<code>reg_cart_simpl</code>, which now ships with <code>nzcensus</code>) is probably even easier than the rectangle version:</p>
<figure>
<pre><code data-lang="r"><span>#===============shape-preserving cartogram=============
</span><span>comb_data</span><span> </span><span>&lt;-</span><span> </span><span>reg_cart_simpl</span><span>@</span><span>data</span><span> </span><span>%>%</span><span>
</span><span>left_join</span><span>(</span><span>REGC2013</span><span>,</span><span> </span><span>by</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>&quot;Name&quot;</span><span> </span><span>=</span><span> </span><span>&quot;REGC2013_N&quot;</span><span>))</span><span> </span><span>par</span><span>(</span><span>font.main</span><span>=</span><span> </span><span>1</span><span>,</span><span> </span><span>fg</span><span> </span><span>=</span><span> </span><span>&quot;grey75&quot;</span><span>,</span><span> </span><span>mfrow</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>1</span><span>,</span><span> </span><span>2</span><span>))</span><span>
</span><span>plot</span><span>(</span><span>reg_cart_simpl</span><span>,</span><span>
</span><span>col</span><span> </span><span>=</span><span> </span><span>colour_scale</span><span>(</span><span>comb_data</span><span>$</span><span>PropUnemploymentBenefit2013</span><span>))</span><span>
</span><span>title</span><span>(</span><span>main</span><span> </span><span>=</span><span> </span><span>&quot;Unemployment by region; regions sized by usual resident population&quot;</span><span>)</span><span>
</span><span>make_legend</span><span>(</span><span>comb_data</span><span>$</span><span>PropUnemploymentBenefit2013</span><span>,</span><span> </span><span>title</span><span> </span><span>=</span><span> </span><span>&quot;Proportion of all individuals\non unemployment benefit&quot;</span><span>,</span><span>
</span><span>location</span><span> </span><span>=</span><span> </span><span>&quot;left&quot;</span><span>,</span><span> </span><span>cex</span><span> </span><span>=</span><span> </span><span>0.8</span><span>)</span><span>
</span><span># compare with the standard regions map, from the mbiemaps package
</span><span>data</span><span>(</span><span>region_simpl</span><span>)</span><span>
</span><span>plot</span><span>(</span><span>region_simpl</span><span>,</span><span> </span><span>col</span><span> </span><span>=</span><span> </span><span>colour_scale</span><span>(</span><span>comb_data</span><span>$</span><span>PropUnemploymentBenefit2013</span><span>))</span><span>
</span><span>title</span><span>(</span><span>main</span><span> </span><span>=</span><span> </span><span>&quot;Regions as they are shaped and sized geographically&quot;</span><span>)</span></code></pre>
</figure>
<p>I was so pleased with how this looks a did a few variants:</p>
<p><img width="100%" src="http://ellisp.github.io/img/0094-reg-cart-2.svg"></p>
<p><img width="100%" src="http://ellisp.github.io/img/0094-reg-cart-3.svg"></p>
<p>Then I realised that better would be to let people choose a variable for colouring in the map themselves so I made this Shiny app:</p>
<p><iframe width="450" src="https://ellisp.shinyapps.io/nzcensus-cartograms/"></iframe></p>
<p>This also makes it easier to select a colour scheme (and its direction), and gives micro-interactivity like informative tooltips. And thanks to the work of the Shiny and Leaflet developers isn’t much harder than the first static graphics.</p>
<p>The web app makes sense because most of the data in the <code>nzcensus</code> package has been transformed into percentages (of dwellings, of households, or of individuals), which minimises the effort needed in choice of scales and the like. More polish (eg clearer what the denominator is for each variable) would be needed to turn this into something of professional standard, but what we’ve got here is ok for a Sunday afternoon project.</p>
<p>Also available:</p>
<ul>
<li><a target="_blank" rel="nofollow" href="https://ellisp.shinyapps.io/nzcensus-cartograms/">Full screen version</a></li>
<li><a target="_blank" rel="nofollow" href="https://github.com/ellisp/ellisp.github.io/tree/source/_working/0094-cartograms">Source code</a></li>
</ul>
<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://ellisp.github.io/blog/2017/04/23/cartograms"> Peter's stats stuff - R</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a title="The R Project for Statistical Computing" rel="nofollow" href="https://www.r-project.org/">R</a> news and <a title="R tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/tutorial">tutorials</a> on topics such as: <a title="Data science" rel="nofollow" href="https://www.r-bloggers.com/search/data%20science">Data science</a>, <a title="Big Data" rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data">Big Data, <a title="R jobs" rel="nofollow" href="https://www.r-users.com/">R jobs</a>, visualization (<a title="ggplot and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/boxplot">Boxplots</a>, <a title="Maps and gis" rel="nofollow" href="https://www.r-bloggers.com/search/map">maps</a>, <a title="Animation in R" rel="nofollow" href="https://www.r-bloggers.com/search/animation">animation</a>), programming (<a title="RStudio IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/RStudio">RStudio</a>, <a title="Sweave and literate programming" rel="nofollow" href="https://www.r-bloggers.com/search/sweave">Sweave</a>, <a title="LaTeX in R" rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX">LaTeX</a>, <a title="SQL and databases" rel="nofollow" href="https://www.r-bloggers.com/search/SQL">SQL</a>, <a title="Eclipse IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/eclipse">Eclipse</a>, <a title="git and github, Version Control System" rel="nofollow" href="https://www.r-bloggers.com/search/git">git</a>, <a title="Large data in R using Hadoop" rel="nofollow" href="https://www.r-bloggers.com/search/hadoop">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/regression">regression</a>, <a title="principal component analysis tutorial" rel="nofollow" href="https://www.r-bloggers.com/search/PCA">PCA</a>, <a title="Time series" rel="nofollow" href="https://www.r-bloggers.com/search/time+series">time series</a>, <a title="finance trading" rel="nofollow" href="https://www.r-bloggers.com/search/trading">trading</a>) and more...
<img height="1" alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/e3jq_X3HBo8"></a></div>