#30daymapchallenge 2023: a diary!
Updated: Nov 10
I've completed the 30 day map challenge twice now; in 2020 and 2021. I skipped this in 2022 for personal reasons and really missed out - so I'm taking on the challenge again!
This year, I thought I'd keep a brief diary of the maps I create. This will (hopefully) help to keep me accountable, but I thought it would also be handy to share links to data sources, tips on visualization techniques etc. So let's get started!
Day 1: Points.
Down Under: A dot density map of Oceanians & Antarcticans living in London.
As someone who’s lived in London since 2016, I always find it really interesting how you can be walking through a neighborhood and suddenly start hearing a lot of accents from the same part of the world. I thought I’d use this excuse to do a bit of data exploration on this topic - and decided to investigate Down Under London; where do you find the most residents who were born in Oceania?
I'm actually not keen on this map in the end! It looks too much like a population density map, and the dot-density element wasn't so good for drawing out the spatial patterns in the way a heat map or hex map would have been - but I guess that's the whole point of this challenge, experimentation!
The data: Place of Birth data was sourced from NOMIS, and joined to Output Areas from the ONS Geoportal. At the level of detail I wanted, I couldn’t find data for individual countries - just global regions.
The analysis: There are around 26,000 output areas in London, which is pretty hefty for my laptop to deal with. To make this map, I uploaded my two source datasets to Google BigQuery, joined them together and then used the CARTO function ST_GENERATE_POINTS() to turn the data from a choropleth to a dot density point layer (SQL code below!). This generated around 61,000 spatially-weighted random points - one for each of the Antipodeans living in London! I then downloaded this data so I could visualize it in QGIS.
WITH output_areas AS (SELECT geom, geoid FROM `myproject.ukcensus2021.oa_traveltowork` WHERE total is NOT NULL), country_of_birth AS (SELECT * FROM `myproject.30day.day01_country_of_birth`), polys AS (SELECT output_areas.*, country_of_birth.oceania FROM output_areas LEFT JOIN country_of_birth ON output_areas.geoid = country_of_birth.Output_areas WHERE country_of_birth.oceania IS NOT NULL), point_lists AS (SELECT *,myproject.carto.ST_GENERATEPOINTS(geom, oceania) AS points FROM polys) SELECT points AS geom, ST_X(points)A S x, ST_Y(points)AS y FROM point_lists CROSS JOIN point_lists.points
The design: the addition blending mode was super important here. I used this at layer and feature level for the points layer. I then duplicated this and turned the second layer into a very transparent heat map to enhance the glow even further.
I also really like adding a mini-globe inset map to visualizations like this. I made a custom globe projection to centre on the area of interest; you can do this by going to Settings > Custom Projections in QGIS and editing the lat/long in the code below to centre on your location of interest.
+proj=ortho +lat_0=-37.649034 +lon_0=160.57617 +x_0=0 +y_0=0 +a=6371000 +b=6371000 +units=m +no_defs
Day 2: Lines
Travel to Work lines in England & Wales
My background is in GIS transport consultancy, and the Census' travel to work data is one of my all-time favourites to work with. It was released just last week - perfect timing for this project!
The analysis: Really simple analysis for this one! I just needed to create a line geometry between each origin and destination pair. As this dataset is pretty enormous, I loaded the tables into Google BigQuery, filtered out any records with < 10 flows, and then used the ST_MAKELINE() function to create lines. I've written about how to do this in this blog for CARTO.
The design: This map is essentially two versions of the same dataset overlaid. The first is a purple gradient, with lines becoming more opaque the more people are making that journey. The second is a faint blue layer, which I've just used to draw out the lower-end of the trips a little more. You might be able to tell I'm addition to the addition blending mode by this point - it's what is creating this awesome glow effect. Then, I just used a CARTO dark matter basemap and added a few cities on top for context. This dataset is so detailed, I wanted to keep the rest of the design simple.
Day 3: Polygons
Building heights of Manhattan
The data: This data can be downloaded from the NYC Open Data hub here.
The design: I created this map in QGIS and wanted a really simple, almost poster-like effect. I used the GOAT colour ramp magma to have the shorter buildings fade into the purple background. I kicked off the colour classification with a quantile classification method (equal number of features per colour), and then played with this a bit to get to the visual I wanted. Luckily doing these maps for fun rather than work means you get a lot of creative license! I also rotated the map by 29 degrees to be able to have this long, thin map. I think it's funky :)
Day 4: A Bad Map
Contours of Badlands National Park
Today's theme was "a bad map" and unfortunately I couldn't find good enough data on sales of Taylor Swift's Bad Blood, so I decided to find a "bad" place to map instead.
The data: I downloaded SRTM DEMs from https://earthexplorer.usgs.gov/ having reset my password as usual.
The analysis: Really simple this time! I just used the QGIS merge raster function to bring the tiles together into one dataset, then created 10-metre contours.
The design: I fiddled around with lots of different ideas for this map, including a hillshade map or a filled contour map. In the end, I decided I wanted to go for something that felt a bit "sketchy" - like someone could have drawn it up on the train 100 years ago. To do this, I turned on the multiply blending mode for the contour layer at both feature and layer level, and then duplicated it a few times. This helps to give some depth to the contours - especially where they fall closely together - as if someone has shaded the same line multiple times.
Then there was the matter of the park boundary. It's a real funky shape which makes it kind of tricky to define visually. I did three things here:
Used a really thin grey line to outline the park. This grey is actually the same colour as the contours, so couldn't be used in isolation. First, I added a slight drop shadow to this.
Used the invert polygon style with a 50% white transparent fill to slightly mask areas outside the park.
Repeated this, but used a grey > transparent shapeburst fill style
The combination of these three things creates a sort of smudgy, sketchy look that I really enjoy. Not my usual type of map, but I had a lot of fun experimenting with it!
Day 5: Analog
I cannot draw in the slightest, so knew I needed a fun slant on this theme - and decided to create an Ana-log i.e. a map of where all the Ana/Annas live!
The data: I scraped the data from https://forebears.io/forenames/anna (which was a brand new discovery for me for this map!) and then joined it to Natural Earth country polygons which are a real staple for me for the 30 day map challenge.
The analysis: Before creating this map, I had to join the name data to the country polygons. This is always a pretty painful exercise as data sources love to use different naming conventions - and this one also had some countries broken down to their constituent parts (e.g. for the UK, England, Scotland, Wales & Northern Ireland were listed separately. I then used the population estimates which handily come with the Natural Earth polygons to calculate the % of the population called Ana/Anna/variety of, and then doubled this to crudely work out the % of the female population.
The design: This is just a global thematic map so the design isn't too exciting, but there are a few things I like to do to help it along (all in QGIS):
Use of a Robinson compromise projection so countries are shown to have "sort of" the right size and "sort of" the right shape.
Smaller countries are depicted using the handy QGIS centroid fill symbology, so you can actually see data for them on the map.
I always find boundaries a problem with this sort of map. You have to have them or countries just merge together, but finding a colour which is appropriate for every colour band without having really ugly coastlines can be tricky. QGIS has a mega handy feature for this; if you click more options by the stroke colour (or any element of your symbology!) and hit edit, you can use the functions @symbol_color and darker() to denote the colour of each band's stroke, without having to do this individually (see below). So here I've used darker(@symbol_color, 130) to set the stroke to be 30% darker than the fill colour - so neat, right?
Day 6: Asia
Tokyo subway map
The data: This data is just lines with the OpenStreetMap railway. Normally I like to download OSM data using Google BigQuery (check out my guide here) as it's super scalable, but as I only needed a small number of features for this map I used the awesome QGIS plugin QuickOSM, and then used the below filter.
"railway" IN ('subway','light_rail','monorail','rail','tram') AND colour IS NOT NULL
The design: One of the really awesome things about OSM data is users can input a colour tag, so you can set the colour of a stroke (or just about anything!) to be dictated by this variable (check out this screenshot of this in action earlier). Once I had the data and the colours set, I changed the layer blending mode to additive, meaning overlapping layers would get lighter. So what you're looking at here is four versions of the same layer duplicated, getting gradually more transparent and thicker in width - creating this awesome neon effect!
Day 7: Navigation
Distance to the closest pub on the Thames Path
Natural England's National Trails WFS
OpenStreetMap's amenities filtered to pubs & bars sourced from Google BigQuery (see this guide)
USGS Earth Explorer SRTM elevation data
The analysis: There are simple ways and complicated ways of doing this sort of analysis. This is the 30 day map challenge and I'm already tired, so I went for simple. I used the QGIS Split lines by maximum length tool to cut the Thames Path into 50-metre segments, then uploaded the data into Google BigQuery to run a Distance to Nearest (via CARTO Workflows) to calculate the distance to the nearest of the UK's ~45k pubs. I then brought this data back into QGIS to get mapping!
The design: What I really want to talk about here is the basemap, because it's something a little different. While I've used OS Zoomstack for a little minimalist context (major roads, water and railways), I really wanted to keep a natural feel to the basemap and wanted the topography to subtly shape the map. To create this effect, I did the following:
Merged all of the USGS SRTM raster data that I needed into one layer
Used the R.neighbors tool in QGIS to smooth out the raster, calculating the average elevation for a circular neighborhood of 9 cells.
Used to Polygon contour tool to convert these to 50-metre polygons.
Applied a subtle dark to light grey on the polygons, and then under the feature-level draw effects, added a really subtle outer glow and drop shadow. This gives a slightly 3D effect to the contours.
Finally, I overlaid the ESRI hillshade WMS from the QuickMapServices plugin, and turned on the multiply blending mode - this gives a final bit of shape to the topography.
Day 8: Africa
The Big 5
The data: this data was sourced from the IUCN red list species distribution data.
The analysis: Rather than having a pretty cluttered map showing the distributions of five different species, I wanted to create a heatmap style visualization showing where you can find most of these species. The problem? Species distribution data is heavy - it does cover the whole world after all!
To tackle this, I brought the data into Google BigQuery and then set up the below process in CARTO Workflows (you can sign up for a free 14-day trial here if you'd like to have a go yourself!). This process converts the data into a H3 Spatial Index, which is a super lightweight hexagonal grid which geolocates data with an ID rather than a long geometry. I then used the Group by component to count where species' distributions overlapped, before converting this data back into a geometry with H3 Boundary. Finally, I used a custom SQL component to dissolve the boundaries of H3 cells with the same count, before bringing the data back into QGIS...
The design: Not loads to remark upon here! I used a combination of hillshade and ocean basemaps to give a subtle natural feel to quite a simple basemap. My top tip with this map is to experiment with adding an Outer Glow to label outlines/halos (under Label Options > Buffer). This helps labels to stand out from the background but in a way that is really soft. This works really nicely when the text is overlaid on so many different colours.
Day 9: Hexagons
Global night lights
Hooray my favourite theme! I actually REALLY struggled on this day because I'd say 90% of the maps I create for CARTO leverage hexagons - I've even done a whole webinar about why hexagons are so awesome for mapping! In the end, I decided to create a map of global night lights using an awesome type of hexagonal data called H3. H3 is a global, multi-resolution grid called a Spatial Index, for which cells are geolocated by a short reference ID - rather than a long geometry description. This makes them mega lightweight to work with, meaning I can render a map like the below - rendering 4 million hexagonal cells - in seconds!
The data: this data is from the Colorado School of Mines, sourced via the CARTO Spatial Data Catalog here. Anyone with a CARTO account can subscribe to this data for free, and you can grab yourself a free 14-day trial here.
The analysis: So in its raw format, this dataset consists of 2.9 BILLION rows in a 500x500m grid. That's way too much data to effectively map - especially for an interactive map - even when the data is stored in the cloud. To be able to get all of this data on a map, I converted it to a H3 grid using CARTO Workflows (see below, you can learn more about this simple process in this video).
The design: Once the data was aggregated to H3, I loaded the table into CARTO Builder and did a few things to help the design pop:
I turned the resolution of the H3 cells up (or... down!?) to the most detailed level. You can see that as you zoom in and out the resolution changes to make the visualization appropriate (and efficient) for the zoom level.
I changed the colour ramp to one of my favourites - Mako!
I then turned the blending mode to additive and added a duplicated layer to make the lights really glow.
Day 10: North America
Walking to Starbucks in Manhattan
Originally I created a version of this map which showed how many Starbucks could be reached from each cell in a 50-metre grid across Manhattan. This was just way too detailed for the scale we're looking at (I always forget that NYC is so BIG!), so I went for something simpler instead.
The data: I accessed the Starbucks data from OpenStreetMap on Google BigQuery (check out my guide to doing this here). OpenStreetMap isn't always super reliable for business locations like Starbucks, but generally the more "urban" an area the better the data is, as there's likely to be more contributors - and you don't get much more urban than Manhattan!
The analysis: I just created 10-minute walk time isolines using CARTO (guide here) for this, which equates to roughly 800 metres - and that's about it!
The design: One of the things I find really fun about this challenging is designing around really distinctive brands. Starbucks' brand is super recognisable, and they actually have a really comprehensive set of brand guidelines that I used as inspiration for this. I also created a really simple basemap using OpenStreetMap data, and I just love how minimalist and classy this turned out (two words normally not associated with either me or my maps!).