

{"id":10886,"date":"2018-06-07T17:01:52","date_gmt":"2018-06-07T22:01:52","guid":{"rendered":"https:\/\/rud.is\/b\/?p=10886"},"modified":"2018-06-08T05:25:28","modified_gmt":"2018-06-08T10:25:28","slug":"making-world-tile-grid-grids","status":"publish","type":"post","link":"https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/","title":{"rendered":"Making World Tile Grid-Grids"},"content":{"rendered":"<p>A colleague asked if I would blog about how I crafted the <a href=\"https:\/\/blog.rapid7.com\/2018\/06\/07\/vpnfilter-potential-reach\/\">grid of world tile grids in this post<\/a> and I accepted the challenge. The technique isn&#8217;t too hard as it just builds on the <a href=\"https:\/\/policyviz.com\/2017\/10\/12\/the-world-tile-grid-map\/\">initial work<\/a> by <a href=\"https:\/\/twitter.com\/jschwabish\">Jon Schwabish<\/a> and a <a href=\"http:\/\/www.maartenlambrechts.com\/2017\/10\/22\/tutorial-a-worldtilegrid-with-ggplot2.html\">handy file<\/a> made by <a href=\"https:\/\/twitter.com\/maartenzam\">Maarten Lambrechts<\/a>.<\/p>\n<h3>The Premise<\/h3>\n<p>For this particular use-case, I sifted through our internet scan data and classified a series of device families from their telnet banners then paired that with our country-level attribution data for each IPv4 address. I&#8217;m not generally &#8220;a fan&#8221; of rolling things up at a country level, but since many (most) of these devices are residential or small\/medium-business routers, country-level attribution has some merit.<\/p>\n<p>But, I&#8217;m also not a fan of country-level choropleths when it comes to &#8220;cyber&#8221; nor am I wont to area-skewed cartograms since most folks still cannot interpret them. Both of those take up a ton of screen real estate, too, espeically if you have more than one of them. Yet, I wanted to show a map-like structure without resorting to Hilbert IPv4 heatmaps since they are neither very readable by a general audience and become skewed when you have to move up from a 1 pixel == 1 Class C network block.<\/p>\n<p>I think the tile grid is a great compromise since it avoids the &#8220;area&#8221;and projection skewness confusion that regular global choropleths cause while still preserving geographic &amp; positional proximity. Sure, they&#8217;ll take some getting used to by casual readers, but I felt it was the best of all the tradeoffs.<\/p>\n<h3>The Setup<\/h3>\n<p>Here&#8217;s the data:<\/p>\n<pre><code class=\"language-r\">\nlibrary(here)\nlibrary(hrbrthemes)\nlibrary(tidyverse)\n\nwtg <- read_csv(\"https:\/\/gist.githubusercontent.com\/maartenzam\/787498bbc07ae06b637447dbd430ea0a\/raw\/9a9dafafb44d8990f85243a9c7ca349acd3a0d07\/worldtilegrid.csv\")\n\nglimpse(wtg)\n\u00a0\n## Observations: 192\n## Variables: 11\n## $ name            <chr> \"Afghanistan\", \"Albania\", \"Algeria\", \"Angola\",...\n## $ alpha.2         <chr> \"AF\", \"AL\", \"DZ\", \"AO\", \"AQ\", \"AG\", \"AR\", \"AM\"...\n## $ alpha.3         <chr> \"AFG\", \"ALB\", \"DZA\", \"AGO\", \"ATA\", \"ATG\", \"ARG...\n## $ country.code    <chr> \"004\", \"008\", \"012\", \"024\", \"010\", \"028\", \"032...\n## $ iso_3166.2      <chr> \"ISO 3166-2:AF\", \"ISO 3166-2:AL\", \"ISO 3166-2:...\n## $ region          <chr> \"Asia\", \"Europe\", \"Africa\", \"Africa\", \"Antarct...\n## $ sub.region      <chr> \"Southern Asia\", \"Southern Europe\", \"Northern ...\n## $ region.code     <chr> \"142\", \"150\", \"002\", \"002\", NA, \"019\", \"019\", ...\n## $ sub.region.code <chr> \"034\", \"039\", \"015\", \"017\", NA, \"029\", \"005\", ...\n## $ x               <int> 22, 15, 13, 13, 15, 7, 6, 20, 24, 15, 21, 4, 2...\n## $ y               <int> 8, 9, 11, 17, 23, 4, 14, 6, 19, 6, 7, 2, 9, 8,...\n\nrouters <- read_csv(here::here(\"data\", \"routers.csv\"))\n\nrouters\n\u00a0\n## # A tibble: 453,027 x 3\n##    type     country_name           country_code\n##    <chr>    <chr>                  <chr>       \n##  1 mikrotik Slovak Republic        SK          \n##  2 mikrotik Czechia                CZ          \n##  3 mikrotik Colombia               CO          \n##  4 mikrotik Bosnia and Herzegovina BA          \n##  5 mikrotik Czechia                CZ          \n##  6 mikrotik Brazil                 BR          \n##  7 mikrotik Vietnam                VN          \n##  8 mikrotik Brazil                 BR          \n##  9 mikrotik India                  IN          \n## 10 mikrotik Brazil                 BR          \n## # ... with 453,017 more rows\n\ndistinct(routers, type) %>% \n  arrange(type) %>% \n  print(n=11)\n\u00a0\n## # A tibble: 11 x 1\n##    type    \n##    <chr>   \n##  1 asus    \n##  2 dlink   \n##  3 huawei  \n##  4 linksys \n##  5 mikrotik\n##  6 netgear \n##  7 qnap    \n##  8 tplink  \n##  9 ubiquiti\n## 10 upvel   \n## 11 zte\n<\/code><\/pre>\n<p>So, we have 11 different device families under assault by &#8220;VPNFilter&#8221; and I wanted to show the global distribution of them. Knowing the compact world tile grid would facet well, I set off to make it happen.<\/p>\n<p>Let&#8217;s get some decent names for facet labels:<\/p>\n<pre><code class=\"language-r\">\nreal_names <- read_csv(here::here(\"data\", \"real_names.csv\"))\n\nreal_names\n\u00a0\n## # A tibble: 11 x 2\n##    type     lab             \n##    <chr>    <chr>           \n##  1 asus     Asus Device     \n##  2 dlink    D-Link Devices  \n##  3 huawei   Huawei Devices  \n##  4 linksys  Linksys Devices \n##  5 mikrotik Mikrotik Devices\n##  6 netgear  Netgear Devices \n##  7 qnap     QNAP Devices    \n##  8 tplink   TP-Link Devices \n##  9 ubiquiti Ubiquiti Devices\n## 10 upvel    Upvel Devices   \n## 11 zte      ZTE Devices\n<\/code><\/pre>\n<p>Next, we need to summarise our scan results and pair it up the world tile grid data and our real names:<\/p>\n<pre><code class=\"language-r\">\ncount(routers, country_code, type) %>%  # summarise the data into # of device familes per country\n  left_join(wtg, by = c(\"country_code\" = \"alpha.2\")) %>% # join them up on the common field\n  filter(!is.na(alpha.3)) %>% # we only want countries on the grid and maxmind attributes some things to meta-regions and anonymous proxies\n  left_join(real_names) -> wtg_routers\n\nglimpse(wtg_routers)\n\n## Observations: 629\n## Variables: 14\n## $ country_code    <chr> \"AE\", \"AE\", \"AE\", \"AF\", \"AF\", \"AF\", \"AG\", \"AL\"...\n## $ type            <chr> \"asus\", \"huawei\", \"mikrotik\", \"huawei\", \"mikro...\n## $ n               <int> 1, 12, 70, 12, 264, 27, 1, 941, 2081, 7, 2, 1,...\n## $ name            <chr> \"United Arab Emirates\", \"United Arab Emirates\"...\n## $ alpha.3         <chr> \"ARE\", \"ARE\", \"ARE\", \"AFG\", \"AFG\", \"AFG\", \"ATG...\n## $ country.code    <chr> \"784\", \"784\", \"784\", \"004\", \"004\", \"004\", \"028...\n## $ iso_3166.2      <chr> \"ISO 3166-2:AE\", \"ISO 3166-2:AE\", \"ISO 3166-2:...\n## $ region          <chr> \"Asia\", \"Asia\", \"Asia\", \"Asia\", \"Asia\", \"Asia\"...\n## $ sub.region      <chr> \"Western Asia\", \"Western Asia\", \"Western Asia\"...\n## $ region.code     <chr> \"142\", \"142\", \"142\", \"142\", \"142\", \"142\", \"019...\n## $ sub.region.code <chr> \"145\", \"145\", \"145\", \"034\", \"034\", \"034\", \"029...\n## $ x               <int> 20, 20, 20, 22, 22, 22, 7, 15, 15, 15, 20, 20,...\n## $ y               <int> 10, 10, 10, 8, 8, 8, 4, 9, 9, 9, 6, 6, 6, 6, 1...\n## $ lab             <chr> \"Asus Device\", \"Huawei Devices\", \"Mikrotik Dev...\n<\/code><\/pre>\n<p>Then, plot it:<\/p>\n<pre><code class=\"language-r\">\nggplot(wtg_routers, aes(x, y, fill=n, group=lab)) +\n  geom_tile(color=\"#b2b2b2\", size=0.125) +\n  scale_y_reverse() +\n  viridis::scale_fill_viridis(name=\"# Devices\", trans=\"log10\", na.value=\"white\", label=scales::comma) +\n  facet_wrap(~lab, ncol=3) +\n  coord_equal() +\n  labs(\n    x=NULL, y=NULL,\n    title = \"World Tile Grid Per-country Concentration of\\nSeriously Poorly Configured Network Devices\",\n    subtitle = \"Device discovery based on in-scope 'VPNFilter' vendor device banner strings\",\n    caption = \"Source: Rapid7 Project Sonar & Censys\"\n  ) +\n  theme_ipsum_rc(grid=\"\") +\n  theme(panel.background = element_rect(fill=\"#969696\", color=\"#969696\")) +\n  theme(axis.text=element_blank()) +\n  theme(legend.direction=\"horizontal\") +\n  theme(legend.key.width = unit(2, \"lines\")) +\n  theme(legend.position=c(0.85, 0.1))\n<\/code><\/pre>\n<p>\u00a0<br \/>\n<img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"10887\" data-permalink=\"https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/chart-1\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/06\/chart-1.png?fit=2304%2C2160&amp;ssl=1\" data-orig-size=\"2304,2160\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"chart-1\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/06\/chart-1.png?fit=510%2C478&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/06\/chart-1.png?resize=510%2C478&#038;ssl=1\" alt=\"\" width=\"510\" height=\"478\" class=\"aligncenter size-full wp-image-10887\" \/><\/p>\n<p>Doh! We forgot to ensure we had data for every country. Let&#8217;s try that again:<\/p>\n<pre><code class=\"language-r\">\ncount(routers, country_code, type) %>%\n  complete(country_code, type) %>%\n  filter(!is.na(country_code)) %>%\n  left_join(wtg, c(\"country_code\" = \"alpha.2\")) %>%\n  filter(!is.na(alpha.3)) %>%\n  left_join(real_names) %>%\n  complete(country_code, type, x=unique(wtg$x), y=unique(wtg$y)) %>%\n  filter(!is.na(lab)) %>%\n  ggplot(aes(x, y, fill=n, group=lab)) +\n  geom_tile(color=\"#b2b2b2\", size=0.125) +\n  scale_y_reverse() +\n  viridis::scale_fill_viridis(name=\"# Devices\", trans=\"log10\", na.value=\"white\", label=scales::comma) +\n  facet_wrap(~lab, ncol=3) +\n  coord_equal() +\n  labs(\n    x=NULL, y=NULL,\n    title = \"World Tile Grid Per-country Concentration of\\nSeriously Poorly Configured Network Devices\",\n    subtitle = \"Device discovery based on in-scope 'VPNFilter' vendor device banner strings\",\n    caption = \"Source: Rapid7 Project Sonar & Censys\"\n  ) +\n  theme_ipsum_rc(grid=\"\") +\n  theme(panel.background = element_rect(fill=\"#969696\", color=\"#969696\")) +\n  theme(axis.text=element_blank()) +\n  theme(legend.direction=\"horizontal\") +\n  theme(legend.key.width = unit(2, \"lines\")) +\n  theme(legend.position=c(0.85, 0.1))\n<\/code><\/pre>\n<p>\u00a0<br \/>\n<img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"10888\" data-permalink=\"https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/chart2-1\/\" data-orig-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/06\/chart2-1.png?fit=2304%2C2160&amp;ssl=1\" data-orig-size=\"2304,2160\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"chart2-1\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/06\/chart2-1.png?fit=510%2C478&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/06\/chart2-1.png?resize=510%2C478&#038;ssl=1\" alt=\"\" width=\"510\" height=\"478\" class=\"aligncenter size-full wp-image-10888\" \/><\/p>\n<p>That&#8217;s better.<\/p>\n<p>We take advantage of ggplot2&#8217;s ability to facet and just ensure we have complete (even if <code>NA<\/code>) tiles for each panel.<\/p>\n<p>Once consumers start seeing these used more they&#8217;ll be able to pick up key markers (or one of us will come up with a notation that makes key markers more visible) and be able to get specific information from the chart. I just wanted to show regional and global differences between vendors (and really give MikroTik users a swift kick in the patootie for being so bad with their kit).<\/p>\n<h3>FIN<\/h3>\n<p>You can find the RStudio project (code + data) here: (<a href=\"http:\/\/rud.is\/dl\/tile-grid-grid.zip\">http:\/\/rud.is\/dl\/tile-grid-grid.zip<\/a>)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A colleague asked if I would blog about how I crafted the grid of world tile grids in this post and I accepted the challenge. The technique isn&#8217;t too hard as it just builds on the initial work by Jon Schwabish and a handy file made by Maarten Lambrechts. The Premise For this particular use-case, [&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":false,"_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":[91],"tags":[],"class_list":["post-10886","post","type-post","status-publish","format-standard","hentry","category-r"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Making World Tile Grid-Grids - 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\/2018\/06\/07\/making-world-tile-grid-grids\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Making World Tile Grid-Grids - rud.is\" \/>\n<meta property=\"og:description\" content=\"A colleague asked if I would blog about how I crafted the grid of world tile grids in this post and I accepted the challenge. The technique isn&#8217;t too hard as it just builds on the initial work by Jon Schwabish and a handy file made by Maarten Lambrechts. The Premise For this particular use-case, [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/\" \/>\n<meta property=\"og:site_name\" content=\"rud.is\" \/>\n<meta property=\"article:published_time\" content=\"2018-06-07T22:01:52+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2018-06-08T10:25:28+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/rud.is\/b\/wp-content\/uploads\/2018\/06\/chart-1.png\" \/>\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=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/06\\\/07\\\/making-world-tile-grid-grids\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/06\\\/07\\\/making-world-tile-grid-grids\\\/\"},\"author\":{\"name\":\"hrbrmstr\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"headline\":\"Making World Tile Grid-Grids\",\"datePublished\":\"2018-06-07T22:01:52+00:00\",\"dateModified\":\"2018-06-08T10:25:28+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/06\\\/07\\\/making-world-tile-grid-grids\\\/\"},\"wordCount\":466,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#\\\/schema\\\/person\\\/d7cb7487ab0527447f7fda5c423ff886\"},\"image\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/06\\\/07\\\/making-world-tile-grid-grids\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2018\\\/06\\\/chart-1.png\",\"articleSection\":[\"R\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/06\\\/07\\\/making-world-tile-grid-grids\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/06\\\/07\\\/making-world-tile-grid-grids\\\/\",\"url\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/06\\\/07\\\/making-world-tile-grid-grids\\\/\",\"name\":\"Making World Tile Grid-Grids - rud.is\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/06\\\/07\\\/making-world-tile-grid-grids\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/06\\\/07\\\/making-world-tile-grid-grids\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2018\\\/06\\\/chart-1.png\",\"datePublished\":\"2018-06-07T22:01:52+00:00\",\"dateModified\":\"2018-06-08T10:25:28+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/06\\\/07\\\/making-world-tile-grid-grids\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/06\\\/07\\\/making-world-tile-grid-grids\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/06\\\/07\\\/making-world-tile-grid-grids\\\/#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2018\\\/06\\\/chart-1.png?fit=2304%2C2160&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/rud.is\\\/b\\\/wp-content\\\/uploads\\\/2018\\\/06\\\/chart-1.png?fit=2304%2C2160&ssl=1\",\"width\":\"2304\",\"height\":\"2160\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/rud.is\\\/b\\\/2018\\\/06\\\/07\\\/making-world-tile-grid-grids\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/rud.is\\\/b\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Making World Tile Grid-Grids\"}]},{\"@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":"Making World Tile Grid-Grids - 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\/2018\/06\/07\/making-world-tile-grid-grids\/","og_locale":"en_US","og_type":"article","og_title":"Making World Tile Grid-Grids - rud.is","og_description":"A colleague asked if I would blog about how I crafted the grid of world tile grids in this post and I accepted the challenge. The technique isn&#8217;t too hard as it just builds on the initial work by Jon Schwabish and a handy file made by Maarten Lambrechts. The Premise For this particular use-case, [&hellip;]","og_url":"https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/","og_site_name":"rud.is","article_published_time":"2018-06-07T22:01:52+00:00","article_modified_time":"2018-06-08T10:25:28+00:00","og_image":[{"url":"https:\/\/rud.is\/b\/wp-content\/uploads\/2018\/06\/chart-1.png","type":"","width":"","height":""}],"author":"hrbrmstr","twitter_card":"summary_large_image","twitter_misc":{"Written by":"hrbrmstr","Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/#article","isPartOf":{"@id":"https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/"},"author":{"name":"hrbrmstr","@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"headline":"Making World Tile Grid-Grids","datePublished":"2018-06-07T22:01:52+00:00","dateModified":"2018-06-08T10:25:28+00:00","mainEntityOfPage":{"@id":"https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/"},"wordCount":466,"commentCount":1,"publisher":{"@id":"https:\/\/rud.is\/b\/#\/schema\/person\/d7cb7487ab0527447f7fda5c423ff886"},"image":{"@id":"https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/#primaryimage"},"thumbnailUrl":"https:\/\/rud.is\/b\/wp-content\/uploads\/2018\/06\/chart-1.png","articleSection":["R"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/","url":"https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/","name":"Making World Tile Grid-Grids - rud.is","isPartOf":{"@id":"https:\/\/rud.is\/b\/#website"},"primaryImageOfPage":{"@id":"https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/#primaryimage"},"image":{"@id":"https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/#primaryimage"},"thumbnailUrl":"https:\/\/rud.is\/b\/wp-content\/uploads\/2018\/06\/chart-1.png","datePublished":"2018-06-07T22:01:52+00:00","dateModified":"2018-06-08T10:25:28+00:00","breadcrumb":{"@id":"https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/#primaryimage","url":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/06\/chart-1.png?fit=2304%2C2160&ssl=1","contentUrl":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/06\/chart-1.png?fit=2304%2C2160&ssl=1","width":"2304","height":"2160"},{"@type":"BreadcrumbList","@id":"https:\/\/rud.is\/b\/2018\/06\/07\/making-world-tile-grid-grids\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/rud.is\/b\/"},{"@type":"ListItem","position":2,"name":"Making World Tile Grid-Grids"}]},{"@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-2PA","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":11445,"url":"https:\/\/rud.is\/b\/2018\/08\/27\/simplifying-world-tile-grid-creation-with-geom_wtg\/","url_meta":{"origin":10886,"position":0},"title":"Simplifying World Tile Grid Creation with geom_wtg()","author":"hrbrmstr","date":"2018-08-27","format":false,"excerpt":"Nowadays (I've seen that word used so much in journal articles lately that I could not resist using it) I'm using world tile grids more frequently as the need arises to convey the state of exposure of various services at a global (country) scale. Given that necessity fosters invention it\u2026","rel":"","context":"In &quot;ggplot&quot;","block_context":{"text":"ggplot","link":"https:\/\/rud.is\/b\/category\/ggplot\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/08\/le-wtg-02.png?fit=958%2C1200&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/08\/le-wtg-02.png?fit=958%2C1200&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/08\/le-wtg-02.png?fit=958%2C1200&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2018\/08\/le-wtg-02.png?fit=958%2C1200&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":3243,"url":"https:\/\/rud.is\/b\/2015\/02\/01\/new-release-0-7-of-metricsgraphics-htmlwidget-grids-rollovers\/","url_meta":{"origin":10886,"position":1},"title":"New release (0.7) of metricsgraphics htmlwidget \u2014 grids &#038; rollovers","author":"hrbrmstr","date":"2015-02-01","format":false,"excerpt":"I've updated my [metricsgraphics](https:\/\/github.com\/hrbrmstr\/metricsgraphics) package to version [0.7](https:\/\/github.com\/hrbrmstr\/metricsgraphics\/releases\/tag\/v0.7). The core [MetricsGraphics](http:\/\/metricsgraphicsjs.org) JavaScript library has been updated to version 2.1.0 (from 1.1.0). Two blog-worthy features since releasing version 0.5 are `mjs_grid` (which is a `grid.arrange`-like equivalent for `metricsgraphics` plots and `mjs_add_rollover` which lets you add your own custom rollover text to\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":[]},{"id":12195,"url":"https:\/\/rud.is\/b\/2019\/05\/18\/mapping-tornado-alley-with-r\/","url_meta":{"origin":10886,"position":2},"title":"Mapping Tornado Alley with R","author":"hrbrmstr","date":"2019-05-18","format":false,"excerpt":"I caught a re-tweet of this tweet by @harry_stevens: THREAD: I wrote a post on @observablehq about a map I made today. It shows a typical day in the life of a graphics journalist: You never know what problems you'll have to solve on deadline! https:\/\/t.co\/yRhW1wbLxN #d3js #dataviz 1\/7 pic.twitter.com\/7N6mmK0nz3\u2014\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\/2019\/05\/map-final-header.png?fit=1001%2C970&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/05\/map-final-header.png?fit=1001%2C970&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/05\/map-final-header.png?fit=1001%2C970&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/rud.is\/b\/wp-content\/uploads\/2019\/05\/map-final-header.png?fit=1001%2C970&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":1334,"url":"https:\/\/rud.is\/b\/2012\/06\/20\/slopegraphs-in-python-failed-states-index-part-1\/","url_meta":{"origin":10886,"position":3},"title":"Slopegraphs in Python \u2013\u00a0Failed States Index (Part 1)","author":"hrbrmstr","date":"2012-06-20","format":false,"excerpt":"The Fund For Peace (FFP) and Foreign Policy jointly released the 2012 version of the \"failed states index\" (FSI). From the FFP site, the FSI: \u2026focuses on the indicators of risk and is based on thousands of articles and reports that are processed by our CAST Software from electronically available\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":[]},{"id":3413,"url":"https:\/\/rud.is\/b\/2015\/05\/15\/u-s-drought-monitoring-with-hexbin-state-maps-in-r\/","url_meta":{"origin":10886,"position":4},"title":"U.S. Drought Monitoring With Hexbin State Maps in R","author":"hrbrmstr","date":"2015-05-15","format":false,"excerpt":"On the news, today, of the early stages of drought hitting the U.S. northeast states I decided to springboard off of yesterday's post and show a more practical use of hexbin state maps than the built-in (and still purpose unknown to me) \"bees\" data. The U.S. Drought Monitor site supplies\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":2288,"url":"https:\/\/rud.is\/b\/2013\/03\/10\/visualizing-risky-words-part-3\/","url_meta":{"origin":10886,"position":5},"title":"Visualizing Risky Words \u2014 Part 3","author":"hrbrmstr","date":"2013-03-10","format":false,"excerpt":"The DST changeover in the US has made today a fairly strange one, especially when combined with a very busy non-computing day yesterday. That strangeness manifest as a need to take the D3 heatmap idea mentioned in the [previous post](http:\/\/rud.is\/b\/2013\/03\/09\/visualizing-risky-words-part-2\/) and actually (mostly) implement it. Folks just coming to this\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":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/10886","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=10886"}],"version-history":[{"count":0,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/posts\/10886\/revisions"}],"wp:attachment":[{"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/media?parent=10886"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/categories?post=10886"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rud.is\/b\/wp-json\/wp\/v2\/tags?post=10886"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}