0

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.

pachadotdev
  • 3,345
  • 6
  • 33
  • 60
  • Sounds like a "find a package for me request". – IRTFM May 16 '23 at 15:50
  • What are you actually trying to convert to a topoJSON file here? From the docs, `geo2topo` will work from a raw geoJSON string or a file containing that. You've tried to run it on an R spatial data frame. Is that what you need? topoJSON from an R spatial data frame without an intermediate file? – Spacedman May 16 '23 at 15:52
  • Duplicate of https://stackoverflow.com/questions/64537922/export-spatialpolygonsdataframe-as-geojson-or-topojson-in-r ? (My google search strategy was "convert from r sf object to topojson object") – IRTFM May 16 '23 at 15:56
  • not a duplicate, this needs to export as topoJSON – pachadotdev May 16 '23 at 15:58
  • @Spacedman any way that produces a list that is topoJSON-formatted is fine, I don't really mind about producing intermediate files – pachadotdev May 16 '23 at 15:59
  • And the next logical search results in: https://gis.stackexchange.com/questions/45138/convert-geojson-to-topojson You did say that an intermediate object was acceptable. – IRTFM May 16 '23 at 16:01

2 Answers2

1

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...

Spacedman
  • 92,590
  • 12
  • 140
  • 224
  • :O the foo is something done in the R side, I can replace it with the object name argument. I can confirm this works and the topoJSON can be passes to highcharts and other maps tools. I added the exported maps here: https://github.com/pachadotdev/canadamaps under the geo/topo json folders – pachadotdev May 16 '23 at 16:41
1

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...
Jindra Lacko
  • 7,814
  • 3
  • 22
  • 44