Search code examples
rggplot2r-sfr-sptopojson

Having trouble reading a topojson into R for plotting using ggplot2 and sp


I'm trying to read a topojson into R for ggplot2 use. It seems the rgdal package is being retired, so I'm trying to use st_read in the sp package, but I just get a big box and that's all. It looks like the fields I get are about right, but it's definitely not getting the whole thing in there correctly. It says it only has one feature and two fields. Any idea what I might be doing wrong? Thanks.

I tried following these directions, but nothing seemed to work:

R - Import html/json map file to use for heatmap https://www.r-bloggers.com/2014/09/overcoming-d3-cartographic-envy-with-r-ggplot/

I can give an example file---I know it works, because we do use it and are able to show it with D3, but I want to be able to show it using ggplot2.

Example code that doesn't work:

library(ggplot2)
library(sp)

j <- sf::st_read("mytopo.json")

ggplot() +
  geom_sf(aes(fill = iso_a3), j) +
  coord_sf()

j <- geojsonio::topojson_read("mytopo.json")

ggplot() +
  geom_sf(aes(fill = iso_a3), j) +
  coord_sf()

Note: Deleted the link to the example for security reasons.


Solution

  • These files can be opened in R with some help from mapshaper.org. I used the online upload, but there's a command line tool as well.

    Use mapshaper to export the file as a shapefile. There might be some options to correct the geometries that R has a hard time with, but I'm unfamiliar with mapshaper & it's options. The code below takes care of the problem of invalid geometries pretty well in R. Once converted by mapshaper, you'll have a folder with .dbf, .shp, and .shx files that R's sf package can read.

    library(dplyr)
    library(sf)
    library(ggplot2)
    
    my_sf <- st_read('path/to/shapefile/folder/')
    #> Reading layer `00005f8d4076b8ced__' from data source `path/to/shapefile/folder/' using driver `ESRI Shapefile'
    #> Simple feature collection with 218 features and 1 field (with 3 geometries empty)
    #> Geometry type: MULTIPOLYGON
    #> Dimension:     XY
    #> Bounding box:  xmin: 0 ymin: 0 xmax: 940 ymax: 470
    #> CRS:           NA
    
    # But some geometries are not valid (only showing first 3 rows)
    st_is_valid(my_sf[1:3,])
    #> [1]  TRUE FALSE FALSE
    
    # Fixing the invalid geometries taken from:
    #  https://r-spatial.org/r/2017/03/19/invalid.html#making-invalid-polygons-valid
    
    valid <- st_is_valid(my_sf)
    my_sf_valid <- st_buffer(my_sf[!is.na(valid),], 0.0)
    
    ggplot(my_sf_valid) +
      geom_sf()
    

    The cartogram shows up but is flipped. There's a gis stack question about that here: https://gis.stackexchange.com/a/233792/161721

    It may have something to do with mapshaper flipping coordinates for .svg/topojson files

    width= (SVG/TopoJSON) Set the width of the output dataset in pixels. When used with TopoJSON output, this option switches the output coordinates from geographic units to pixels and flips the Y axis. SVG output is always in pixels (default SVG width is 800).

    Above quote from: https://github.com/mbloch/mapshaper/wiki/Command-Reference

    Created on 2022-03-18 by the reprex package (v2.0.1)