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

Feature: isolines custom id/retain attributes #153

Closed
hrecht opened this issue Jul 1, 2022 · 4 comments
Closed

Feature: isolines custom id/retain attributes #153

hrecht opened this issue Jul 1, 2022 · 4 comments
Assignees
Labels
feature New feature or enhancement

Comments

@hrecht
Copy link

hrecht commented Jul 1, 2022

Description
Hello, thanks for the great package. I often use the isolines feature with an sf of many source points. I'd like to retain attributes of my source points in the output, either a meaningful id column that I can join to other data or just retaining all columns. As is, the function returns a set of isolines that have a new id number that I can't join to other datasets. I've used a lot of hacky workarounds to retain identifying columns, like looping through points one at a time instead of doing the single API call.

Is this possible to do with some option that I'm missing? If not, it would be a great feature to add.

@hrecht hrecht added the feature New feature or enhancement label Jul 1, 2022
@munterfi
Copy link
Owner

munterfi commented Jul 3, 2022

Thanks for the positive feedback on the package. This is very motivating to continue to maintain the package :)

Retaining the attributes of the input is not ideal, since in many requests to the HERE APIs (not only the isoline routing), there is more than one response (alternatives, different ranges, triplegs …), which by default would lead to duplication of attributes in the resulting sf data.frames. To ensure the possibility of joining input and output data, the order of results is the same as the order of the requests (although they are sent asynchronously to the APIs). Therefore, you can join the results to the input data by using the id column in the results.

The isoline request is somewhat special, since by default (isoline(..., aggregate = TRUE)) it spatially aggregates the isolines of all given points of interest with the same range, and the request IDs are NA since they can no longer be assigned to a single request. Therefore, this option must be disabled to use a non-spatial join.

library(sf)
#> Linking to GEOS 3.10.2, GDAL 3.4.2, PROJ 8.2.1; sf_use_s2() is TRUE
library(hereR)
set_verbose(TRUE)

data(poi)
  • Non-spatial join:
# Add IDs (or use row.names if they are the default sequence)
poi$id <- seq_len(nrow(poi))

# Request isolines, without aggregating
iso = isoline(poi, aggregate = FALSE)
#> Sending 8 request(s) with 1 RPS to: 'https://isoline.router.hereapi.com/v8/isolines?...'
#> Received 8 response(s) with total size: 82.9 Kb

# non-spatial join
(iso_attr <- st_sf(merge(as.data.frame(poi), iso,  by = "id", all = TRUE)))
#> Simple feature collection with 48 features and 7 fields
#> Active geometry column: geometry.x
#> Geometry type: POINT
#> Dimension:     XY
#> Bounding box:  xmin: 6.140028 ymin: 46.00038 xmax: 9.516669 ymax: 47.58039
#> Geodetic CRS:  WGS 84
#> First 10 features:
#>    id   city population rank           departure             arrival range
#> 1   1 Luzern     250000    1 2022-07-03 14:00:32 2022-07-03 14:05:32   300
#> 2   1 Luzern     250000    2 2022-07-03 14:00:32 2022-07-03 14:10:32   600
#> 3   1 Luzern     250000    3 2022-07-03 14:00:32 2022-07-03 14:15:32   900
#> 4   1 Luzern     250000    4 2022-07-03 14:00:32 2022-07-03 14:20:32  1200
#> 5   1 Luzern     250000    5 2022-07-03 14:00:32 2022-07-03 14:25:32  1500
#> 6   1 Luzern     250000    6 2022-07-03 14:00:32 2022-07-03 14:30:32  1800
#> 7   2 Lugano     105388    1 2022-07-03 14:00:32 2022-07-03 14:05:32   300
#> 8   2 Lugano     105388    2 2022-07-03 14:00:32 2022-07-03 14:10:32   600
#> 9   2 Lugano     105388    3 2022-07-03 14:00:32 2022-07-03 14:15:32   900
#> 10  2 Lugano     105388    4 2022-07-03 14:00:32 2022-07-03 14:20:32  1200
#>                   geometry.x                     geometry.y
#> 1  POINT (8.280001 47.05042) POLYGON ((8.245926 47.04895...
#> 2  POINT (8.280001 47.05042) POLYGON ((8.185501 47.04895...
#> 3  POINT (8.280001 47.05042) POLYGON ((8.107224 47.05856...
#> 4  POINT (8.280001 47.05042) POLYGON ((8.070145 47.07092...
#> 5  POINT (8.280001 47.05042) POLYGON ((7.976761 47.21924...
#> 6  POINT (8.280001 47.05042) POLYGON ((7.925949 47.24808...
#> 7  POINT (8.966677 46.00038) POLYGON ((8.954544 46.01624...
#> 8  POINT (8.966677 46.00038) POLYGON ((8.932571 46.03272...
#> 9  POINT (8.966677 46.00038) POLYGON ((8.898239 46.01761...
#> 10 POINT (8.966677 46.00038) POLYGON ((8.866653 45.98877...
  • If you want to keep the aggregated polygons (even if it probably doesn't make sense?), then you could use a spatial join:
# Remove IDs
poi$id <- NULL

# Request isolines, with aggregating
iso = isoline(poi, aggregate = TRUE)
#> Sending 8 request(s) with 1 RPS to: 'https://isoline.router.hereapi.com/v8/isolines?...'
#> Received 8 response(s) with total size: 83 Kb

# Avoid another issue, concerning invalid spherical geometries...
# Consider converting the coordinates to a projected CRS, e.g. for Switzerland: EPSG 2056
sf::sf_use_s2(FALSE)
#> Spherical geometry (s2) switched off
poi <- st_transform(poi, 2056)
iso <- st_transform(iso, 2056)

# Spatial join
iso_attr <- st_join(iso, poi)

# Convert back to lat/lng WGS 84
(iso_attr <- st_transform(iso_attr, 4326))
#> Simple feature collection with 232 features and 7 fields
#> Geometry type: MULTIPOLYGON
#> Dimension:     XY
#> Bounding box:  xmin: 5.84473 ymin: 45.81848 xmax: 9.73389 ymax: 47.93335
#> Geodetic CRS:  WGS 84
#> First 10 features:
#>     id rank           departure             arrival range     city population
#> 1   NA    1 2022-07-03 14:23:42 2022-07-03 14:28:42   300   Luzern     250000
#> 1.1 NA    1 2022-07-03 14:23:42 2022-07-03 14:28:42   300   Lugano     105388
#> 1.2 NA    1 2022-07-03 14:23:42 2022-07-03 14:28:42   300 Lausanne     265702
#> 1.3 NA    1 2022-07-03 14:23:42 2022-07-03 14:28:42   300    Basel     830000
#> 1.4 NA    1 2022-07-03 14:23:42 2022-07-03 14:28:42   300     Bern     275329
#> 1.5 NA    1 2022-07-03 14:23:42 2022-07-03 14:28:42   300   Zurich    1108000
#> 1.6 NA    1 2022-07-03 14:23:42 2022-07-03 14:28:42   300   Geneva    1240000
#> 1.7 NA    1 2022-07-03 14:23:42 2022-07-03 14:28:42   300    Vaduz      36281
#> 2   NA    2 2022-07-03 14:23:42 2022-07-03 14:33:42   600     <NA>         NA
#> 3   NA    3 2022-07-03 14:23:42 2022-07-03 14:38:42   900     <NA>         NA
#>                           geometry
#> 1   MULTIPOLYGON (((8.95523 46....
#> 1.1 MULTIPOLYGON (((8.95523 46....
#> 1.2 MULTIPOLYGON (((8.95523 46....
#> 1.3 MULTIPOLYGON (((8.95523 46....
#> 1.4 MULTIPOLYGON (((8.95523 46....
#> 1.5 MULTIPOLYGON (((8.95523 46....
#> 1.6 MULTIPOLYGON (((8.95523 46....
#> 1.7 MULTIPOLYGON (((8.95523 46....
#> 2   MULTIPOLYGON (((8.95523 45....
#> 3   MULTIPOLYGON (((8.95935 45....

sf::sf_use_s2(TRUE)
#> Spherical geometry (s2) switched on

I hope this solves your issue? Maybe it would make more sense to set aggregate = FALSE as default?

Session info
devtools::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.2.0 (2022-04-22)
#>  os       macOS Big Sur/Monterey 10.16
#>  system   x86_64, darwin17.0
#>  ui       X11
#>  language (EN)
#>  collate  en_US.UTF-8
#>  ctype    en_US.UTF-8
#>  tz       Europe/Zurich
#>  date     2022-07-03
#>  pandoc   2.18 @ /usr/local/bin/ (via rmarkdown)
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────
#>  package      * version    date (UTC) lib source
#>  brio           1.1.3      2021-11-30 [1] CRAN (R 4.2.0)
#>  cachem         1.0.6      2021-08-19 [1] CRAN (R 4.2.0)
#>  callr          3.7.0      2021-04-20 [1] CRAN (R 4.2.0)
#>  class          7.3-20     2022-01-16 [1] CRAN (R 4.2.0)
#>  classInt       0.4-7      2022-06-10 [1] CRAN (R 4.2.0)
#>  cli            3.3.0      2022-04-25 [1] CRAN (R 4.2.0)
#>  crayon         1.5.1      2022-03-26 [1] CRAN (R 4.2.0)
#>  crul           1.2.0      2021-11-22 [1] CRAN (R 4.2.0)
#>  curl           4.3.2      2021-06-23 [1] CRAN (R 4.2.0)
#>  data.table     1.14.2     2021-09-27 [1] CRAN (R 4.2.0)
#>  DBI            1.1.3      2022-06-18 [1] CRAN (R 4.2.0)
#>  desc           1.4.1      2022-03-06 [1] CRAN (R 4.2.0)
#>  devtools       2.4.3      2021-11-30 [1] CRAN (R 4.2.0)
#>  digest         0.6.29     2021-12-01 [1] CRAN (R 4.2.0)
#>  dplyr          1.0.9      2022-04-28 [1] CRAN (R 4.2.0)
#>  e1071          1.7-11     2022-06-07 [1] CRAN (R 4.2.0)
#>  ellipsis       0.3.2      2021-04-29 [1] CRAN (R 4.2.0)
#>  evaluate       0.15       2022-02-18 [1] CRAN (R 4.2.0)
#>  fansi          1.0.3      2022-03-24 [1] CRAN (R 4.2.0)
#>  fastmap        1.1.0      2021-01-25 [1] CRAN (R 4.2.0)
#>  flexpolyline   0.2.5      2021-11-19 [1] CRAN (R 4.2.0)
#>  fs             1.5.2      2021-12-08 [1] CRAN (R 4.2.0)
#>  generics       0.1.2      2022-01-31 [1] CRAN (R 4.2.0)
#>  glue           1.6.2      2022-02-24 [1] CRAN (R 4.2.0)
#>  hereR        * 0.8.2.9000 2022-06-30 [1] local
#>  htmltools      0.5.2      2021-08-25 [1] CRAN (R 4.2.0)
#>  httpcode       0.3.0      2020-04-10 [1] CRAN (R 4.2.0)
#>  jsonlite       1.8.0      2022-02-22 [1] CRAN (R 4.2.0)
#>  KernSmooth     2.23-20    2021-05-03 [1] CRAN (R 4.2.0)
#>  knitr          1.39       2022-04-26 [1] CRAN (R 4.2.0)
#>  lifecycle      1.0.1      2021-09-24 [1] CRAN (R 4.2.0)
#>  magrittr       2.0.3      2022-03-30 [1] CRAN (R 4.2.0)
#>  memoise        2.0.1      2021-11-26 [1] CRAN (R 4.2.0)
#>  pillar         1.7.0      2022-02-01 [1] CRAN (R 4.2.0)
#>  pkgbuild       1.3.1      2021-12-20 [1] CRAN (R 4.2.0)
#>  pkgconfig      2.0.3      2019-09-22 [1] CRAN (R 4.2.0)
#>  pkgload        1.2.4      2021-11-30 [1] CRAN (R 4.2.0)
#>  prettyunits    1.1.1      2020-01-24 [1] CRAN (R 4.2.0)
#>  processx       3.5.3      2022-03-25 [1] CRAN (R 4.2.0)
#>  proxy          0.4-27     2022-06-09 [1] CRAN (R 4.2.0)
#>  ps             1.7.0      2022-04-23 [1] CRAN (R 4.2.0)
#>  purrr          0.3.4      2020-04-17 [1] CRAN (R 4.2.0)
#>  R6             2.5.1      2021-08-19 [1] CRAN (R 4.2.0)
#>  Rcpp           1.0.8.3    2022-03-17 [1] CRAN (R 4.2.0)
#>  remotes        2.4.2      2021-11-30 [1] CRAN (R 4.2.0)
#>  rlang          1.0.2      2022-03-04 [1] CRAN (R 4.2.0)
#>  rmarkdown      2.14       2022-04-25 [1] CRAN (R 4.2.0)
#>  rprojroot      2.0.3      2022-04-02 [1] CRAN (R 4.2.0)
#>  rstudioapi     0.13       2020-11-12 [1] CRAN (R 4.2.0)
#>  s2             1.0.7      2021-09-28 [1] CRAN (R 4.2.0)
#>  sessioninfo    1.2.2      2021-12-06 [1] CRAN (R 4.2.0)
#>  sf           * 1.0-7      2022-03-07 [1] CRAN (R 4.2.0)
#>  stringi        1.7.6      2021-11-29 [1] CRAN (R 4.2.0)
#>  stringr        1.4.0      2019-02-10 [1] CRAN (R 4.2.0)
#>  testthat       3.1.4      2022-04-26 [1] CRAN (R 4.2.0)
#>  tibble         3.1.7      2022-05-03 [1] CRAN (R 4.2.0)
#>  tidyselect     1.1.2      2022-02-21 [1] CRAN (R 4.2.0)
#>  units          0.8-0      2022-02-05 [1] CRAN (R 4.2.0)
#>  usethis        2.1.6      2022-05-25 [1] CRAN (R 4.2.0)
#>  utf8           1.2.2      2021-07-24 [1] CRAN (R 4.2.0)
#>  vctrs          0.4.1      2022-04-13 [1] CRAN (R 4.2.0)
#>  withr          2.5.0      2022-03-03 [1] CRAN (R 4.2.0)
#>  wk             0.6.0      2022-01-03 [1] CRAN (R 4.2.0)
#>  xfun           0.31       2022-05-10 [1] CRAN (R 4.2.0)
#>  yaml           2.3.5      2022-02-21 [1] CRAN (R 4.2.0)
#> 
#>  [1] /Library/Frameworks/R.framework/Versions/4.2/Resources/library
#> 
#> ──────────────────────────────────────────────────────────────────────────────

@munterfi munterfi self-assigned this Jul 3, 2022
@hrecht
Copy link
Author

hrecht commented Jul 8, 2022

Hi, thanks for the detailed reply! I didn't realize that the isoline function maintained the order of the source points. That's really helpful.
Yeah, I personally would never use the aggregated option - but that's just me.

@munterfi
Copy link
Owner

Thanks for the feedback, isoline(..., aggregate = FALSE) is now set as default.

@hrecht
Copy link
Author

hrecht commented Jul 24, 2022

Nice, thanks!

munterfi added a commit that referenced this issue Jul 24, 2022
Set `aggregate = FALSE` as default in `isoline()`, closes #153.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or enhancement
Projects
None yet
Development

No branches or pull requests

2 participants