Skip to content

bdgroves/natgeo-style-species-maps

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NatGeo Style Species Maps 🗺️

Recreating the National Geographic editorial map style using open source tools. A cartography learning project with an automated pipeline that builds a new species map every week.

Maps in the Series

# Species Region Tool Status
1 Namibian Wolf Snake 🐍 Southern Africa QGIS
2 Great Basin Bristlecone Pine 🌲 Western USA QGIS
3 Gila Monster 🦎 SW USA / Mexico R
4 Dhole 🐕 South & SE Asia R ✅ Hand-crafted
5 Snow Leopard 🐆 Central Asia R ✅ Auto
6 Ethiopian Wolf 🐺 Horn of Africa R ✅ Auto
7 Red Panda 🐼 Nepal to China R ✅ Auto
8 Kakapo 🦜 New Zealand R ✅ Auto
9 Chafarinas Skink 🦎 N. Africa / Mediterranean R ✅ Auto
10 Verreaux's Sifaka 🐒 Madagascar R ✅ Auto
11 Antanosy Day Gecko 🦎 Madagascar R ✅ Auto

Gallery

Dhole — Cuon alpinus

Dhole

Endangered. Social pack-hunting wild dog found across India through Southeast Asia to the Indonesian archipelago.

Snow Leopard — Panthera uncia

Snow Leopard

Vulnerable. Solitary big cat of the high mountains of Central Asia. Range spans 12 countries from Afghanistan to Mongolia.

Ethiopian Wolf — Canis simensis

Ethiopian Wolf

Endangered. The world's rarest canid, found only in the Ethiopian highlands above 3,000m. Fewer than 500 adults remain.

Red Panda — Ailurus fulgens

Red Panda

Endangered. Arboreal mammal of the eastern Himalayas and southwestern China. Habitat loss and poaching are primary threats.

Kakapo — Strigops habroptila

Kakapo

Critically Endangered. Flightless nocturnal parrot endemic to New Zealand. One of the world's most intensive conservation programs with ~250 individuals.

Chafarinas Skink — Chalcides parallelus

Chafarinas Skink

Vulnerable. Small lizard endemic to the Chafarinas Islands off the coast of Morocco in the Mediterranean. Extremely limited range.

Verreaux's Sifaka — Propithecus verreauxi

Verreauxs Sifaka

Critically Endangered. Distinctive dancing lemur of southwestern Madagascar's dry deciduous forests. Threatened by habitat loss and hunting.

Antanosy Day Gecko — Phelsuma antanosy

Antanosy Day Gecko

Endangered. Vibrant green gecko restricted to a tiny area of southeastern Madagascar. One of the most range-restricted reptiles on the island.

Gila Monster — Heloderma suspectum

Gila Monster

Near Threatened. Venomous lizard of the Sonoran and Chihuahuan Desert regions of the American Southwest and northern Mexico.

Namibian Wolf Snake — Lycophidion namibianum

Wolf Snake

Data Deficient. Endemic to Angola and Namibia in southern Africa.

Great Basin Bristlecone Pine — Pinus longaeva

Bristlecone Pine

Vulnerable. Among the oldest living organisms on Earth. High-elevation Great Basin ranges of the western USA.


Automation Pipeline

Maps 5–11 were built automatically using a reusable pipeline. Add a species shapefile + photo, run one command, and the map builds itself.

How It Works

┌─────────────────────────────────────────────────┐ │ YOU (once per species, ~5 min) │ │ │ │ 1. Download shapefile from IUCN Red List │ │ 2. Find a CC-licensed photo on Wikimedia │ │ 3. Run add_species() → unzips, organizes, │ │ copies photo, adds row to CSV │ ├─────────────────────────────────────────────────┤ │ PIPELINE (automatic) │ │ │ │ 4. run_queue() builds every unbuilt species │ │ 5. Auto-detects map extent from range bbox │ │ 6. Auto-detects countries in view │ │ 7. Auto-places labels at country centroids │ │ 8. Auto-calculates scale bars for latitude │ │ 9. Picks palette from CSV (6 options) │ │ 10. Adds photo + credit to right column │ │ 11. Exports 300 DPI PNG │ └─────────────────────────────────────────────────┘ Copy

Quick Start

setwd("C:/data/R_Projects/natgeo-style-species-maps")
source("R/auto/add_species.R")

add_species(
  common_name       = "Species Name",
  scientific_name   = "Genus species",
  zip_path          = "C:/data/Shapefiles/IUCN/redlist_download.zip",
  photo_path_source = "C:/data/Shapefiles/IUCN/photo.jpg",
  photo_credit      = "Photographer / Source / License",
  palette_type      = "jungle",
  continent         = "Asia",
  iucn_status       = "Endangered"
)

source("R/auto/generate_map.R")
run_queue()

The NatGeo Style
Key design elements recreated from National Geographic
editorial species range maps:
ElementImplementationWarm parchment land#E4DDD0 — #EBE1D1 depending on regionSoft blue ocean#D6E8F0 as panel backgroundSpaced uppercase labelsCustom space_text() functionMuted range colorSpecies-specific earth tone from palette libraryLocator insetFlat WGS-84 regional context mapDual scale barsMiles + km, auto-calculated for latitudeSpecies annotationBold common name + italic scientific nameAnimal photoRight column below locator insetColumn dividerThin rule line between map and sidebarTypographyggplot2 default (Helvetica-style sans-serif)Attribution footerSource + author at 6pt

Color Palettes
Six palettes for different habitats and regions:
PaletteRange ColorHexBest ForDesertTerracotta#D4845AArid / sandy regionsSavannaGolden Ochre#C8A856African grasslandsJungleEarth Brown#8B6E4ETropical AsiaForestSage Green#7A9E6BTemperate woodlandMountainWarm Gray#8C7B6BAlpine / high altitudeOceanSteel Blue#5B8FA8Marine / freshwater
All palettes share the same warm parchment land fill
and soft blue oceanonly the range highlight color
and label tones change.

Lessons Learned
Orthographic Globe Insets
The original design used an orthographic globe inset
(like real NatGeo maps). This works well for Africa and
North America but causes GEOS geometry errors for
Asia-centered projections:
CopyIllegalArgumentException: Invalid number of points
in LinearRing found 2 - must be 0 or >= 4
Root cause: Country polygons crossing the orthographic
hemisphere boundary are clipped into 23 point sliversinvalid LinearRings. ggplot2 defers geometry processing
to render time, so suppressWarnings() does not help.
Solution adopted: Replaced the orthographic globe with
a flat WGS-84 regional locator inset. Visually equivalent,
zero projection math, no crashes. Many real NatGeo maps
use this approach anyway.
Automation Challenges

st_bbox() returns named numeric values — st_crop()
chokes on them. Fix: unname() in auto_extent()
Some cropped country polygons have NA names —
space_text() crashes. Fix: filter(!is.na(name))
before labeling
parse() with escaped quotes inside writeLines()
is fragile. Fix: use bquote() instead
Page height must be calculated from map aspect ratiohardcoded values produce large white gaps

R vs QGIS for This Style
TaskRQGISScripted / reproducible✅❌Fine label placementHarderEasierGlobe insetFragileStableBatch speciesManualPhoto insetmagickManualAutomationGitHub ActionsProject Structure
Copynatgeo-style-species-maps/
│
├── .github/
│   └── workflows/
│       └── weekly_map.yml          # GitHub Actions (planned)
│
├── R/
│   ├── dhole.R                     # Hand-crafted Dhole map
│   ├── gila_monster.R              # Hand-crafted Gila Monster
│   └── auto/
│       ├── generate_map.R          # Auto map builder
│       ├── add_species.R           # Species setup helper
│       ├── post_twitter.R          # Twitter auto-post (planned)
│       └── post_bluesky.R          # Bluesky auto-post (planned)
│
├── QGIS/
│   ├── wolf_snake.qgz             # Namibian Wolf Snake
│   └── bristlecone_pine.qgz       # Bristlecone Pine
│
├── data/
│   ├── species_queue.csv           # Pipeline queue (8 species)
│   ├── Cuon.alpinus-cut.jpg        # Dhole photo
│   └── photos/
│       ├── snow_leopard.jpg
│       ├── ethiopian_wolf.jpg
│       ├── red_panda.jpg
│       ├── kakapo.jpg
│       ├── chafarinas_skink.jpg
│       ├── verreauxs_sifaka.jpg
│       └── antanosy_day_gecko.jpg
│
├── outputs/
│   ├── dhole_natgeo.png
│   ├── snow_leopard_natgeo.png
│   ├── ethiopian_wolf_natgeo.png
│   ├── red_panda_natgeo.png
│   ├── kakapo_natgeo.png
│   ├── chafarinas_skink_natgeo.png
│   ├── verreauxs_sifaka_natgeo.png
│   ├── antanosy_day_gecko_natgeo.png
│   ├── gila_monster_natgeo.png
│   ├── wolf_snake_natgeo.png
│   └── bristlecone_pine_natgeo.png
│
└── README.md

Note: Species shapefiles from IUCN Red List are not
included in this repositorythey are not redistributable.
Download from https://www.iucnredlist.org (free account required).


Data Sources
DataSourceLicenseSpecies rangesIUCN Red ListFree, not redistributableBase mapsNatural EarthPublic domainDhole photoDavidvraju / WikimediaCC BY-SA 4.0Snow Leopard photoBernard Landgraf / WikimediaCC BY-SA 3.0Ethiopian Wolf photoCharles J. Sharp / WikimediaCC BY-SA 4.0Red Panda photoSunuwargr / WikimediaCC BY-SA 4.0Kakapo photoDOC NZ / WikimediaCC BY 2.0Verreaux's Sifaka photoKevin Gepford / WikimediaCC BY-SA 4.0Chafarinas Skink photoEarth.comEditorial useAntanosy Day Gecko photoEarth.comEditorial use

R Package Dependencies
rCopyinstall.packages(c(
  "tidyverse",          # data wrangling + ggplot2
  "sf",                 # spatial data handling
  "rnaturalearth",      # Natural Earth base maps
  "rnaturalearthdata",  # Natural Earth data files
  "cowplot",            # map composition + ggdraw
  "magick"              # animal photo inset
))

How to Reproduce
Auto Pipeline (recommended)
rCopysetwd("path/to/natgeo-style-species-maps")
source("R/auto/add_species.R")

add_species(
  common_name       = "Species Name",
  scientific_name   = "Genus species",
  zip_path          = "path/to/iucn_download.zip",
  photo_path_source = "path/to/photo.jpg",
  photo_credit      = "Photographer / Source / License",
  palette_type      = "jungle",
  continent         = "Asia",
  iucn_status       = "Endangered"
)

source("R/auto/generate_map.R")
run_queue()
Palette Options
Copydesert   → arid / sandy regions
savanna  → African grasslands
jungle   → tropical Asia
forest   → temperate woodland
mountain → alpine / high altitude
ocean    → marine / freshwater
Hand-Crafted Maps
rCopysource("R/dhole.R")          # Dhole — custom labels + layout
source("R/gila_monster.R")   # Gila Monster
QGIS Maps
Open the .qgz project files in QGIS 3.x.
Data layers use relative paths — place shapefiles
in the same directory structure as the project.

Planned Features

 GitHub Actions weekly auto-build
 Auto-post to Twitter/X
 Auto-post to Bluesky
 Label collision detection
 Arctic + tropical palettes
 Gallery webpage from outputs folder
 Social caption templates in CSV


A personal cartography project by Brooks Groves.
Maps produced with open source tools — R and QGIS.
Pipeline automation built with ggplot2, sf, cowplot, and magick.

About

R scripts for generating National Geographic-style species distribution maps using GBIF occurrence data and custom cartographic styling.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages