Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workaround to convert geoJSON to topoJSON #193

Closed
tonycmac opened this issue Dec 16, 2022 · 10 comments
Closed

Workaround to convert geoJSON to topoJSON #193

tonycmac opened this issue Dec 16, 2022 · 10 comments
Labels
help wanted ❤️ we'd love your help!

Comments

@tonycmac
Copy link

New to writing issues so apologies if this isn't done correctly but I'm curious if there's any known workarounds to converting geoJSON to topoJSON.

I know that issue 168 made geojsonio::topojson_write() defunct in April 2020 but wondering if there's any programmatic ways to do these conversions.

I've been using mapshaper to manually convert to topoJSON for now and it works but would love to have an R solution to this.

I was naively hopeful that perhaps the github/dev version of geojsonio had fixed this issue but it appears (after installing it) that the issue remains.

Additional info if useful:

My specific use case is utilizing the Government of Canada boundary files and using the Economic regions SHP file. I'm able to read in and use the file using sf::st_read() but attempting to convert it to topoJSON produces the defunct error message. Reviewing the documentation for geojsonio::topojson_write(), it indicates it's just a wrapper for geojsonio::geojson_write() and geojsonio::geo2topo() so I tried doing so and was able to convert successfully to geonJSON but geo2topo() fails.

library(tidyverse)
library(sf)
#> Linking to GEOS 3.9.3, GDAL 3.5.2, PROJ 8.2.1; sf_use_s2() is TRUE

# works fine
can_er_1km <- st_read("C:/Users/machadot/Documents/R/Projects/adhoc/data/econ_regions/ler_000b16a_e.shp") %>% 
  st_transform(crs = 4326) %>% # needs to be in 4326 to do st_intersection
  st_make_valid() %>%  # Nunavut comes up as invalid so this fixes it
  st_simplify(dTolerance = 1000)  # 1km
#> Reading layer `ler_000b16a_e' from data source 
#>   `C:\Users\machadot\Documents\R\Projects\adhoc\data\econ_regions\ler_000b16a_e.shp' 
#>   using driver `ESRI Shapefile'
#> Simple feature collection with 76 features and 4 fields
#> Geometry type: MULTIPOLYGON
#> Dimension:     XY
#> Bounding box:  xmin: 3689439 ymin: 659338.9 xmax: 9015737 ymax: 5242179
#> Projected CRS: PCS_Lambert_Conformal_Conic

# error
can_er_1km %>% 
  geojsonio::topojson_write("C:/Users/machadot/Documents/R/Projects/adhoc/data/er.json")
#> Registered S3 method overwritten by 'geojsonsf':
#>   method        from   
#>   print.geojson geojson
#> Error: topojson_write is temporarily defunct; check back later

# works
can_er_1km %>% 
  geojsonio::geojson_write(file = "C:/Users/machadot/Documents/R/Projects/adhoc/data/er.json")
#> Success! File is at C:/Users/machadot/Documents/R/Projects/adhoc/data/er.json
#> <geojson-file>
#>   Path:       C:/Users/machadot/Documents/R/Projects/adhoc/data/er.json
#>   From class: geo_list

can_geojson <- geojsonio::geojson_read("C:/Users/machadot/Documents/R/Projects/adhoc/data/er.json")

# doesn't work
can_geojson %>% 
  geojsonio::geo2topo()
#> Error in context_eval(join(src), private$context, serialize, await): ReferenceError: FeatureCollection is not defined

Created on 2022-12-16 with reprex v2.0.2

Session info
sessioninfo::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.2.2 (2022-10-31 ucrt)
#>  os       Windows 10 x64 (build 19044)
#>  system   x86_64, mingw32
#>  ui       RTerm
#>  language (EN)
#>  collate  English_Canada.utf8
#>  ctype    English_Canada.utf8
#>  tz       America/New_York
#>  date     2022-12-16
#>  pandoc   2.19.2 @ C:/Users/machadot/Documents/RStudio/bin/quarto/bin/tools/ (via rmarkdown)
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────
#>  package       * version     date (UTC) lib source
#>  assertthat      0.2.1       2019-03-21 [1] CRAN (R 4.2.2)
#>  backports       1.4.1       2021-12-13 [1] CRAN (R 4.2.0)
#>  broom           1.0.1       2022-08-29 [1] CRAN (R 4.2.2)
#>  cellranger      1.1.0       2016-07-27 [1] CRAN (R 4.2.2)
#>  class           7.3-20      2022-01-16 [1] CRAN (R 4.2.2)
#>  classInt        0.4-8       2022-09-29 [1] CRAN (R 4.2.2)
#>  cli             3.4.1       2022-09-23 [1] CRAN (R 4.2.2)
#>  colorspace      2.0-3       2022-02-21 [1] CRAN (R 4.2.2)
#>  crayon          1.5.2       2022-09-29 [1] CRAN (R 4.2.2)
#>  crul            1.3         2022-09-03 [1] CRAN (R 4.2.2)
#>  curl            4.3.3       2022-10-06 [1] CRAN (R 4.2.2)
#>  DBI             1.1.3       2022-06-18 [1] CRAN (R 4.2.2)
#>  dbplyr          2.2.1       2022-06-27 [1] CRAN (R 4.2.2)
#>  digest          0.6.30      2022-10-18 [1] CRAN (R 4.2.2)
#>  dplyr         * 1.0.10      2022-09-01 [1] CRAN (R 4.2.2)
#>  e1071           1.7-12      2022-10-24 [1] CRAN (R 4.2.2)
#>  ellipsis        0.3.2       2021-04-29 [1] CRAN (R 4.2.2)
#>  evaluate        0.18        2022-11-07 [1] CRAN (R 4.2.2)
#>  fansi           1.0.3       2022-03-24 [1] CRAN (R 4.2.2)
#>  fastmap         1.1.0       2021-01-25 [1] CRAN (R 4.2.2)
#>  forcats       * 0.5.2       2022-08-19 [1] CRAN (R 4.2.2)
#>  foreign         0.8-83      2022-09-28 [1] CRAN (R 4.2.2)
#>  fs              1.5.2       2021-12-08 [1] CRAN (R 4.2.2)
#>  gargle          1.2.1       2022-09-08 [1] CRAN (R 4.2.2)
#>  generics        0.1.3       2022-07-05 [1] CRAN (R 4.2.2)
#>  geojson         0.3.4       2020-06-23 [1] CRAN (R 4.2.2)
#>  geojsonio       0.10.0.9000 2022-12-16 [1] Github (ropensci/geojsonio@30897f2)
#>  geojsonsf       2.0.3       2022-05-30 [1] CRAN (R 4.2.2)
#>  ggplot2       * 3.4.0       2022-11-04 [1] CRAN (R 4.2.2)
#>  glue            1.6.2       2022-02-24 [1] CRAN (R 4.2.2)
#>  googledrive     2.0.0       2021-07-08 [1] CRAN (R 4.2.2)
#>  googlesheets4   1.0.1       2022-08-13 [1] CRAN (R 4.2.2)
#>  gtable          0.3.1       2022-09-01 [1] CRAN (R 4.2.2)
#>  haven           2.5.1       2022-08-22 [1] CRAN (R 4.2.2)
#>  highr           0.9         2021-04-16 [1] CRAN (R 4.2.2)
#>  hms             1.1.2       2022-08-19 [1] CRAN (R 4.2.2)
#>  htmltools       0.5.3       2022-07-18 [1] CRAN (R 4.2.2)
#>  httpcode        0.3.0       2020-04-10 [1] CRAN (R 4.2.2)
#>  httr            1.4.4       2022-08-17 [1] CRAN (R 4.2.2)
#>  jqr             1.2.3       2022-03-10 [1] CRAN (R 4.2.2)
#>  jsonlite        1.8.3       2022-10-21 [1] CRAN (R 4.2.2)
#>  KernSmooth      2.23-20     2021-05-03 [1] CRAN (R 4.2.2)
#>  knitr           1.40        2022-08-24 [1] CRAN (R 4.2.2)
#>  lattice         0.20-45     2021-09-22 [1] CRAN (R 4.2.2)
#>  lazyeval        0.2.2       2019-03-15 [1] CRAN (R 4.2.2)
#>  lifecycle       1.0.3       2022-10-07 [1] CRAN (R 4.2.2)
#>  lubridate       1.9.0       2022-11-06 [1] CRAN (R 4.2.2)
#>  magrittr        2.0.3       2022-03-30 [1] CRAN (R 4.2.2)
#>  maptools        1.1-6       2022-12-14 [1] CRAN (R 4.2.2)
#>  modelr          0.1.10      2022-11-11 [1] CRAN (R 4.2.2)
#>  munsell         0.5.0       2018-06-12 [1] CRAN (R 4.2.2)
#>  pillar          1.8.1       2022-08-19 [1] CRAN (R 4.2.2)
#>  pkgconfig       2.0.3       2019-09-22 [1] CRAN (R 4.2.2)
#>  proxy           0.4-27      2022-06-09 [1] CRAN (R 4.2.2)
#>  purrr         * 0.3.5       2022-10-06 [1] CRAN (R 4.2.2)
#>  R.cache         0.16.0      2022-07-21 [1] CRAN (R 4.2.2)
#>  R.methodsS3     1.8.2       2022-06-13 [1] CRAN (R 4.2.0)
#>  R.oo            1.25.0      2022-06-12 [1] CRAN (R 4.2.0)
#>  R.utils         2.12.2      2022-11-11 [1] CRAN (R 4.2.2)
#>  R6              2.5.1       2021-08-19 [1] CRAN (R 4.2.2)
#>  Rcpp            1.0.9       2022-07-08 [1] CRAN (R 4.2.2)
#>  readr         * 2.1.3       2022-10-01 [1] CRAN (R 4.2.2)
#>  readxl          1.4.1       2022-08-17 [1] CRAN (R 4.2.2)
#>  reprex          2.0.2       2022-08-17 [1] CRAN (R 4.2.2)
#>  rgeos           0.6-1       2022-12-14 [1] CRAN (R 4.2.2)
#>  rlang           1.0.6       2022-09-24 [1] CRAN (R 4.2.2)
#>  rmarkdown       2.18        2022-11-09 [1] CRAN (R 4.2.2)
#>  rstudioapi      0.14        2022-08-22 [1] CRAN (R 4.2.2)
#>  rvest           1.0.3       2022-08-19 [1] CRAN (R 4.2.2)
#>  s2              1.1.0       2022-07-18 [1] CRAN (R 4.2.2)
#>  scales          1.2.1       2022-08-20 [1] CRAN (R 4.2.2)
#>  sessioninfo     1.2.2       2021-12-06 [1] CRAN (R 4.2.2)
#>  sf            * 1.0-9       2022-11-08 [1] CRAN (R 4.2.2)
#>  sp              1.5-1       2022-11-07 [1] CRAN (R 4.2.2)
#>  stringi         1.7.8       2022-07-11 [1] CRAN (R 4.2.1)
#>  stringr       * 1.4.1       2022-08-20 [1] CRAN (R 4.2.2)
#>  styler          1.8.1       2022-11-07 [1] CRAN (R 4.2.2)
#>  tibble        * 3.1.8       2022-07-22 [1] CRAN (R 4.2.2)
#>  tidyr         * 1.2.1       2022-09-08 [1] CRAN (R 4.2.2)
#>  tidyselect      1.2.0       2022-10-10 [1] CRAN (R 4.2.2)
#>  tidyverse     * 1.3.2       2022-07-18 [1] CRAN (R 4.2.2)
#>  timechange      0.1.1       2022-11-04 [1] CRAN (R 4.2.2)
#>  tzdb            0.3.0       2022-03-28 [1] CRAN (R 4.2.2)
#>  units           0.8-0       2022-02-05 [1] CRAN (R 4.2.2)
#>  utf8            1.2.2       2021-07-24 [1] CRAN (R 4.2.2)
#>  V8              4.2.2       2022-11-03 [1] CRAN (R 4.2.2)
#>  vctrs           0.5.0       2022-10-22 [1] CRAN (R 4.2.2)
#>  withr           2.5.0       2022-03-03 [1] CRAN (R 4.2.2)
#>  wk              0.7.0       2022-10-13 [1] CRAN (R 4.2.2)
#>  xfun            0.34        2022-10-18 [1] CRAN (R 4.2.2)
#>  xml2            1.3.3       2021-11-30 [1] CRAN (R 4.2.2)
#>  yaml            2.3.6       2022-10-18 [1] CRAN (R 4.2.1)
#> 
#>  [1] C:/Users/machadot/Documents/R/R-4.2.2/library
#> 
#> ──────────────────────────────────────────────────────────────────────────────
@mikemahoney218
Copy link
Member

Hey @tonycmac , appreciate the issue.

Right now, geojsonio is broadly inactive; I took over maintenance of the package to keep it (and its dependencies) on CRAN, but I don't currently have the time (or, frankly, the familiarity with package internals) for feature development.

So, I'm going to leave this issue open in case anyone skimming issues has a good solution for you. I'm personally not aware of any implementations in R for dealing with TopoJSON yet. And if I am able to find anything, I'll make sure I let you know.

@natereal
Copy link

This is a real pity. Power BI requires shapefiles in topoJSON format and it would be great if it was possible to convert in R. I would have thought it was one of the core functions of geojson, so it's a shame the original makers abandoned it.

@mikemahoney218 mikemahoney218 added the help wanted ❤️ we'd love your help! label Jan 17, 2023
@Shaunson26
Copy link
Contributor

Hi all, I had a brief look at this, given my current line of study (JS for R) ...

I assume @oduilln is using mapshaper through node.js ? At least you've installed node.js, used npm to install mapshaper and are calling mapshaper from the command line ...

mapshaper -i input.geojson -o output.topojson format=topojson

I assume this topo is correct .. seems to have "arcs" in the output file ..

Which brings me to the idea that rmapshaper should be able to do it? (will use capital R from here on)

Having a look at the source code there, it either calls mapshaper by using a system2() call, or use the V8 package (running javascript from R, serializing data in and back to R) by including mapshaper.js in the source of the object - Rmapshaper seems to switch between them depending on whether you use a file.path or R object ..

Following on from using mapshaper through a system call by giving Rmapshaper a file.path, i see in Rmapshaper source code, there is this line (utils.R .. sys_mapshaper())

cmd_args <- c(sys_mem, shQuote(in_data_file), command, "-o", shQuote(out_data_file))

which gives the max memory to use, the -i, some command (say -simplify), -o , e.g.

mapshaper 8 -i input.geojson -simplify -o output.geojson

There doesn't seem to be an option (although i've spent little time looking at the source code) to tag on the end of the -o format=topojson .. If I edit the source code of Rmapshaper ..

 cmd_args <- c(sys_mem, shQuote(in_data_file), command, "-o",  shQuote(out_data_file), 'format=topojson')

where I leave command="", I seem to be able to produce the same topojson as calling mapshaper from the command line, given the system2() call now looks like

mapshaper 8 -i input.geojson -o output.geojson format=topojson

Conclusion

If this is correct - please advise! - then either

  • we can ask Rmapshaper to allow this option, and use that as a dependency
  • include mapshaper in this package (if it isn't already?), and follow a simpler approach (system call, V8)

@Shaunson26
Copy link
Contributor

I created this .. ateucher/rmapshaper#128

@Shaunson26
Copy link
Contributor

Shaunson26 commented Feb 1, 2023

I had a look at the issue with geojsonio and geojsonio::topojson_write() #168 .. not sure what the check issues where, but when i uncomment the tests in test-topojson_write.R it seems that there are issues with finding the topojson_write methods? It says they're S3methods() in the NAMESPACE but devtools::missing_s3() showed they were missing... I found here - r-lib/devtools#2293 - that you may need to export the methods (for R v4 .. is version came out around Apr 2020? seems plausible) Although I though you didn't have to .. if I add @export to all the topojson_write methods, they are no longer missing and all the tests pass ..

Was this the main isssue here, or somethin else?

@mikemahoney218
Copy link
Member

Honestly, no idea; I think that was done in ~2019, way before I had anything to do with this package. I can try to investigate once I've got a bit more time, or if you want to make a PR I'd be happy to look it over @Shaunson26

@Shaunson26
Copy link
Contributor

Sweet.. Can do..

@mikemahoney218
Copy link
Member

Hey folks ( @tonycmac , @oduilln and anyone else watching) -- @Shaunson26 contributed a PR which may have fixed this issue. Can someone install the newest development version (via remotes::install_github('ropensci/geojsonio')) and then try writing topojson, and tell me if the results match what you're after?

@mikemahoney218
Copy link
Member

Via email, Carina Hoyer confirms that this works (though is perhaps inefficient; I welcome issues/PRs to fix that!). I'm going to close this out; if there are related issues with writing topoJSON, please feel free to open a new issue.

@github-actions
Copy link

This issue has been automatically locked. If you believe you have found a related problem, please file a new issue (with a reprex: https://reprex.tidyverse.org) and link to this issue.

@github-actions github-actions bot locked and limited conversation to collaborators Feb 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
help wanted ❤️ we'd love your help!
Projects
None yet
Development

No branches or pull requests

4 participants