

{"id":3054,"date":"2014-09-26T00:49:32","date_gmt":"2014-09-26T05:49:32","guid":{"rendered":"http:\/\/rud.is\/b\/?p=3054"},"modified":"2022-10-11T15:29:54","modified_gmt":"2022-10-11T20:29:54","slug":"overcoming-d3-cartographic-envy-with-r-ggplot","status":"publish","type":"post","link":"https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/","title":{"rendered":"Overcoming D3 Cartographic Envy With R + ggplot"},"content":{"rendered":"<p>When I used one of the Scotland TopoJSON files for a <a href=\"https:\/\/rud.is\/b\/2014\/09\/20\/chartingmapping-the-scottish-vote-with-r-rvestdplyrtidyrtopojsonggplot\/\">recent post<\/a>, it really hit me just how much D3 cartography envy I had\/have as an R user. Don&#8217;t get me wrong, I can conjure up D3 maps pretty well [<a href=\"http:\/\/vcdb.org\/explore.html\">1<\/a>] [<a href=\"http:\/\/datadrivensecurity.info\/blog\/posts\/2014\/Jan\/malicious-cartography-part-1\/\">2<\/a>] and the utility of an interactive map visualization goes without saying, but we can make great static maps in R without a great deal of effort, so I decided to replicate a few core examples from the <a href=\"https:\/\/github.com\/mbostock\/topojson\/wiki\/Gallery\">D3 topojson gallery<\/a> in R.<\/p>\n<p>I chose five somewhat different examples, each focusing on various aspects of creating map layers and trying to not be too U.S. focused. Here they are (hit the main link to go to the gist for the example and the <code>bl.ocks<\/code> URL to see it&#8217;s D3 counterpart):<\/p>\n<ul>\n<li><a href=\"https:\/\/gist.github.com\/hrbrmstr\/e3d0dc87eaacf7bbece7\">Swiss Cantons<\/a> &#8211; R version of <a href=\"http:\/\/bl.ocks.org\/mbostock\/4207744\">http:\/\/bl.ocks.org\/mbostock\/4207744<\/a><\/li>\n<li><a href=\"https:\/\/gist.github.com\/hrbrmstr\/08eab5535619daaa281e\">Costa Rica<\/a> &#8211; R version of <a href=\"http:\/\/bl.ocks.org\/arce\/9357998\">http:\/\/bl.ocks.org\/arce\/9357998<\/a><\/li>\n<li><a href=\"https:\/\/gist.github.com\/hrbrmstr\/9bda23f79ce2a5776733\">Area Choropleth<\/a> &#8211; R version of <a href=\"http:\/\/bl.ocks.org\/mbostock\/4206573\">http:\/\/bl.ocks.org\/mbostock\/4206573<\/a><\/li>\n<li><a href=\"https:\/\/gist.github.com\/hrbrmstr\/b7ffe6137c4ff6acd009\">Block Counties<\/a> &#8211; R version of <a href=\"http:\/\/bl.ocks.org\/mbostock\/4206857\">http:\/\/bl.ocks.org\/mbostock\/4206857<\/a><\/li>\n<li><a href=\"https:\/\/gist.github.com\/hrbrmstr\/6c6ffda42a93e2f8b380\">County Circles<\/a> (OK, Ovals) &#8211; R version of <a href=\"http:\/\/bl.ocks.org\/mbostock\/4206975\">http:\/\/bl.ocks.org\/mbostock\/4206975<\/a><\/li>\n<\/ul>\n<p>I used the TopoJSON\/GeoJSON files provided with each example, so you&#8217;ll need a recent <a href=\"http:\/\/www.gdal.org\/\">gdal<\/a> (>= 1.11), and&mdash;consequently&mdash;a suitable build of <code>rgdal<\/code>) to work through the examples.<\/p>\n<h3>The Core Mapping Idiom<\/h3>\n<p>While the details may vary with each project you work on, the basic flow to present a map in R with <code>ggplot<\/code> are:<\/p>\n<ul>\n<li>read in a map features (I use <code>readOGR<\/code> in these examples)<\/li>\n<li>convert that into something <code>ggplot<\/code> can handle<\/li>\n<li>identify values you wish to pair with those features (optional if we&#8217;re just plotting a plain map)<\/li>\n<li>determine which portion of the map is to be displayed<\/li>\n<li>plot the map features<\/li>\n<\/ul>\n<p>Words &amp; abbreviations mean things, just like map symbols mean things, and if you&#8217;re wondering what this &#8220;OGR&#8221; is, here&#8217;s the answer from the <a href=\"https:\/\/trac.osgeo.org\/gdal\/wiki\/FAQGeneral#WhatdoesOGRstandfor\">official FAQ<\/a>:<\/p>\n<blockquote><p>\n  <em>OGR used to stand for OpenGIS Simple Features Reference Implementation. However, since OGR is not fully compliant with the OpenGIS Simple Feature specification and is not approved as a reference implementation of the spec the name was changed to OGR Simple Features Library. The only meaning of OGR in this name is historical. OGR is also the prefix used everywhere in the source of the library for class names, filenames, etc.<\/em>\n<\/p><\/blockquote>\n<p>The <code>readOGR<\/code> function can work with a wide variety of file formats and OGR files can hold a wide variety of data. The most basic use for our mapping is to read in these TopoJSON\/GeoJSON files and use the right features from them to make our maps. Features\/layers can be almost anything (counties, states, countries, rivers, lakes, etc) and we can see what features we want to work with by using the <code>ogrListLayers<\/code> function (you can do this from an operating system command line as well, but we&#8217;ll stay in R for now). Let&#8217;s take a look at the layers available in the map from the Costa Rica example:<\/p>\n<pre lang=\"rsplus\">ogrListLayers(\"division.json\")\n\n## [1] \"limites\"    \"provincias\" \"cantones\"   \"distritos\" \nattr(,\"driver\")\n## [1] \"GeoJSON\"\nattr(,\"nlayers\")\n## [1] 4<\/pre>\n<p>Those translate to &#8220;country&#8221;, &#8220;provinces&#8221;, &#8220;cantons&#8221;, &amp; &#8220;districts&#8221;. Each layer has polygons and associated data for the polygons (and overall layer), including information about the type of projection. If you&#8217;re sensing a &#8220;math trigger warning&#8221;, fear not; I won&#8217;t be delving into to much more cartographic detail as you probably just want to see the maps &amp; code.<\/p>\n<h3>Swiss Cantons<\/h3>\n<p>If you&#8217;re from the U.S. you (most likely) have no idea what a canton is. The quickest explanation is that it is an administrative division within a country and, in this specific example, the 26 cantons of Switzerland are the member states of the federal state of Switzerland.<\/p>\n<p>The <a href=\"http:\/\/bl.ocks.org\/mbostock\/4207744\">D3 Swiss Cantons<\/a> uses a TopoJSON\/GeoJSON file that has only one layer (i.e. the cantons) along with metadata about the canton <code>id<\/code> and <code>name<\/code>:<\/p>\n<pre lang=\"rsplus\">ogrInfo(\"readme-swiss.json\", \"cantons\")\n\n## Source: \"readme-swiss.json\", layer: \"cantons\"\n## Driver: GeoJSON number of rows 26 \n## Feature type: wkbPolygon with 2 dimensions\n## Extent: (5.956 45.818) - (10.492 47.808)\n## Number of fields: 2 \n##   name type length typeName\n## 1   id    4      0   String\n## 2 name    4      0   String<\/pre>\n<blockquote><p>\n  NOTE: you should learn to get pretty adept with the OGR functions or command-line tools as you can do some really amazing things with them, including extracting only certain features, simplifying the polygons or fixing issues. Some of the TopoJSON\/GeoJSON files you&#8217;ll find with D3 examples may have missing or invalid components and you can fix some of them with these tools. We&#8217;ll be working around errors and missing values in these examples.\n<\/p><\/blockquote>\n<p>The D3 example displays the canton <code>name<\/code> at the <a href=\"http:\/\/en.wikipedia.org\/wiki\/Centroid\">centroid<\/a> of the polygon, so that&#8217;s what we&#8217;ll do in R:<\/p>\n<pre lang=\"rsplus\">library(rgeos)\nlibrary(rgdal) # needs gdal > 1.11.0\nlibrary(ggplot2)\n \n# ggplot map theme\ndevtools::source_gist(\"https:\/\/gist.github.com\/hrbrmstr\/33baa3a79c5cfef0f6df\")\n \nmap = readOGR(\"readme-swiss.json\", \"cantons\")\n\nmap_df <- fortify(map)<\/pre>\n<p>The <code>map<\/code> object is a <code>SpatialPolygonsDataFrame<\/code> and has a fairly complex structure:<\/p>\n<pre lang=\"rsplus\">slotNames(map)\n## [1] \"data\"        \"polygons\"    \"plotOrder\"   \"bbox\"       \n## [5] \"proj4string\"\n\nnames(map)\n## [1] \"id\"   \"name\"\n\n# execute these on your own and poke around the data structures after determining the class\nclass(map@data)\nclass(map@polygons)\nclass(map@plotOrder)\nclass(map@bbox)\nclass(map@proj4string)\n<\/pre>\n<p>The <code>fortify<\/code> function turns all that into something we can use with <code>ggplot<\/code>. Normally, we'd be able to get <code>fortify<\/code> to associate the canton <code>name<\/code> to the polygon points it encodes via the <code>region<\/code> parameter. That did not work with these TopoJSON\/GeoJSON files and I didn't really poke around much to determine why since it's easy enough to work around. In this case, I manually merged the names with the fortified map data frame.<\/p>\n<pre lang=\"rsplus\">#  create mapping for id # to name since \"region=\" won't work\ndat <- data.frame(id=0:(length(map@data$name)-1), canton=map@data$name)\nmap_df <- merge(map_df, dat, by=\"id\")<\/pre>\n<p>We can get the centroid via the <code>gCentroid<\/code> function, and we'll make a data frame of those center points and the name of the canton for use with a <code>geom_text<\/code> layer after plotting the base outlines of the cantons (with a rather bland fill, but I didn't pick the color):<\/p>\n<pre lang=\"rsplus\"># find canton centers\ncenters <- data.frame(gCentroid(map, byid=TRUE))\ncenters$canton <- dat$canton\n \n# make a map!\ngg <- ggplot()\ngg <- gg + geom_map(data=map_df, map=map_df,\n                    aes(map_id=id, x=long, y=lat, group=group),\n                    color=\"#ffffff\", fill=\"#bbbbbb\", size=0.25)\n# gg <- gg + geom_point(data=centers, aes(x=x, y=y))\ngg <- gg + geom_text(data=centers, aes(label=canton, x=x, y=y), size=3)\ngg <- gg + coord_map()\ngg <- gg + labs(x=\"\", y=\"\", title=\"Swiss Cantons\")\ngg <- gg + theme_map()<\/pre>\n<p>The <code>coord_map()<\/code> works with the <code>mapproj<\/code> package to help us display maps in reasonable projections (or really dumb ones). The default is <code>\"mercator\"<\/code> and we'll stick with that since the D3 examples use it (but, <a href=\"http:\/\/www.winkel.org\/other\/Winkel%20Tripel%20Projections.htm\">winkel-tripel<\/a> FTW!).<\/p>\n<p>Here's the result of our hard work (select map for larger version):<\/p>\n<p><a target=\"_blank\" href=\"https:\/\/rud.is\/dl\/cantons.svg\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/rud.is\/dl\/cantons.svg\"\/><\/a><\/p>\n<p>If you ignore the exposition above and just take into account non-blank source code lines, we did all that in ~16LOC and have a scaleable SVG file as a result. You can have some fun with the above code and remove the static <code>fill=\"#bbbbbb\"<\/code> and move it to the <code>mapping<\/code> aesthetic parameter and tie it's value to the canton name.<\/p>\n<h3>Costa Rica<\/h3>\n<p>The TopoJSON\/GeoJSON file provided with the <a href=\"http:\/\/bl.ocks.org\/arce\/9357998\">D3 example<\/a> is a good example of encoding multiple layers into a single file (see the first <code>ogrListLayers<\/code> above). We'll create a fortified version of each layer and then plot each with a <code>geom_map<\/code> layer using different line colors, sizes and fills:<\/p>\n<pre lang=\"rsplus\">limites = readOGR(\"division.json\", \"limites\")\nprovincias = readOGR(\"division.json\", \"provincias\")\ncantones = readOGR(\"division.json\", \"cantones\")\ndistritos = readOGR(\"division.json\", \"distritos\")\n \nlimites_df <- fortify(limites)\ncantones_df <- fortify(cantones)\ndistritos_df <- fortify(distritos)\nprovincias_df <- fortify(provincias)\n  \ngg <- ggplot()\ngg <- gg + geom_map(data=limites_df, map=limites_df,\n                    aes(map_id=id, x=long, y=lat, group=group),\n                    color=\"white\", fill=\"#dddddd\", size=0.25)\ngg <- gg + geom_map(data=cantones_df, map=cantones_df,\n                    aes(map_id=id, x=long, y=lat, group=group),\n                    color=\"red\", fill=\"#ffffff00\", size=0.2)\ngg <- gg + geom_map(data=distritos_df, map=distritos_df,\n                    aes(map_id=id, x=long, y=lat, group=group),\n                    color=\"#999999\", fill=\"#ffffff00\", size=0.1)\ngg <- gg + geom_map(data=provincias_df, map=provincias_df,\n                    aes(map_id=id, x=long, y=lat, group=group),\n                    color=\"black\", fill=\"#ffffff00\", size=0.33)\ngg <- gg + coord_map()\ngg <- gg + labs(x=\"\", y=\"\", title=\"Costa Rica TopoJSON\")\ngg <- gg + theme_map()<\/pre>\n<p>The result is pretty neat and virtually identical to the D3 version:<\/p>\n<p><a target=\"_blank\" href=\"https:\/\/rud.is\/dl\/costarica.svg\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/rud.is\/dl\/costarica.svg\"\/><\/a><\/p>\n<p>Try playing around with the order of the <code>geom_map<\/code> layers (or remove some) and also the line color\/size\/fill &amp; alpha values to see how it changes the map.<\/p>\n<h3>Area Choropleth<\/h3>\n<p>I'm not a huge fan of the colors used in the <a href=\"http:\/\/bl.ocks.org\/mbostock\/4206573\">D3 version<\/a> and I'm not going to spend any time moving Hawaii &amp; Alaska around (that's a whole different post). <strong>But<\/strong>, I <em>will<\/em> show how to make a similar area choropleth:<\/p>\n<pre lang=\"rsplus\"># read in the county borders\nmap = readOGR(\"us.json\", \"counties\")\n\n# calculate (well retrieve) the area since it's part of the polygon structure\n# and associate it with the polygon id so we can use it later. We need to do\n# the merge manually again since the \"us.json\" file threw errors again when\n# trying to use the fortify \"region\" parameter.\n\nmap_area <- data.frame(id=0:(length(map@data$id)-1),\n                       area=sapply(slot(map, \"polygons\"), slot, \"area\") )\n\n# read in the state borders\nstates = readOGR(\"us.json\", \"states\")\nstates_df <- fortify(states)\n\n# create map data frame and merge area info\nmap_df <- fortify(map)\nmap_df <- merge(map_df, map_area, by=\"id\")\n\ngg <- ggplot()\n\n# thin white border around counties and shades of yellow-green for area (log scale)\ngg <- gg + geom_map(data=map_df, map=map_df,\n                    aes(map_id=id, x=long, y=lat, group=group, fill=log1p(area)),\n                    color=\"white\", size=0.05)\n\n# thick white border for states\ngg <- gg + geom_map(data=states_df, map=states_df,\n                    aes(map_id=id, x=long, y=lat, group=group),\n                    color=\"white\", size=0.5, alpha=0)\ngg <- gg + scale_fill_continuous(low=\"#ccebc5\", high=\"#084081\")\n\n# US continental extents - not showing alaska &#038; hawaii\ngg <- gg + xlim(-124.848974, -66.885444)\ngg <- gg + ylim(24.396308, 49.384358)\n\ngg <- gg + coord_map()\ngg <- gg + labs(x=\"\", y=\"\", title=\"Area Choropleth\")\ngg <- gg + theme_map()\ngg <- gg + theme(legend.position=\"none\")<\/pre>\n<p><a target=\"_blank\" href=\"https:\/\/rud.is\/dl\/areachoropleth.svg\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/rud.is\/dl\/areachoropleth.svg\"\/><\/a><\/p>\n<p>Play with the colors and use different values instead of the polygon area (perhaps use <code>sample<\/code> or <code>runif<\/code> to generate some data) to see how it changes the choropleth outcome.<\/p>\n<h3>Blocky Counties<\/h3>\n<p>The example from the <a href=\"http:\/\/bl.ocks.org\/mbostock\/4206857\">D3 wiki<\/a> is more \"how to work with shapefiles and map coordinates\" than it is useful, but we have the same flexibility in R, so we'll make the same plot by using the <code>bbox<\/code> function to make a data frame of bounding boxes we can use with <code>geom_rect<\/code> (there's <em>no<\/em> <code>geom_map<\/code> in this example, just using the coordinate system to plot boxes):<\/p>\n<pre lang=\"rsplus\"># use the topojson from the bl.ocks example\nmap = readOGR(\"us.json\", \"counties\")\n\n# build our map data frame of rects\n\nmap_df <- do.call(\"rbind\", lapply(map@polygons, function(p) {\n\n  b <- bbox(p) # get bounding box of polygon and put it into a form we can use later\n\n  data.frame(xmin=b[\"x\", \"min\"],\n             xmax=b[\"x\", \"max\"],\n             ymin=b[\"y\", \"min\"],\n             ymax=b[\"y\", \"max\"])\n\n}))\nmap_df$id <- map$id # add the id even though we aren't using it now\n\ngg <- ggplot(data=map_df)\ngg <- gg + geom_rect(aes(xmin=xmin, xmax=xmax,\n                         ymin=ymin, ymax=ymax),\n                     color=\"steelblue\", alpha=0, size=0.25)\n\n# continental us only\ngg <- gg + xlim(-124.848974, -66.885444)\ngg <- gg + ylim(24.396308, 49.384358)\ngg <- gg + coord_map()\ngg <- gg + labs(x=\"\", y=\"\", title=\"Blocky Counties\")\ngg <- gg + theme_map()\ngg <- gg + theme(legend.position=\"none\")<\/pre>\n<p><a target=\"_blank\" href=\"https:\/\/rud.is\/dl\/blockycounties.svg\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/rud.is\/dl\/blockycounties.svg\"\/><\/a><\/p>\n<p>To re-emphasize we're just working with <code>ggplot<\/code> layers, so play around and, perhaps color in only the odd numbered counties.<\/p>\n<h3>County Circles (OK, Ovals)<\/h3>\n<p>The last <a href=\"http:\/\/bl.ocks.org\/mbostock\/4206975\">D3 example<\/a> I'm copying swaps squares for circles, which makes this more of a challenge to do in R+ggplot since <code>ggplot<\/code> has no \"circle\" geom (and holey <code>geom_point<\/code>s <em>do not count<\/em>). So, we'll borrow and slightly adapt a <a href=\"http:\/\/stackoverflow.com\/a\/6863490\/1457051\">function from StackOverflow<\/a> by <a href=\"http:\/\/stackoverflow.com\/users\/324364\/joran\">joran<\/a> that builds a data frame of polygon points derived by a center &amp; diameter. We'll add an <code>id<\/code> value (for each of the counties) and make one <em>really<\/em> big data frame (well, big for use in <code>ggplot<\/code>) that we can then plot as grouped <code>geom_path<\/code>s. Unlike our cantons example, the <code>gCentroid<\/code> function coughed up errors on this TopoJSON\/GeoJSON file, so I resorted to approximating the center from the rectangular bounding box. Also, I don't project the circle coordinates before plotting, so they're ovals. While it doesn't mirror the D3 example perfectly, it should help reinforce how to work with the map's metadata and draw arbitrary components on a map:<\/p>\n<pre lang=\"rsplus\"># adapted from http:\/\/stackoverflow.com\/questions\/6862742\/draw-a-circle-with-ggplot2\n# computes a circle from a given diameter. we add \"id\" so we can have one big\n# data frame and group them for plotting\n\ncircleFun <- function(id, center = c(0,0),diameter = 1, npoints = 100){\n    r = diameter \/ 2\n    tt <- seq(0,2*pi,length.out = npoints)\n    xx <- center[1] + r * cos(tt)\n    yy <- center[2] + r * sin(tt)\n    return(data.frame(id=id, x = xx, y = yy))\n}\n\n# us topojson from the bl.ocks example\nmap = readOGR(\"us.json\", \"counties\")\n\n# this topojson file gives rgeos_getcentroid errors here\n# so we approximate the centroid\n\nmap_df <- do.call(\"rbind\", lapply(map@polygons, function(p) {\n\n  b <- bbox(p)\n  \n  data.frame(x=b[\"x\", \"min\"] + ((b[\"x\", \"max\"] - b[\"x\", \"min\"]) \/ 2),\n             y=b[\"y\", \"min\"] + ((b[\"y\", \"max\"] - b[\"y\", \"min\"]) \/ 2))\n\n}))\n\n# get area &#038; diameter\nmap_df$area <- sapply(slot(map, \"polygons\"), slot, \"area\")\nmap_df$diameter <- sqrt(map_df$area \/ pi) * 2\n\n# make our big data frame of circles\ncircles <- do.call(\"rbind\", lapply(1:nrow(map_df), function(i) {\n  circleFun(i, c(map_df[i,]$x, map_df[i,]$y), map_df[i,]$diameter)\n}))\n\ngg <- ggplot(data=circles, aes(x=x, y=y, group=id))\ngg <- gg + geom_path(color=\"steelblue\", size=0.25)\n\n# continental us\ngg <- gg + xlim(-124.848974, -66.885444)\ngg <- gg + ylim(24.396308, 49.384358)\ngg <- gg + coord_map()\ngg <- gg + labs(x=\"\", y=\"\", title=\"County Circles (OK, Ovals)\")\ngg <- gg + theme_map()\ngg <- gg + theme(legend.position=\"none\")<\/pre>\n<p><a target=\"_blank\" href=\"https:\/\/rud.is\/dl\/countycircles.svg\" rel=\"noopener\"><img decoding=\"async\" src=\"https:\/\/rud.is\/dl\/countycircles.svg\"\/><\/a><\/p>\n<p>If you poke around a bit at the various map libraries in R, you should be able to figure out how to get those plotted as circles (and learn alot in the process).<\/p>\n<h3>Wrapping Up<\/h3>\n<p>R <code>ggplot<\/code> maps won't and shouldn't replace D3 maps for many reasons, paramount of which is interactivity. The generated SVG files are also fairly large and the non-SVG versions don't look nearly as crisp (and aren't as flexible). However, this should be a decent introductory primer on mapping and shapefiles and might come in handy when you want to use R to enhance maps with other data and write out (yep, R can read <em>and<\/em> write OGR) your own shapefiles for use in D3 (or other tools\/languages).<\/p>\n<p>Don't forget that all source code (including TopoJSON\/GeoJSON files and sample SVGs) are in their own gists:<\/p>\n<ul>\n<li><a href=\"https:\/\/gist.github.com\/hrbrmstr\/e3d0dc87eaacf7bbece7\">Swiss Cantons<\/a><\/li>\n<li><a href=\"https:\/\/gist.github.com\/hrbrmstr\/08eab5535619daaa281e\">Costa Rica<\/a><\/li>\n<li><a href=\"https:\/\/gist.github.com\/hrbrmstr\/9bda23f79ce2a5776733\">Area Choropleth<\/a><\/li>\n<li><a href=\"https:\/\/gist.github.com\/hrbrmstr\/b7ffe6137c4ff6acd009\">Block Counties<\/a><\/li>\n<li><a href=\"https:\/\/gist.github.com\/hrbrmstr\/6c6ffda42a93e2f8b380\">County Circles<\/a> (OK, Ovals)<\/li>\n<\/ul>\n<p>If you figure out what is causing some of the errors I mentioned or make some epic maps of your own, don't hesitate to drop a note in the comments.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When I used one of the Scotland TopoJSON files for a recent post, it really hit me just how much D3 cartography envy I had\/have as an R user. Don&#8217;t get me wrong, I can conjure up D3 maps pretty well [1] [2] and the utility of an interactive map visualization goes without saying, but [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":true,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":3,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"","footnotes":""},"categories":[24,666,673,674,15,706,91],"tags":[810],"class_list":["post-3054","post","type-post","status-publish","format-standard","hentry","category-charts-graphs","category-d3","category-datavis-2","category-dataviz","category-javascript","category-maps","category-r","tag-post"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Overcoming D3 Cartographic Envy With R + ggplot - rud.is<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Overcoming D3 Cartographic Envy With R + ggplot - rud.is\" \/>\n<meta property=\"og:description\" content=\"When I used one of the Scotland TopoJSON files for a recent post, it really hit me just how much D3 cartography envy I had\/have as an R user. Don&#8217;t get me wrong, I can conjure up D3 maps pretty well [1] [2] and the utility of an interactive map visualization goes without saying, but [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/\" \/>\n<meta property=\"og:site_name\" content=\"rud.is\" \/>\n<meta property=\"article:published_time\" content=\"2014-09-26T05:49:32+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-10-11T20:29:54+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/rud.is\/dl\/cantons.svg\" \/>\n<meta name=\"author\" content=\"hrbrmstr\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"hrbrmstr\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2014\\\/09\\\/26\\\/overcoming-d3-cartographic-envy-with-r-ggplot\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2014\\\/09\\\/26\\\/overcoming-d3-cartographic-envy-with-r-ggplot\\\/\"},\"author\":{\"name\":\"hrbrmstr\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"headline\":\"Overcoming D3 Cartographic Envy With R + ggplot\",\"datePublished\":\"2014-09-26T05:49:32+00:00\",\"dateModified\":\"2022-10-11T20:29:54+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2014\\\/09\\\/26\\\/overcoming-d3-cartographic-envy-with-r-ggplot\\\/\"},\"wordCount\":1588,\"commentCount\":8,\"publisher\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"image\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2014\\\/09\\\/26\\\/overcoming-d3-cartographic-envy-with-r-ggplot\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/rud.is\\\/dl\\\/cantons.svg\",\"keywords\":[\"post\"],\"articleSection\":[\"Charts &amp; Graphs\",\"d3\",\"DataVis\",\"DataViz\",\"Javascript\",\"maps\",\"R\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/rud.is\\\/b\\\/2014\\\/09\\\/26\\\/overcoming-d3-cartographic-envy-with-r-ggplot\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2014\\\/09\\\/26\\\/overcoming-d3-cartographic-envy-with-r-ggplot\\\/\",\"url\":\"https:\\\/\\\/rud.is\\\/b\\\/2014\\\/09\\\/26\\\/overcoming-d3-cartographic-envy-with-r-ggplot\\\/\",\"name\":\"Overcoming D3 Cartographic Envy With R + ggplot - rud.is\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2014\\\/09\\\/26\\\/overcoming-d3-cartographic-envy-with-r-ggplot\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2014\\\/09\\\/26\\\/overcoming-d3-cartographic-envy-with-r-ggplot\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/rud.is\\\/dl\\\/cantons.svg\",\"datePublished\":\"2014-09-26T05:49:32+00:00\",\"dateModified\":\"2022-10-11T20:29:54+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2014\\\/09\\\/26\\\/overcoming-d3-cartographic-envy-with-r-ggplot\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/rud.is\\\/b\\\/2014\\\/09\\\/26\\\/overcoming-d3-cartographic-envy-with-r-ggplot\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2014\\\/09\\\/26\\\/overcoming-d3-cartographic-envy-with-r-ggplot\\\/#primaryimage\",\"url\":\"https:\\\/\\\/rud.is\\\/dl\\\/cantons.svg\",\"contentUrl\":\"https:\\\/\\\/rud.is\\\/dl\\\/cantons.svg\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2014\\\/09\\\/26\\\/overcoming-d3-cartographic-envy-with-r-ggplot\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/rud.is\\\/b\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Overcoming D3 Cartographic Envy With R + ggplot\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#website\",\"url\":\"https:\\\/\\\/rud.is\\\/b\\\/\",\"name\":\"rud.is\",\"description\":\"&quot;In God we trust. All others must bring data&quot;\",\"publisher\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/rud.is\\\/b\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\",\"name\":\"hrbrmstr\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2023\\\/10\\\/ukr-shield.png?fit=460%2C460&ssl=1\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2023\\\/10\\\/ukr-shield.png?fit=460%2C460&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2023\\\/10\\\/ukr-shield.png?fit=460%2C460&ssl=1\",\"width\":460,\"height\":460,\"caption\":\"hrbrmstr\"},\"logo\":{\"@id\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2023\\\/10\\\/ukr-shield.png?fit=460%2C460&ssl=1\"},\"description\":\"Don't look at me\u2026I do what he does \u2014 just slower. #rstats avuncular \u2022 ?Resistance Fighter \u2022 Cook \u2022 Christian \u2022 [Master] Chef des Donn\u00e9es de S\u00e9curit\u00e9 @ @rapid7\",\"sameAs\":[\"http:\\\/\\\/rud.is\"],\"url\":\"https:\\\/\\\/rud.is\\\/b\\\/author\\\/hrbrmstr\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Overcoming D3 Cartographic Envy With R + ggplot - rud.is","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/","og_locale":"en_US","og_type":"article","og_title":"Overcoming D3 Cartographic Envy With R + ggplot - rud.is","og_description":"When I used one of the Scotland TopoJSON files for a recent post, it really hit me just how much D3 cartography envy I had\/have as an R user. Don&#8217;t get me wrong, I can conjure up D3 maps pretty well [1] [2] and the utility of an interactive map visualization goes without saying, but [&hellip;]","og_url":"https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/","og_site_name":"rud.is","article_published_time":"2014-09-26T05:49:32+00:00","article_modified_time":"2022-10-11T20:29:54+00:00","og_image":[{"url":"https:\/\/rud.is\/dl\/cantons.svg","type":"","width":"","height":""}],"author":"hrbrmstr","twitter_card":"summary_large_image","twitter_misc":{"Written by":"hrbrmstr","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/#article","isPartOf":{"@id":"https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/"},"author":{"name":"hrbrmstr","@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"headline":"Overcoming D3 Cartographic Envy With R + ggplot","datePublished":"2014-09-26T05:49:32+00:00","dateModified":"2022-10-11T20:29:54+00:00","mainEntityOfPage":{"@id":"https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/"},"wordCount":1588,"commentCount":8,"publisher":{"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"image":{"@id":"https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/#primaryimage"},"thumbnailUrl":"https:\/\/rud.is\/dl\/cantons.svg","keywords":["post"],"articleSection":["Charts &amp; Graphs","d3","DataVis","DataViz","Javascript","maps","R"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/","url":"https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/","name":"Overcoming D3 Cartographic Envy With R + ggplot - rud.is","isPartOf":{"@id":"https:\/\/rud.is\/b\/#website"},"primaryImageOfPage":{"@id":"https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/#primaryimage"},"image":{"@id":"https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/#primaryimage"},"thumbnailUrl":"https:\/\/rud.is\/dl\/cantons.svg","datePublished":"2014-09-26T05:49:32+00:00","dateModified":"2022-10-11T20:29:54+00:00","breadcrumb":{"@id":"https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/#primaryimage","url":"https:\/\/rud.is\/dl\/cantons.svg","contentUrl":"https:\/\/rud.is\/dl\/cantons.svg"},{"@type":"BreadcrumbList","@id":"https:\/\/rud.is\/b\/2014\/09\/26\/overcoming-d3-cartographic-envy-with-r-ggplot\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/rud.is\/b\/"},{"@type":"ListItem","position":2,"name":"Overcoming D3 Cartographic Envy With R + ggplot"}]},{"@type":"WebSite","@id":"https:\/\/rud.is\/b\/#website","url":"https:\/\/rud.is\/b\/","name":"rud.is","description":"&quot;In God we trust. All others must bring data&quot;","publisher":{"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/rud.is\/b\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886","name":"hrbrmstr","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","contentUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1","width":460,"height":460,"caption":"hrbrmstr"},"logo":{"@id":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2023\/10\/ukr-shield.png?fit=460%2C460&ssl=1"},"description":"Don't look at me\u2026I do what he does \u2014 just slower. #rstats avuncular \u2022 ?Resistance Fighter \u2022 Cook \u2022 Christian \u2022 [Master] Chef des Donn\u00e9es de S\u00e9curit\u00e9 @ @rapid7","sameAs":["http:\/\/rud.is"],"url":"https:\/\/rud.is\/b\/author\/hrbrmstr\/"}]}},"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p23idr-Ng","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":3563,"url":"https:\/\/rud.is\/b\/2015\/07\/26\/making-staticinteractive-voronoi-map-layers-in-ggplotleaflet\/","url_meta":{"origin":3054,"position":0},"title":"Making Static\/Interactive Voronoi Map Layers In ggplot\/leaflet","author":"hrbrmstr","date":"2015-07-26","format":false,"excerpt":"Despite having shown various ways to overcome D3 cartographic envy, there are always more examples that can cause the green monster to rear it's ugly head. Take the Voronoi Arc Map example. For those in need of a primer, a Voronoi tesslation\/diagram is: \u2026a partitioning of a plane into regions\u2026","rel":"","context":"In &quot;cartography&quot;","block_context":{"text":"cartography","link":"https:\/\/rud.is\/b\/category\/cartography\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2816,"url":"https:\/\/rud.is\/b\/2013\/11\/28\/one-more-timemapping-maine-power-outages-with-d3\/","url_meta":{"origin":3054,"position":1},"title":"One More Time\u2026Mapping Maine Power Outages with D3","author":"hrbrmstr","date":"2013-11-28","format":false,"excerpt":"It started with a local R version and migrated to a Shiny version and is now in full D3 glory. Some down time gave me the opportunity to start a basic D3 version of the outage map, but it needs a bit of work as it relies on a page\u2026","rel":"","context":"In &quot;d3&quot;","block_context":{"text":"d3","link":"https:\/\/rud.is\/b\/category\/d3\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/11\/Central_Maine_Power_Live_Outage_Map-2.png?fit=757%2C649&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/11\/Central_Maine_Power_Live_Outage_Map-2.png?fit=757%2C649&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/11\/Central_Maine_Power_Live_Outage_Map-2.png?fit=757%2C649&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2013\/11\/Central_Maine_Power_Live_Outage_Map-2.png?fit=757%2C649&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":3117,"url":"https:\/\/rud.is\/b\/2014\/11\/16\/moving-the-earth-well-alaska-hawaii-with-r\/","url_meta":{"origin":3054,"position":2},"title":"Moving The Earth (well, Alaska &#038; Hawaii) With R","author":"hrbrmstr","date":"2014-11-16","format":false,"excerpt":"In a previous post we looked at how to use D3 TopoJSON files with R and make some very D3-esque maps. I mentioned that one thing missing was moving Alaska & Hawaii a bit closer to the continental United States and this post shows you how to do that. The\u2026","rel":"","context":"In &quot;d3&quot;","block_context":{"text":"d3","link":"https:\/\/rud.is\/b\/category\/d3\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":4209,"url":"https:\/\/rud.is\/b\/2016\/03\/27\/nuclear-animations-in-d3\/","url_meta":{"origin":3054,"position":3},"title":"Nuclear Animations in D3","author":"hrbrmstr","date":"2016-03-27","format":false,"excerpt":"As I said, I'm kinda obsessed with the \"nuclear\" data set. So much so that I made a D3 version that's similar to the R version I made the other day. I tried not to code much today (too much Easter fun going on), so I left off the size\u2026","rel":"","context":"In &quot;cartography&quot;","block_context":{"text":"cartography","link":"https:\/\/rud.is\/b\/category\/cartography\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2016\/03\/ogimg.png?fit=1200%2C946&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2016\/03\/ogimg.png?fit=1200%2C946&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2016\/03\/ogimg.png?fit=1200%2C946&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2016\/03\/ogimg.png?fit=1200%2C946&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2016\/03\/ogimg.png?fit=1200%2C946&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":2846,"url":"https:\/\/rud.is\/b\/2013\/12\/27\/points-polygons-and-power-outages\/","url_meta":{"origin":3054,"position":4},"title":"Points, Polygons and Power Outages","author":"hrbrmstr","date":"2013-12-27","format":false,"excerpt":"Most of my free coding time has been spent tweaking a D3-based live power outage tracker for Central Maine Power customers (there's also a woefully less-featured Shiny app for it, too). There is some R associated with the D3 vis, but it's limited to a cron job that's makes the\u2026","rel":"","context":"In &quot;Data Visualization&quot;","block_context":{"text":"Data Visualization","link":"https:\/\/rud.is\/b\/category\/data-visualization\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":3028,"url":"https:\/\/rud.is\/b\/2014\/09\/20\/chartingmapping-the-scottish-vote-with-r-rvestdplyrtidyrtopojsonggplot\/","url_meta":{"origin":3054,"position":5},"title":"Charting\/Mapping the Scottish Vote with R (an rvest\/dplyr\/tidyr\/TopoJSON\/ggplot tutorial)","author":"hrbrmstr","date":"2014-09-20","format":false,"excerpt":"The BBC did a pretty good job [live tracking the Scotland secession vote](http:\/\/www.bbc.com\/news\/events\/scotland-decides\/results), but I really didn't like the color scheme they chose and decided to use the final tally site as the basis for another tutorial using the tools from the Hadleyverse and taking advantage of the fact that\u2026","rel":"","context":"In &quot;Charts &amp; Graphs&quot;","block_context":{"text":"Charts &amp; Graphs","link":"https:\/\/rud.is\/b\/category\/charts-graphs\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/3054","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/comments?post=3054"}],"version-history":[{"count":0,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/3054\/revisions"}],"wp:attachment":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/media?parent=3054"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/categories?post=3054"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/tags?post=3054"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}