converting sf object to topojson

400 views Asked by At

I am trying to create a list that is correctly formatted as topoJSON from an sf object.

What would work when reading a valid topoJSON file is:

sa <- jsonlite::read_json("https://raw.githubusercontent.com/pachadotdev/d3po/main/dev/south-america.topojson", simplifyVector = F)

What I am trying to do is:

# install_github("pachadotdev/canadamaps")
library(canadamaps)

library(sf)
library(geojsonio)

provinces <- get_provinces()
provinces <- st_as_sf(provinces)

geojson_write(provinces, file = "provinces.geojson")

provinces2 <- geojson_read("provinces.geojson")

geo2topo(provinces)

Error: no 'geo2topo' method for sftbl_dftbldata.frame

Is there any option to convert to topoJSON from R?

I tried saving as geoJSON and then re-exporting in QGIS, but it doesn't save as topoJSON.

2

There are 2 answers

1
Spacedman On BEST ANSWER

geo2topo works on JSON strings, not R objects.

Start with the geoJSON file you wrote in your example. ogrinfo tells me its geoJSON:

$ ogrinfo provinces.geojson 
INFO: Open of `provinces.geojson'
      using driver `GeoJSON' successful.
1: provinces (Multi Polygon)

Read it into R as text - this is the plain text geoJSON:

> s = readLines("provinces.geojson")
Warning message:
In readLines("provinces.geojson") :
  incomplete final line found on 'provinces.geojson'
> substr(s, 1, 100)
[1] "{\"type\":\"FeatureCollection\",\"features\":[{\"type\":\"Feature\",\"properties\":{\"pruid\":46,\"prname\":\"Manitob"

Now convert to topoJSON string:

> tj = geojsonio::geo2topo(s)
> substr(tj, 1, 100)
{"type":"Topology","objects":{"foo":{"type":"GeometryCollection","geometries":[{"type":"MultiPolygon 

and write text to file:

> writeLines(tj, "tj.topojson")
> 

Giving what gdal interprets as topoJSON:

$ ogrinfo tj.topojson 
INFO: Open of `tj.topojson'
      using driver `TopoJSON' successful.
1: foo (Multi Polygon)

I'm not sure where it gets the foo layer name from, this can probably be set to something else somewhere, unless its actually in the data...

0
Jindra Lacko On

In addition to the geo2topo approach described by Spacedman you can consider geojsonio::topojson_json().

A possible snag could be that the provinces object is in some local CRS, while the current geojson standard expects EPSG:4326 (only). There is a nice story, possibly apocryphal, that the standard setting body did not trust the primary users (IT, not GIS people) to understand the problem of the Earth not being flat and removed the option to use CRS as standardized in the EPSG database, which the original standard allowed.

The geojson / topojson still has hard time with CRS, and even when saved according to standard and read back in to R it struggles with CRS, which is why I had to apply the sf::st_set_crs(4326).

library(sf)
library(geojsonio)
library(canadamaps)

provinces <- get_provinces()
provinces <- st_as_sf(provinces)

provinces %>% 
  st_transform(4326) %>% # the one and only CRS that geojson standard allows
  dplyr::transmute(id = pruid, prname) %>% 
  geojsonio::topojson_json(object_name = "provinces", crs = 4326) %>% 
  geojsonio::topojson_write(file = "oh_canada.json", crs = 4326)

st_read("oh_canada.json") %>% 
  st_set_crs(4326)

# Reading layer `provinces' from data source `/home/jindra/Documents/SmallDev/oh_canada.json' using driver `TopoJSON'
# Simple feature collection with 13 features and 2 fields
# Geometry type: MULTIPOLYGON
# Dimension:     XY
# Bounding box:  xmin: -141.0181 ymin: 41.72967 xmax: -52.61941 ymax: 83.1355
# CRS:           NA
# Simple feature collection with 13 features and 2 fields
# Geometry type: MULTIPOLYGON
# Dimension:     XY
# Bounding box:  xmin: -141.0181 ymin: 41.72967 xmax: -52.61941 ymax: 83.1355
# Geodetic CRS:  WGS 84
# First 10 features:
#    id                                              prname                        geometry
# 1  46                                            Manitoba MULTIPOLYGON (((-101.3625 4...
# 2  47                                        Saskatchewan MULTIPOLYGON (((-102 60, -1...
# 3  48                                             Alberta MULTIPOLYGON (((-110 60, -1...
# 4  59             British Columbia / Colombie-Britannique MULTIPOLYGON (((-120 60, -1...
# 5  24                                     Quebec / Québec MULTIPOLYGON (((-69.05071 4...
# 6  35                                             Ontario MULTIPOLYGON (((-79.51585 5...
# 7  10 Newfoundland and Labrador / Terre-Neuve-et-Labrador MULTIPOLYGON (((-53.81009 4...
# 8  11        Prince Edward Island / Île-du-Prince-Édouard MULTIPOLYGON (((-62.85386 4...
# 9  12                       Nova Scotia / Nouvelle-Écosse MULTIPOLYGON (((-64.0426 45...
# 10 13                   New Brunswick / Nouveau-Brunswick MULTIPOLYGON # ##(((-64.27499 4...