Giter VIP home page Giter VIP logo

munterfi / herer Goto Github PK

View Code? Open in Web Editor NEW
82.0 3.0 11.0 39.4 MB

R package that provides an interface to the HERE REST APIs: Geocoder API, Routing API, Traffic API, Public Transit API and Destination Weather API. Locations and routes are returned as 'sf' objects.

Home Page: https://munterfi.github.io/hereR/

License: GNU General Public License v3.0

R 100.00%
routing geocoding traffic weather isoline here-technologies api rspatial rstats gis

herer's People

Contributors

balthasars avatar dpprdan avatar munterfi avatar panhypersebastos avatar szaboildi avatar tomjaksztat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

herer's Issues

Bug: isoline fails when response polygon is multipart

Describe the bug
I'm running isoline() on many points and am getting the following errors on a small number. I've discovered that this is happening response returns multiple polygons, by using the url_only option to see the returned data in the browser. This might be happening because it's near a coastline and islands? Just a guess.

When using multiple times in range:
Error in UseMethod("decode_sf", encoded) : no applicable method for 'decode_sf' applied to an object of class "list"

When using just one time:
Error in decode(encoded[[x]]) : Invalid format version

Reproducible example

point_test <- data.frame(
	latitude = 41.73076,
	longitude = -72.79058)

point_test <- st_as_sf(point_test, coords = c("longitude", "latitude")) %>% 
	st_set_crs(4326)

test <- isoline(
	poi = point_test,
	range = 180 * 60,
	range_type = "time",
	transport_mode = "car",
	url_only = F,
	optimize = "quality",
	traffic = F,
	aggregate = F
)
test2 <- isoline(
	poi = point_test,
	range = c(120 * 60, 180 * 60),
	range_type = "time",
	transport_mode = "car",
	url_only = F,
	optimize = "quality",
	traffic = F,
	aggregate = F
)

Expected behavior
Successful isolines returned.

Optionally: R session info
version R version 4.0.4 (2021-02-15)
os macOS Catalina 10.15.7

New CRAN issues of v0.4.0 on all platforms

{hereR} v0.4.0 is encountering new issues on CRAN, which have to be fixed before 2020-08-26 to safely retain the package on CRAN: https://cran.r-project.org/web/checks/check_results_hereR.html

The building of the vignettes fails due to a new release of {mapview} v2.9.0 on CRAN:

* checking package vignettes in ‘inst/doc’ ... OK
* checking re-building of vignette outputs ... [40s/51s] WARNING
Error(s) in re-building vignettes:
  ...
--- re-building ‘authentication.Rmd’ using rmarkdown
--- finished re-building ‘authentication.Rmd’

--- re-building ‘geocoder.Rmd’ using rmarkdown
Could not determine mime type for `/tmp/RtmpVgrBta/file55575cf9ebdc/geocoded_layer.fgb'
Error: processing vignette 'geocoder.Rmd' failed with diagnostics:
pandoc document conversion failed with error 63
--- failed re-building ‘geocoder.Rmd’

--- re-building ‘intermodal.Rmd’ using rmarkdown
Could not determine mime type for `/tmp/RtmpKDZmI2/file607e4277b938/Intermodalroute_layer.fgb'
Error: processing vignette 'intermodal.Rmd' failed with diagnostics:
pandoc document conversion failed with error 63
--- failed re-building ‘intermodal.Rmd’

--- re-building ‘routing.Rmd’ using rmarkdown
Could not determine mime type for `/tmp/RtmpqWMhLS/file6b0624241742/Route[O-D]_layer.fgb'
Error: processing vignette 'routing.Rmd' failed with diagnostics:
pandoc document conversion failed with error 63
--- failed re-building ‘routing.Rmd’

--- re-building ‘traffic.Rmd’ using rmarkdown
Could not determine mime type for `/tmp/RtmpnKfVY1/file717d30881319/Jamfactor_layer.fgb'
Error: processing vignette 'traffic.Rmd' failed with diagnostics:
pandoc document conversion failed with error 63
--- failed re-building ‘traffic.Rmd’

--- re-building ‘transit.Rmd’ using rmarkdown
Could not determine mime type for `/tmp/Rtmp28fq3V/file785a69cecc7d/Transportmode_layer.fgb'
Error: processing vignette 'transit.Rmd' failed with diagnostics:
pandoc document conversion failed with error 63
--- failed re-building ‘transit.Rmd’

--- re-building ‘weather.Rmd’ using rmarkdown
Could not determine mime type for `/tmp/RtmplrmSn6/file551555cf1e8/Observation_layer.fgb'
Error: processing vignette 'weather.Rmd' failed with diagnostics:
pandoc document conversion failed with error 63
--- failed re-building ‘weather.Rmd’

SUMMARY: processing the following files failed:
  ‘geocoder.Rmd’ ‘intermodal.Rmd’ ‘routing.Rmd’ ‘traffic.Rmd’
  ‘transit.Rmd’ ‘weather.Rmd’

Error: Vignette re-building failed.
Execution halted

Bug: Suggested packages should be used conditionally

CRAN complains about missing if(requireNamespace("pkgname")) statements in the package vignettes:

This concerns packages

[... hereR ...]

Suggested packages should be used conditionally: see §1.1.3.1 of 'Writing R Extensions'. Some of these are hard to install on a platform without X11 such as M1 Macs: see the logs at https://www.stats.ox.ac.uk/pub/bdr/M1mac/.

You can check all of the suggested packages by setting environment variable R_CHECK_DEPENDS_ONLY=true -- see https://cran.r-project.org/doc/manuals/r-devel/R-ints.html#Tools .

Please correct ASAP and before 2021-01-12 to safely retain the package on CRAN.

According to 1.1.3.1 Suggested packages, the solution is:

However, using require for conditioning in package code is not good practice as it alters the search path for the rest of the session and relies on functions in that package not being masked by other require or library calls. It is better practice to use code like:

if (requireNamespace("rgl", quietly = TRUE)) {
  rgl::plot3d(...)
} else {
  ## do something else not involving rgl.
}

Note the use of rgl:: as that object would not necessarily be visible (and if it is, it need not be the one from that namespace: plot3d occurs in several other packages). If the intention is to give an error if the suggested package is not available, simply use e.g. rgl::plot3d.

In the vignettes of hereR this is pointing to the mapview, leafpop and ggplot2 packages, which are listed as suggested packages. There seem to be two solutions:

  1. Add the statement above to the vignettes and come up with a fallback solution if the packages are not present.
  2. Remove them from the vignettes and suggested packages in DESCRIPTION and use the fall back solution instead. This would also be preferable with regard to the size of the vignettes.

Feature: Filter transport modes in 'connection()'

Add parameter to allow filtering transport modes in connection().

# Use minus to avoid modes
connection(..., modes = c("-highSpeedTrain", "-subway", "-monorail"))

# ... or use another boolean parameter
connection(..., modes = c("highSpeedTrain", "subway", "monorail"), avoid_modes = FALSE)

All modes:

Name Vehicle types
highSpeedTrain High-speed trains
intercityTrain Intercity/EuroCity trains
interRegionalTrain Inter-regional and fast trains
regionalTrain Regional and other trains
cityTrain City trains
bus Buses
ferry Boats/Ferries
subway Metros/Subways
lightRail Trams
privateBus Ordered services/Taxis
inclined Inclined/Funiculars
aerial Aerials/Cable cars
busRapid Rapid buses
monorail Monorails
flight Airplanes
walk Walk

See the API documentation.

TologogyException with default setting aggregate = F

With some (only a few) queries a TopologyException: found non-noded intersection between LINESTRING ( ... is thrown, when the default of the paremter aggregate = T is set.

library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1
hereR::set_key("TOKEN")

hereR::isoline(st_sf(st_sfc(st_point(c(6.950437 , 50.93997)), crs = 4326)),
               range = c(seq(1, 50, 5)) * 60, 
               range_type = "time",
               mode = "car",
               traffic = TRUE,
               datetime = as.POSIXct("2020-11-10 08:00")
)
#> Error in CPL_nary_difference(x): Evaluation error: TopologyException: found non-noded intersection between LINESTRING (7.08893 50.8255, 7.08893 50.8255) and LINESTRING (7.08893 50.8255, 7.08893 50.8255) at 7.0889299999999977 50.825500000000005.

Created on 2020-12-16 by the reprex package (v0.3.0)

Created on 2020-12-16 by the reprex package (v0.3.0)

error in the connection function

I was trying to use this function with my own data but appears the following error:

Error in `$<-.data.frame`(x, name, value) : 
  replacement has 1 row, data has 0`

My code is the following:

library(hereR)
library(sf)
library(stringr)
set_key("MyAPIKey")
bs <- tibble::tribble(  ~COD_USUSEN,       ~x,        ~y,
       "B01I", 349256.6,   6303178,
       "B01I", 349032.5, 6303101.5,
       "B01I", 348914.7, 6303158.8,
       "B01I", 348714.8,   6303276,
       "B01I", 348693.4, 6303503.9,
       "B01I", 348699.4, 6303567.2,
       "B01I", 348449.2, 6303715.7,
       "B01I", 348014.2, 6303966.7,
       "B01I", 347829.6,   6304033,
       "B01I", 347732.5, 6304071.4,
       "B01I", 347488.4, 6304142.3,
       "B01I", 347270.1, 6304170.3,
       "B01I", 347200.9, 6304201.1,
       "B01I", 346922.5, 6304355.4,
       "B01I", 346697.2, 6304472.4,
       "B01I", 346523.3, 6304555.1,
       "B01I", 346183.2, 6304584.1,
       "B01I", 345893.4, 6304613.5,
       "B01I", 345703.3, 6304627.8,
       "B01I", 345480.4, 6304639.7,
       "B01I", 345169.6, 6304660.5,
       "B01I", 344928.3, 6304657.4,
       "B01I", 344717.1, 6304656.9,
       "B01I", 344645.7, 6304892.8,
       "B01I",   344497, 6304881.9,
       "B01I", 344252.6, 6304845.4,
       "B01I", 343985.8, 6304866.5,
       "B01I", 343856.6, 6304856.6,
       "B01I", 343734.8,   6304646,
       "B01I", 343555.6, 6304563.3,
       "B01I", 343307.6, 6304450.2,
       "B01I", 342935.4, 6304260.9,
       "B01I", 342860.5, 6304052.8,
       "B01I", 342685.7, 6303791.2,
       "B01I", 342454.4, 6303756.6,
       "B01I", 342308.5, 6303769.5,
       "B01I",   342120, 6303787.8,
       "B01I", 341835.9, 6303808.5,
       "B01I", 341902.4, 6304022.9,
       "B01I", 341958.6, 6304173.8,
       "B01I", 342060.4, 6304440.5,
       "B01I", 342141.7, 6304645.4
  )

bs <- st_as_sf(bs, coords = c("x", "y")) %>%
  st_set_crs(32719) %>%
  st_transform(4326)

O <- station(bs[1,], radius = 500) %>%
  filter(str_detect(lines, "B01") == T) %>%
  select(-c(station, lines))
D <- station(bs[42,], radius = 500) %>%
  filter(str_detect(lines, "B01") == T) %>%
  select(-c(station, lines))

timePT <- connection(origin = O[1,], destination = D[1, ])

Geocode error

Hi,
I've got the following error with the exemple:
geocode(c("Schweighofstrasse 190, Zurich, Switzerland", "Hardstrasse 48, Zurich, Switzerland"))
NULL
Warning messages:
1: In (function (res) : Request 'id = 2' failed: Status 400.
2: In (function (res) : Request 'id = 1' failed: Status 400.

Status 400 means Bad Request.

Any ideas?

Geocode: Optionally return alternative locations

As mentioned by @spatialhusky in #81, geocode() should provide an option to return alternative geocoding results.

Alternative results are not returned in any case, as the raw JSON responses from the Geocoder API show for different requests:

library(hereR)
set_key("<APIKEY>")
set_verbose(TRUE)
Single result
url <- geocode("Schweighofstrasse, Zürich, Switzerland", url_only = TRUE)
json <- hereR:::.get_content(url)
#> Sending 1 request(s) to: 'https://geocode.search.hereapi.com/v1/geocode?...'
#> Received 1 response(s) with total size: 968 bytes
jsonlite::prettify(json)
#> {
#>     "items": [
#>         {
#>             "title": "Schweighofstrasse, Zürich Zürich, Schweiz",
#>             "id": "here:af:streetsection:Tuxxas8I0326Adw-GMpvCB",
#>             "resultType": "street",
#>             "address": {
#>                 "label": "Schweighofstrasse, Zürich Zürich, Schweiz",
#>                 "countryCode": "CHE",
#>                 "countryName": "Schweiz",
#>                 "stateCode": "ZH",
#>                 "state": "Zürich",
#>                 "county": "Zürich",
#>                 "city": "Zürich",
#>                 "district": "Kreis 3",
#>                 "street": "Schweighofstrasse"
#>             },
#>             "position": {
#>                 "lat": 47.36482,
#>                 "lng": 8.50271
#>             },
#>             "mapView": {
#>                 "west": 8.50036,
#>                 "south": 47.35341,
#>                 "east": 8.51184,
#>                 "north": 47.36878
#>             },
#>             "scoring": {
#>                 "queryScore": 1.0,
#>                 "fieldScore": {
#>                     "country": 1.0,
#>                     "city": 1.0,
#>                     "streets": [
#>                         1.0
#>                     ]
#>                 }
#>             }
#>         }
#>     ]
#> }
#> 
Multiple results
url <- geocode("404 Wyman St #300, Waltham, MA, 02451, United Sates", url_only = TRUE)
json <- hereR:::.get_content(url)
#> Sending 1 request(s) to: 'https://geocode.search.hereapi.com/v1/geocode?...'
#> Received 1 response(s) with total size: 4.5 Kb
jsonlite::prettify(json)
#> {
#>     "items": [
#>         {
#>             "title": "404 Wyman St, Broken Hill NSW 2880, Australia",
#>             "id": "here:af:streetsection:mz6vcU0tg6ShaiNMU0dbkD:CggIBCD0kr2eARABGgM0MDQoZA",
#>             "resultType": "houseNumber",
#>             "houseNumberType": "PA",
#>             "address": {
#>                 "label": "404 Wyman St, Broken Hill NSW 2880, Australia",
#>                 "countryCode": "AUS",
#>                 "countryName": "Australia",
#>                 "stateCode": "NSW",
#>                 "state": "New South Wales",
#>                 "city": "Broken Hill",
#>                 "street": "Wyman St",
#>                 "postalCode": "2880",
#>                 "houseNumber": "404"
#>             },
#>             "position": {
#>                 "lat": -31.94001,
#>                 "lng": 141.45513
#>             },
#>             "access": [
#>                 {
#>                     "lat": -31.94031,
#>                     "lng": 141.45538
#>                 }
#>             ],
#>             "mapView": {
#>                 "west": 141.45407,
#>                 "south": -31.94091,
#>                 "east": 141.45619,
#>                 "north": -31.93911
#>             },
#>             "scoring": {
#>                 "queryScore": 1.0,
#>                 "fieldScore": {
#>                     "streets": [
#>                         1.0
#>                     ],
#>                     "houseNumber": 1.0
#>                 }
#>             }
#>         },
#>         {
#>             "title": "404 Wyman St, Waltham, MA 02451-1210, United States",
#>             "id": "here:af:streetsection:8XJ.l40GZCw2R4HVzpIpiC:CgcIBCDVmqsfEAEaAzQwNChk",
#>             "resultType": "houseNumber",
#>             "houseNumberType": "PA",
#>             "address": {
#>                 "label": "404 Wyman St, Waltham, MA 02451-1210, United States",
#>                 "countryCode": "USA",
#>                 "countryName": "United States",
#>                 "stateCode": "MA",
#>                 "state": "Massachusetts",
#>                 "county": "Middlesex",
#>                 "city": "Waltham",
#>                 "district": "Piety Corner",
#>                 "street": "Wyman St",
#>                 "postalCode": "02451-1210",
#>                 "houseNumber": "404"
#>             },
#>             "position": {
#>                 "lat": 42.40847,
#>                 "lng": -71.25705
#>             },
#>             "access": [
#>                 {
#>                     "lat": 42.4098,
#>                     "lng": -71.25522
#>                 }
#>             ],
#>             "mapView": {
#>                 "west": -71.25962,
#>                 "south": 42.40657,
#>                 "east": -71.25448,
#>                 "north": 42.41037
#>             },
#>             "scoring": {
#>                 "queryScore": 1.0,
#>                 "fieldScore": {
#>                     "streets": [
#>                         1.0
#>                     ],
#>                     "houseNumber": 1.0
#>                 }
#>             }
#>         },
#>         {
#>             "title": "404 Wyman St, New London, WI 54961-1431, United States",
#>             "id": "here:af:streetsection:0Wc-8Kpo2X-DxR6cktglqA:EAIaAzQwNChk",
#>             "resultType": "houseNumber",
#>             "houseNumberType": "interpolated",
#>             "address": {
#>                 "label": "404 Wyman St, New London, WI 54961-1431, United States",
#>                 "countryCode": "USA",
#>                 "countryName": "United States",
#>                 "stateCode": "WI",
#>                 "state": "Wisconsin",
#>                 "county": "Waupaca",
#>                 "city": "New London",
#>                 "street": "Wyman St",
#>                 "postalCode": "54961-1431",
#>                 "houseNumber": "404"
#>             },
#>             "position": {
#>                 "lat": 44.38946,
#>                 "lng": -88.74292
#>             },
#>             "access": [
#>                 {
#>                     "lat": 44.38946,
#>                     "lng": -88.74311
#>                 }
#>             ],
#>             "mapView": {
#>                 "west": -88.74418,
#>                 "south": 44.38856,
#>                 "east": -88.74166,
#>                 "north": 44.39036
#>             },
#>             "scoring": {
#>                 "queryScore": 1.0,
#>                 "fieldScore": {
#>                     "streets": [
#>                         1.0
#>                     ],
#>                     "houseNumber": 1.0
#>                 }
#>             }
#>         },
#>         {
#>             "title": "404 Wyman St, Sycamore, IL 60178, United States",
#>             "id": "here:af:streetsection:lFOA2H38U-uR1ES9DkVqWD:EAIaAzQwNChk",
#>             "resultType": "houseNumber",
#>             "houseNumberType": "interpolated",
#>             "address": {
#>                 "label": "404 Wyman St, Sycamore, IL 60178, United States",
#>                 "countryCode": "USA",
#>                 "countryName": "United States",
#>                 "stateCode": "IL",
#>                 "state": "Illinois",
#>                 "county": "Dekalb",
#>                 "city": "Sycamore",
#>                 "street": "Wyman St",
#>                 "postalCode": "60178",
#>                 "houseNumber": "404"
#>             },
#>             "position": {
#>                 "lat": 41.97939,
#>                 "lng": -88.69335
#>             },
#>             "access": [
#>                 {
#>                     "lat": 41.97952,
#>                     "lng": -88.69335
#>                 }
#>             ],
#>             "mapView": {
#>                 "west": -88.69456,
#>                 "south": 41.97849,
#>                 "east": -88.69214,
#>                 "north": 41.98029
#>             },
#>             "scoring": {
#>                 "queryScore": 1.0,
#>                 "fieldScore": {
#>                     "streets": [
#>                         1.0
#>                     ],
#>                     "houseNumber": 1.0
#>                 }
#>             }
#>         },
#>         {
#>             "title": "404 Wyman St, Sheldon, IA 51201-1953, United States",
#>             "id": "here:af:streetsection:X8Fr32OEG0xlH8mOTnq.KB:EAIaAzQwNChk",
#>             "resultType": "houseNumber",
#>             "houseNumberType": "interpolated",
#>             "address": {
#>                 "label": "404 Wyman St, Sheldon, IA 51201-1953, United States",
#>                 "countryCode": "USA",
#>                 "countryName": "United States",
#>                 "stateCode": "IA",
#>                 "state": "Iowa",
#>                 "county": "Obrien",
#>                 "city": "Sheldon",
#>                 "street": "Wyman St",
#>                 "postalCode": "51201-1953",
#>                 "houseNumber": "404"
#>             },
#>             "position": {
#>                 "lat": 43.17528,
#>                 "lng": -95.85585
#>             },
#>             "access": [
#>                 {
#>                     "lat": 43.17541,
#>                     "lng": -95.8558
#>                 }
#>             ],
#>             "mapView": {
#>                 "west": -95.85708,
#>                 "south": 43.17438,
#>                 "east": -95.85462,
#>                 "north": 43.17618
#>             },
#>             "scoring": {
#>                 "queryScore": 1.0,
#>                 "fieldScore": {
#>                     "streets": [
#>                         1.0
#>                     ],
#>                     "houseNumber": 1.0
#>                 }
#>             }
#>         },
#>         {
#>             "title": "404 Wyman St, West Union, IL 62477, United States",
#>             "id": "here:af:streetsection:NJp8Mz2tM6T8d98cVnYH7C:EAIaAzQwNChk",
#>             "resultType": "houseNumber",
#>             "houseNumberType": "interpolated",
#>             "address": {
#>                 "label": "404 Wyman St, West Union, IL 62477, United States",
#>                 "countryCode": "USA",
#>                 "countryName": "United States",
#>                 "stateCode": "IL",
#>                 "state": "Illinois",
#>                 "county": "Clark",
#>                 "city": "West Union",
#>                 "street": "Wyman St",
#>                 "postalCode": "62477",
#>                 "houseNumber": "404"
#>             },
#>             "position": {
#>                 "lat": 39.21663,
#>                 "lng": -87.66111
#>             },
#>             "access": [
#>                 {
#>                     "lat": 39.21666,
#>                     "lng": -87.66128
#>                 }
#>             ],
#>             "mapView": {
#>                 "west": -87.66227,
#>                 "south": 39.21573,
#>                 "east": -87.65995,
#>                 "north": 39.21753
#>             },
#>             "scoring": {
#>                 "queryScore": 1.0,
#>                 "fieldScore": {
#>                     "streets": [
#>                         1.0
#>                     ],
#>                     "houseNumber": 1.0
#>                 }
#>             }
#>         }
#>     ]
#> }
#> 

Unfortunately the queryScore is not suitable to prioritize the alternatives, because all the query scores of the alternatives have the value 1.0. A binary option (e.g. alternatives = TRUE or FALSE) seems to be more useful than passing a maximum number of returned alternatives (e.g. results = 3). In the return value of geocode() each alternative gets the rank of the order from the API.

Session info
devtools::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#>  setting  value                       
#>  version  R version 4.0.2 (2020-06-22)
#>  os       macOS Catalina 10.15.7      
#>  system   x86_64, darwin17.0          
#>  ui       X11                         
#>  language (EN)                        
#>  collate  en_US.UTF-8                 
#>  ctype    en_US.UTF-8                 
#>  tz       Europe/Zurich               
#>  date     2020-11-06                  
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────
#>  package     * version date       lib source        
#>  assertthat    0.2.1   2019-03-21 [1] CRAN (R 4.0.0)
#>  backports     1.1.10  2020-09-15 [1] CRAN (R 4.0.2)
#>  callr         3.5.1   2020-10-13 [1] CRAN (R 4.0.2)
#>  class         7.3-17  2020-04-26 [1] CRAN (R 4.0.2)
#>  classInt      0.4-3   2020-04-07 [1] CRAN (R 4.0.0)
#>  cli           2.1.0   2020-10-12 [1] CRAN (R 4.0.2)
#>  crayon        1.3.4   2017-09-16 [1] CRAN (R 4.0.0)
#>  curl          4.3     2019-12-02 [1] CRAN (R 4.0.1)
#>  data.table    1.13.2  2020-10-19 [1] CRAN (R 4.0.2)
#>  DBI           1.1.0   2019-12-15 [1] CRAN (R 4.0.0)
#>  desc          1.2.0   2018-05-01 [1] CRAN (R 4.0.0)
#>  devtools      2.3.2   2020-09-18 [1] CRAN (R 4.0.2)
#>  digest        0.6.27  2020-10-24 [1] CRAN (R 4.0.2)
#>  dplyr         1.0.2   2020-08-18 [1] CRAN (R 4.0.2)
#>  e1071         1.7-4   2020-10-14 [1] CRAN (R 4.0.2)
#>  ellipsis      0.3.1   2020-05-15 [1] CRAN (R 4.0.0)
#>  evaluate      0.14    2019-05-28 [1] CRAN (R 4.0.0)
#>  fansi         0.4.1   2020-01-08 [1] CRAN (R 4.0.0)
#>  fs            1.5.0   2020-07-31 [1] CRAN (R 4.0.2)
#>  generics      0.0.2   2018-11-29 [1] CRAN (R 4.0.0)
#>  glue          1.4.2   2020-08-27 [1] CRAN (R 4.0.2)
#>  hereR       * 0.5.1   2020-10-20 [1] CRAN (R 4.0.2)
#>  htmltools     0.5.0   2020-06-16 [1] CRAN (R 4.0.2)
#>  jsonlite      1.7.1   2020-09-07 [1] CRAN (R 4.0.2)
#>  KernSmooth    2.23-17 2020-04-26 [1] CRAN (R 4.0.2)
#>  knitr         1.30    2020-09-22 [1] CRAN (R 4.0.2)
#>  lifecycle     0.2.0   2020-03-06 [1] CRAN (R 4.0.0)
#>  magrittr      1.5     2014-11-22 [1] CRAN (R 4.0.0)
#>  memoise       1.1.0   2017-04-21 [1] CRAN (R 4.0.0)
#>  pillar        1.4.6   2020-07-10 [1] CRAN (R 4.0.2)
#>  pkgbuild      1.1.0   2020-07-13 [1] CRAN (R 4.0.2)
#>  pkgconfig     2.0.3   2019-09-22 [1] CRAN (R 4.0.0)
#>  pkgload       1.1.0   2020-05-29 [1] CRAN (R 4.0.2)
#>  prettyunits   1.1.1   2020-01-24 [1] CRAN (R 4.0.0)
#>  processx      3.4.4   2020-09-03 [1] CRAN (R 4.0.2)
#>  ps            1.4.0   2020-10-07 [1] CRAN (R 4.0.2)
#>  purrr         0.3.4   2020-04-17 [1] CRAN (R 4.0.0)
#>  R6            2.4.1   2019-11-12 [1] CRAN (R 4.0.0)
#>  Rcpp          1.0.5   2020-07-06 [1] CRAN (R 4.0.2)
#>  remotes       2.2.0   2020-07-21 [1] CRAN (R 4.0.2)
#>  rlang         0.4.8   2020-10-08 [1] CRAN (R 4.0.2)
#>  rmarkdown     2.5     2020-10-21 [1] CRAN (R 4.0.2)
#>  rprojroot     1.3-2   2018-01-03 [1] CRAN (R 4.0.0)
#>  sessioninfo   1.1.1   2018-11-05 [1] CRAN (R 4.0.0)
#>  sf            0.9-6   2020-09-13 [1] CRAN (R 4.0.2)
#>  stringi       1.5.3   2020-09-09 [1] CRAN (R 4.0.2)
#>  stringr       1.4.0   2019-02-10 [1] CRAN (R 4.0.2)
#>  testthat      2.3.2   2020-03-02 [1] CRAN (R 4.0.2)
#>  tibble        3.0.4   2020-10-12 [1] CRAN (R 4.0.2)
#>  tidyselect    1.1.0   2020-05-11 [1] CRAN (R 4.0.0)
#>  units         0.6-7   2020-06-13 [1] CRAN (R 4.0.2)
#>  usethis       1.6.3   2020-09-17 [1] CRAN (R 4.0.2)
#>  vctrs         0.3.4   2020-08-29 [1] CRAN (R 4.0.2)
#>  withr         2.3.0   2020-09-22 [1] CRAN (R 4.0.2)
#>  xfun          0.18    2020-09-29 [1] CRAN (R 4.0.2)
#>  yaml          2.2.1   2020-02-01 [1] CRAN (R 4.0.0)
#> 
#> [1] /Library/Frameworks/R.framework/Versions/4.0/Resources/library

Bug: Error code 403, forbidden

I'm stuck here. After set_key, trying to get isoline with this

isoline(
  poi = far_upmc_points[1,],
  range = seq(10, 20, 10) * 60,
  range_type = "time",
  datetime <- as.POSIXct(paste0(Sys.Date()," 10:00")) 
) %>%
  mutate(name = paste0((range - 600) / 60," to ", range / 60, " mins"))

The far_upmc_points is look like this:

Simple feature collection with 3 features and 2 fields
Geometry type: POINT
Dimension:     XY
Bounding box:  xmin: -80.0983 ymin: 40.35162 xmax: -79.76028 ymax: 40.68328
CRS:           +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
# A tibble: 3 × 3
  Location           Address             geometry
* <chr>              <chr>            <POINT [°]>
1 UPMC East          2775 M… (-79.76028 40.43666)
2 UPMC McKeesport    1500 5… (-79.84907 40.35162)
3 UPMC Passavant - … 1 St. …  (-80.0983 40.68328)

Result

Error in UseMethod("mutate") : 
  no applicable method for 'mutate' applied to an object of class "NULL"
In addition: Warning message:
In .parse_response(i, out$responses()[[i]]) :
  https://isoline.router.hereapi.com/v8/isolines: Request 'id = 1' failed. 
  Status 403; Forbidden; Request forbidden -- authorization will not help.

I'm also try another request:
geocode(c("Schweighofstrasse 190, Zürich, Schweiz", "Hardstrasse 48, Zürich, Schweiz"))
which return the same error

Quality index

First, thank you for the work.
I was reading here (pun not intended) about the quality index of the matching process in the geocode:
https://developer.here.com/documentation/geocoder/dev_guide/topics/reading-geocoding-response.html
I believe that the package currently cannot have a quality index of the matching process in geocoding, such as relevance or match quality. If this is the case, could be possible that a future version of the package could have an option quality to include those outputs in the geocode function results?

Bug: HERE rate limits

Describe the bug
Unfortunately HERE introduced rate limits on freemium licenses:

Starting April 1st, 2021, we will be introducing rate limiting for our freemium licenses. This means that alongside the maximum 250k transactions limit per month the number of requests per second (RPS) is now limited.

This rate limiting only applies for Freemium License plans and does not apply to any paid commercial plans. To learn more about upgrading to a commercial plan, click here.

The limits are:

Service Max RPS
Geocoding & Search 5
Multi Reverse Geocoding 1
Vector Tile 10
Map Tile 30
Map Image 2
Routing 10
Matrix Routing 1
Isoline Routing 1
Route Matching 1
Advanced Datasets 10
Waypoints Sequence 1
Transit 10
Intermodal 5

For freemium licenses requests fail randomly with status code 429 on all API endpoints if they exceed the rate limit.

Reproducible example

library(hereR)
set_key("KEY")
locs <- geocode(address = rep(poi$city, 100), url_only = F)
#> There were 50 or more warnings (use warnings() to see the first 50)
warnings()
#> 1: In (function (res)  ... : Request 'id = 22' failed: Status 429. 
#> 2: In (function (res)  ... : Request 'id = 24' failed: Status 429. 
#> 3: In (function (res)  ... : Request 'id = 25' failed: Status 429. 
#> 4: In (function (res)  ... : Request 'id = 26' failed: Status 429. 
#> 5: In (function (res)  ... : Request 'id = 28' failed: Status 429. 

Expected behavior
Add sleep time if request code 429 is encountered and retry. Not sure if async requests are still the way to go... ?

geocode: optionally return DisplayPosition

geocode() currently returns the latitude/longitude values of the NavigationPosition.

A navigation position contains the coordinates of a potential route waypoint. It is used for routes that pass through the given location.

From https://developer.here.com/documentation/geocoder/dev_guide/topics/resource-type-response-geocode.html#resource-type-response-geocode__location

Depending on the use case, e.g. mapping, the alternative DisplayPosition may be better suited:

The display position contains the coordinates at which to place a marker indicating the given location on the map.

Would you consider optionally returning the DisplayPosition lat/lng pair? I have been bitten by this, namely that two or more distinct addresse have the same NavigationPosition (i.e. access from the road), but different DisplayPositions.

NavigationPosition and DisplayPosition are respectively called access and position in the v7 API (Navigate to Geocode > Responses > 200 > items).

upcoming sf breaks hereR on CRAN

See

Package hereR has one or more sf objects stored that use the old represenation of crs objects. This breaks downstream code (here: in mapview, through your vignettes). Please update these objects, or consider using dynamic construction with the sf api (using e.g. st_set_crs()), so you no longer get bitten by issues of this kind.

Feature: Update Routing API to v8

The Routing API v7 used in the {hereR} package is no longer actively developed. Newer versions of the APIs are available and the package should be updated to the:

New endpoints to use:

Note: The shapes are encoded in the flexible polyline encoding format and have to be decoded using the {flexpolyline} package. The pacakge is not yet supporting the geometry type "POLYGON", which has to be implemented first (see munterfi/flexpolyline#31).

Update authentication to API key

Here has updated the authentication process and changed from APP_ID and APP_CODE to a single API_KEY: https://developer.here.com/documentation/authentication/dev_guide/topics/api-key-credentials.html

This means the set_auth(), unset_auth(), .check_auth() and .add_auth() methods have to be adjusted.

Most important change will be add_auth(), probably:

.add_auth <- function(url) {
  api_key = Sys.getenv("HERE_API_KEY")
  .check_auth(api_key)
  paste0(
    url,
    "&api_key=",
    api_key)
}

Thanks for reporting: https://twitter.com/anders_elias/status/1208132508384137217

Bug: Status 401; Unauthorized; No permission

Describe the bug
here endpoint rejects API key

Unless I am wrong that the 'single-bearer credential' is the API key, authentication is consistently failing. If the API key is something other than here.access.key.id or here.access.key.secret, that's unclear in the example given. I've been unable to discover a third way of creating tokens on their developer website.

Reproducible example

# libraries
library(dplyr)
library(hereR)

# health facility
data <- read.csv("https://raw.githubusercontent.com/isaid-hi/bipi.datalab/main/2023.06.24_%234%20Hospital%20Access/hospitals.csv")

# hospital only
hospitals <- data %>% filter(Type %in% "Rumah Sakit")
hospital_sf <- st_as_sf(x = hospitals,
                        coords = c("Longitude", "Latitude"),
                        crs = "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0")

# get isoline ----
## here api setup ----
set_key("here.access.key.id") # either this or the longer here.access.key.secret

## build isoline ----
### isoline for hospitals ----
isochrones_all <- isoline(
  poi = hospital_sf,
  range = seq(10, 30, 10) * 60,
  range_type = "time",
  datetime <- as.POSIXct(paste0(Sys.Date()," 10:00")) 
) %>%
  mutate(name = paste0((range - 600) / 60," to ", range / 60, " mins"))

Expected behavior
Following `set_key("some_token") request silently authenticates and returns results

Optionally: R session info
Not relevant

Feature: Add a robust argument to hereR::isoline.

Sometimes hereR::isoline fails for specific cases in poi, causing an error. Consider adding a robust argument that allows the function to return values for the successful isolines and NAs for the unsuccessful ones. This argument would take a logical and default to FALSE.

I often find myself using this pattern:

library(dplyr)
library(hereR)
library(purrr)
library(tidyr)

# Failproof version of isoline (returns just the geometry for use in mutate).
safely_isoline <- function(...) {
  fxn <- safely(isoline)
  value <- fxn(...)
  if (is.null(value$error)) value$result$geometry else NA
}

# A sf object with points.
my_sf <- ... 

# Example usage: Replace some point geometries with isoline geometries.
my_sf %>%
  group_by(id) %>%           # Some unique identifier.
  nest(data = geometry) %>%  # A sfc with point geometries.
  mutate(geometry = map(data, safely_isoline)) %>%
  select(-data) %>% unnest(geometry) %>%
  ungroup()

The failing cases may deserve a bug report of their own. I haven't figured out the cause; all I know is that it seems to happen for specific cases when combined with specific function arguments. This issue is only concerned with moving past these failures.

Update to package required

Hi,

I've been receiving error 400 while trying to use your package. After digging around and asking Here's customer service, there seems to be an update required to the function's URL script piece.

image

This image is a response from their team. Was wondering if there is any quick way to push an update here 👍

geocode(): Toggle geographic columns returned

I've noticed that depending on the specificity of the address sent to hereR::geocode(), different columns are returned in the resulting sf/data frame object.

Here's a reproducible example (assuming you have the geocoding API set up):

# Make some sample data
vec <- c("boston, massachusetts", "massachusetts") # two localities, one of which can be geocoded down to the city/zip code level
vec2 <- "massachusetts" #locality that can only be geocoded down to the US state level

# Geocode each of these (I'm leaving sf = F just for simplicity of display of the output. We get the same behavior with sf = T).
vec_gc <- hereR::geocode(vec, sf = F)
vec2_gc <- hereR::geocode(vec2, sf = F)

# View the results
vec_gc
    id                 address                    postalCode   city       county state country  type       lng              lat
1  1 Boston, MA, United States      02109            Boston Suffolk  MA     USA      point      -71.05675 42.35866
2  2         MA, United States           <NA>             <NA>    <NA>   MA     USA      point      -71.05675 42.35866

vec2_gc
    id  address                     state  country  type       lng              lat
1  1   MA, United States    MA     USA        point      -71.05675 42.35866

Note that because vec2 could not be geocoded more precisely than a US state, additional columns (city, county, postalCode) don't show up.

I can understand why this behavior would be desired: it prevents the user from getting back a needlessly-large data frame with a huge number of NA values. But I'm trying to write an automated workflow where I'll be geocoding addresses at varying levels of specificity. I need to know ahead of time what columns will be present in my output data frame, so that I can write functions to operate on it without first checking whether the county/state/city columns exist.

Is there currently a way to toggle the inclusion of additional columns in geocode()? If not, would you consider adding this feature? Maybe an argument show_all_cols that defaults to FALSE, or something of that nature.

Bug: route_matrix() output order

Hi,

Thanks for the package! I encountered an issue while using route_matrix(). According to the documentation, the orig_id and dest_id are supposed to reflect the order of the provided POIs. However, when I tried to input multiple origins, the order seems to be off.

route_matrix(poi[1:2,]) generates a data frame of 4 route summaries. However, I found that the orig_id and dest_id are reverse. For instance, I suppose that with orig_id = 1 and dest_id = 2, the route should be from poi[1,] to poi[2,]. But by requesting the route one-by-one, route_matrix(poi[1,],poi[2,]) prints out the same route info as orig_id =2 and dest_id = 1 from the previous table. (Sorry for the mumbling, I hope I stated my issue clearly... )

Is there a reason why the order is reversed?
I appreciate any help in advance!

Feature: isolines custom id/retain attributes

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.

add query column to `geocode()` result?

Potential use case: When geocoding, I would like to bind a source data frame to the results sf object. I.e. in the following example I would like to have the company name in the sf object.

library(hereR)

x <- data.frame(
  company = c("Schweizerische Bundesbahnen SBB", "Deutsche Bahn AG"),
  address = c("Wylerstrasse 123, 3000 Bern 65", "Potsdamer Platz 2, 10785 Berlin"),
  stringsAsFactors = FALSE
)

geocode(x$address)
#> Simple feature collection with 2 features and 10 fields
#> geometry type:  POINT
#> dimension:      XY
#> bbox:           xmin: 7.44657 ymin: 46.96138 xmax: 13.37525 ymax: 52.51005
#> epsg (SRID):    4326
#> proj4string:    +proj=longlat +datum=WGS84 +no_defs
#>                                        address          street houseNumber
#> 1    Wylerstrasse 123, 3014 Bern Bern, Schweiz    Wylerstrasse         123
#> 2 Potsdamer Platz 2, 10785 Berlin, Deutschland Potsdamer Platz           2
#>   postalCode   district   city          county  state country  type
#> 1       3014      Wyler   Bern Bern-Mittelland     BE     CHE point
#> 2      10785 Tiergarten Berlin          Berlin Berlin     DEU point
#>                    geometry
#> 1  POINT (7.44657 46.96138)
#> 2 POINT (13.37525 52.51005)

However, I don’t have an identical column in both data frames with which I could merge both. How would I be able do that? (In this simple example it would be possible to rbind() both objects, but that rests on the (fragile) assumption that both objects have the same nrow()).

One possible solution would be to add the query vector as a column to the results object.

Geocoding and Search API v7

HERE launched a new Geocoding and Search API v7 (apparently already some time ago).

The Geocoder, Geocoder Autocomplete (and Places) APIs have been placed "in maintenance":

Note: This service is no longer being actively developed. We will only provide critical fixes for this service in future. Instead, use the new Geocoding and Search API v7 service.

From https://developer.here.com/documentation/geocoder/dev_guide/topics/what-is.html

I have not found out the EOL of the "old" APIs, so cannot say how urgent it is to act on this.

Apparently the response format also changed. Here are the geocoding results for "Schweighofstrasse 190, Zurich, Switzerland"

v6.2
{
  "Response": {
    "MetaInfo": {
      "Timestamp": "2020-08-18T14:34:00.522+0000"
    },
    "View": [
      {
        "_type": "SearchResultsViewType",
        "ViewId": 0,
        "Result": [
          {
            "Relevance": 1,
            "MatchLevel": "houseNumber",
            "MatchQuality": {
              "Country": 1,
              "City": 1,
              "Street": [
                1
              ],
              "HouseNumber": 1
            },
            "MatchType": "interpolated",
            "Location": {
              "LocationId": "NT_wqJFy0LBrbr0VLs1azqsVB_xkDM",
              "LocationType": "point",
              "DisplayPosition": {
                "Latitude": 47.3596988,
                "Longitude": 8.5075278
              },
              "NavigationPosition": [
                {
                  "Latitude": 47.35959,
                  "Longitude": 8.50741
                }
              ],
              "MapView": {
                "TopLeft": {
                  "Latitude": 47.3608229,
                  "Longitude": 8.5058683
                },
                "BottomRight": {
                  "Latitude": 47.3585746,
                  "Longitude": 8.5091873
                }
              },
              "Address": {
                "Label": "Schweighofstrasse 190, 8045 Zürich Zürich, Schweiz",
                "Country": "CHE",
                "State": "ZH",
                "County": "Zürich",
                "City": "Zürich",
                "District": "Kreis 3",
                "Street": "Schweighofstrasse",
                "HouseNumber": "190",
                "PostalCode": "8045",
                "AdditionalData": [
                  {
                    "value": "Schweiz",
                    "key": "CountryName"
                  },
                  {
                    "value": "Zürich",
                    "key": "StateName"
                  },
                  {
                    "value": "Zürich",
                    "key": "CountyName"
                  }
                ]
              }
            }
          }
        ]
      }
    ]
  }
}
v7
{
  "items": [
    {
      "title": "Schweighofstrasse 190, 8045 Zürich Zürich, Schweiz",
      "id": "here:af:streetsection:c9lD-AuiFGH7e4vmkB0XDB:EAIaAzE5MChk",
      "resultType": "houseNumber",
      "houseNumberType": "interpolated",
      "address": {
        "label": "Schweighofstrasse 190, 8045 Zürich Zürich, Schweiz",
        "countryCode": "CHE",
        "countryName": "Schweiz",
        "state": "Zürich",
        "county": "Zürich",
        "city": "Zürich",
        "district": "Kreis 3",
        "street": "Schweighofstrasse",
        "postalCode": "8045",
        "houseNumber": "190"
      },
      "position": {
        "lat": 47.35955,
        "lng": 8.50769
      },
      "access": [
        {
          "lat": 47.35948,
          "lng": 8.50752
        }
      ],
      "mapView": {
        "west": 8.50636,
        "south": 47.35865,
        "east": 8.50902,
        "north": 47.36045
      },
      "scoring": {
        "queryScore": 1,
        "fieldScore": {
          "country": 1,
          "city": 1,
          "streets": [
            1
          ],
          "houseNumber": 1
        }
      }
    }
  ]
}

Bug: `geocode` error, invalid string in json text

When I run geocode(), I get the following error:

Error: lexical error: invalid string in json text.
                                       new
                     (right here) ------^

Note that I'm using the development version of hereR, because my code depends on the fix implemented in #98. If there's a stable released version that I could reference, that would be great, but I think that fix is too new to have made it into a release.

The complete code to generate this error, with a minimal example, is:

remotes::install_github("munterfinger/hereR@develop")
library(hereR)

# Create minimal df to generate the error
errorDF <- structure(list(togeocode = c("edinburgh", "newtonville massachusetts", 
"latham new york", "ponte vedra beach florida", "shanadoah virginia"
), id = 1:5), row.names = c(NA, 5L), class = "data.frame")

hereR::geocode(errorDF$togeocode, sf = FALSE)

Error: lexical error: invalid string in json text.
                                       new
                     (right here) ------^

# There seems to be some problem with the place names. I thought the "new" might refer to "latham new york", so I tried a minimal example that omits the localities containing "new":
noErrorDF <- structure(list(togeocode = c("edinburgh", "ponte vedra beach florida", "shanadoah virginia"
), id = 1:3), row.names = c(NA, 3L), class = "data.frame")

geocode(noErrorDF$togeocode, sf = FALSE)

# this works fine, with no error

Note that I've geocoded these exact same localities before, about two weeks ago, with no error. Not sure if something has been changed in either hereR or the API itself that would cause problems with something related to a json file?

Bug: Timezone issue in 'connection()' and 'intermodal_route()'

Since the fix of the timezone issue in isoline() (see #85), there is now an incorrect shift in the arrival and departure time of connection() and intermodal_route(). This occurs due the change in .encode_datetime, which now encodes the timezone instead of converting to UTC before sending the request. The connection() and intermodal_route() functions still assume a timestamp in timezone UTC in the response from the API. So there occurs a shift in time:

library(sf)
#> Linking to GEOS 3.8.1, GDAL 3.2.0, PROJ 7.2.0
library(hereR)

# Timestamp with different timezone as my local CET
(datetime = as.POSIXct("2020-12-17 08:00:00", tz = "Europe/Moscow"))
#> [1] "2020-12-17 08:00:00 MSK"

connection(poi[1, ], poi[2, ], datetime = datetime)$departure[1]
#> [1] "2020-12-17 09:53:00 MSK"

intermodal_route(poi[1, ], poi[2, ], datetime = datetime)$departure[1]
#> [1] "2020-12-17 09:53:00 MSK"

The functions route(), route_matrix() and isoline() are handling the timestamps correctly (as they are not taking the timestamp from the the API response):

route(poi[1, ], poi[2, ], datetime = datetime)$departure[1]
#> [1] "2020-12-17 08:00:00 MSK"

route_matrix(poi[1, ], poi[2, ], datetime = datetime)$departure[1]
#> [1] "2020-12-17 08:00:00 MSK"

isoline(poi[1, ], datetime = datetime)$departure[1]
#> [1] "2020-12-17 08:00:00 MSK"

The .parse_datetime() helper function that causes the problem can not be replaced, as other functions (incident() and weather()) still use older API versions and receive UTC timestamps. Adding a .parse_datetime_tz() that also parses the timezone information would solve the problem.

Session info
devtools::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#>  setting  value                       
#>  version  R version 4.0.3 (2020-10-10)
#>  os       macOS Catalina 10.15.7      
#>  system   x86_64, darwin17.0          
#>  ui       X11                         
#>  language (EN)                        
#>  collate  en_US.UTF-8                 
#>  ctype    en_US.UTF-8                 
#>  tz       Europe/Zurich               
#>  date     2020-12-17                  
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────
#>  package      * version date       lib source        
#>  assertthat     0.2.1   2019-03-21 [1] CRAN (R 4.0.0)
#>  callr          3.5.1   2020-10-13 [1] CRAN (R 4.0.2)
#>  class          7.3-17  2020-04-26 [1] CRAN (R 4.0.3)
#>  classInt       0.4-3   2020-04-07 [1] CRAN (R 4.0.0)
#>  cli            2.2.0   2020-11-20 [1] CRAN (R 4.0.2)
#>  crayon         1.3.4   2017-09-16 [1] CRAN (R 4.0.0)
#>  curl           4.3     2019-12-02 [1] CRAN (R 4.0.1)
#>  data.table     1.13.2  2020-10-19 [1] CRAN (R 4.0.3)
#>  DBI            1.1.0   2019-12-15 [1] CRAN (R 4.0.2)
#>  desc           1.2.0   2018-05-01 [1] CRAN (R 4.0.0)
#>  devtools       2.3.2   2020-09-18 [1] CRAN (R 4.0.2)
#>  digest         0.6.27  2020-10-24 [1] CRAN (R 4.0.2)
#>  dplyr          1.0.2   2020-08-18 [1] CRAN (R 4.0.2)
#>  e1071          1.7-4   2020-10-14 [1] CRAN (R 4.0.2)
#>  ellipsis       0.3.1   2020-05-15 [1] CRAN (R 4.0.0)
#>  evaluate       0.14    2019-05-28 [1] CRAN (R 4.0.0)
#>  fansi          0.4.1   2020-01-08 [1] CRAN (R 4.0.0)
#>  flexpolyline   0.2.0   2020-12-09 [1] local         
#>  fs             1.5.0   2020-07-31 [1] CRAN (R 4.0.2)
#>  generics       0.1.0   2020-10-31 [1] CRAN (R 4.0.2)
#>  glue           1.4.2   2020-08-27 [1] CRAN (R 4.0.2)
#>  hereR        * 0.5.2   2020-11-26 [1] CRAN (R 4.0.3)
#>  htmltools      0.5.0   2020-06-16 [1] CRAN (R 4.0.2)
#>  jsonlite       1.7.1   2020-09-07 [1] CRAN (R 4.0.2)
#>  KernSmooth     2.23-18 2020-10-29 [1] CRAN (R 4.0.2)
#>  knitr          1.30    2020-09-22 [1] CRAN (R 4.0.2)
#>  lifecycle      0.2.0   2020-03-06 [1] CRAN (R 4.0.0)
#>  magrittr       2.0.1   2020-11-17 [1] CRAN (R 4.0.2)
#>  memoise        1.1.0   2017-04-21 [1] CRAN (R 4.0.0)
#>  pillar         1.4.7   2020-11-20 [1] CRAN (R 4.0.2)
#>  pkgbuild       1.1.0   2020-07-13 [1] CRAN (R 4.0.2)
#>  pkgconfig      2.0.3   2019-09-22 [1] CRAN (R 4.0.0)
#>  pkgload        1.1.0   2020-05-29 [1] CRAN (R 4.0.2)
#>  prettyunits    1.1.1   2020-01-24 [1] CRAN (R 4.0.0)
#>  processx       3.4.4   2020-09-03 [1] CRAN (R 4.0.2)
#>  ps             1.4.0   2020-10-07 [1] CRAN (R 4.0.2)
#>  purrr          0.3.4   2020-04-17 [1] CRAN (R 4.0.0)
#>  R6             2.5.0   2020-10-28 [1] CRAN (R 4.0.2)
#>  Rcpp           1.0.5   2020-07-06 [1] CRAN (R 4.0.2)
#>  remotes        2.2.0   2020-07-21 [1] CRAN (R 4.0.2)
#>  rlang          0.4.9   2020-11-26 [1] CRAN (R 4.0.3)
#>  rmarkdown      2.5     2020-10-21 [1] CRAN (R 4.0.2)
#>  rprojroot      2.0.2   2020-11-15 [1] CRAN (R 4.0.2)
#>  sessioninfo    1.1.1   2018-11-05 [1] CRAN (R 4.0.0)
#>  sf           * 0.9-6   2020-09-13 [1] CRAN (R 4.0.3)
#>  stringi        1.5.3   2020-09-09 [1] CRAN (R 4.0.2)
#>  stringr        1.4.0   2019-02-10 [1] CRAN (R 4.0.2)
#>  testthat       3.0.0   2020-10-31 [1] CRAN (R 4.0.2)
#>  tibble         3.0.4   2020-10-12 [1] CRAN (R 4.0.2)
#>  tidyselect     1.1.0   2020-05-11 [1] CRAN (R 4.0.0)
#>  units          0.6-7   2020-06-13 [1] CRAN (R 4.0.2)
#>  usethis        1.6.3   2020-09-17 [1] CRAN (R 4.0.2)
#>  vctrs          0.3.5   2020-11-17 [1] CRAN (R 4.0.2)
#>  withr          2.3.0   2020-09-22 [1] CRAN (R 4.0.2)
#>  xfun           0.19    2020-10-30 [1] CRAN (R 4.0.2)
#>  yaml           2.2.1   2020-02-01 [1] CRAN (R 4.0.0)
#> 
#> [1] /Library/Frameworks/R.framework/Versions/4.0/Resources/library

Feature: Request tolls

I see that it is possible to request tolls for routes in the API but it would be great to be able to do it with hereR.

Bug: Function hereR::isoline fails for a single-value range.

I expect hereR::isoline to accept integer vector of length 1 for range and to produce a sf object with a single polygon. Instead, I get an error:

library(hereR)
library(sf)

# Insert your own HERE API key.
set_key("my-key")

# Get a sf object with one point for NYC.
p <- c(-74.0060, 40.7128) %>% st_point() %>% st_sfc() %>% st_sf(crs = "wgs84")

# Get 5 min isolines with two breaks (succeeds).
isoline(p, range = c(0, 300))

# Get 5 min isolines with one break (fails).
isoline(p, range = 300)
## Error in st_sf(x, ..., agr = agr, sf_column_name = sf_column_name) : 
##   no simple features geometry column present

I may be misunderstanding the intended purpose. I appreciate any guidance or a fix.

`geocode()` returns results for Namibia for empty or `NA_character_` strings.

geocode() returns results for Namibia for empty or NA_character_ strings.

library(hereR)
geocode(c("Hamburg", NA_character_, "", "Bern"))
#> Simple feature collection with 4 features and 7 fields
#> geometry type:  POINT
#> dimension:      XY
#> bbox:           xmin: 7.44046 ymin: -22.57159 xmax: 17.09075 ymax: 53.55375
#> epsg (SRID):    4326
#> proj4string:    +proj=longlat +datum=WGS84 +no_defs
#>                address postalCode    city          county   state country
#> 1 Hamburg, Deutschland      20354 Hamburg         Hamburg Hamburg     DEU
#> 2              Namibia       <NA>    <NA>            <NA>    <NA>     NAM
#> 3              Namibia       <NA>    <NA>            <NA>    <NA>     NAM
#> 4    Bern, BE, Schweiz       3011    Bern Bern-Mittelland      BE     CHE
#>    type                   geometry
#> 1 point   POINT (9.99183 53.55375)
#> 2 point POINT (17.09075 -22.57159)
#> 3 point POINT (17.09075 -22.57159)
#> 4 point   POINT (7.44046 46.94843)

Feature: Add geocoding parameters

Description
I was checking the API reference guide and you can specify country, county, state, district, and house number. I think this would be a great addition to the library for better geocoding results.

'reverse_geocode()' should recognize and avoid empty geometries

Attempts to reverse_geocode() empty geometries should be recognized and trigger an error.

library(hereR)
library(sf)
#> Linking to GEOS 3.7.2, GDAL 2.4.2, PROJ 5.2.0

x <- data.frame(
  id = c(1, 2, 3),
  company = c("Schweizerische Bundesbahnen SBB", "Bahnhof AG", "Deutsche Bahn AG"),
  address = c("Wylerstrasse 123, 3000 Bern 65", "not_an_address", "Potsdamer Platz 2, 10785 Berlin"),
  stringsAsFactors = FALSE
)
locs <- geocode(x$address)
#> Address(es) 'not_an_address' not found.

(y <- st_as_sf(merge(x, locs, all.x = TRUE, by = "id")))
#> Simple feature collection with 3 features and 13 fields (with 1 geometry empty)
#> geometry type:  POINT
#> dimension:      XY
#> bbox:           xmin: 7.44657 ymin: 46.96138 xmax: 13.37525 ymax: 52.51005
#> epsg (SRID):    4326
#> proj4string:    +proj=longlat +datum=WGS84 +no_defs
#>   id                         company                       address.x
#> 1  1 Schweizerische Bundesbahnen SBB  Wylerstrasse 123, 3000 Bern 65
#> 2  2                      Bahnhof AG                  not_an_address
#> 3  3                Deutsche Bahn AG Potsdamer Platz 2, 10785 Berlin
#>                                      address.y          street houseNumber
#> 1    Wylerstrasse 123, 3014 Bern Bern, Schweiz    Wylerstrasse         123
#> 2                                         <NA>            <NA>        <NA>
#> 3 Potsdamer Platz 2, 10785 Berlin, Deutschland Potsdamer Platz           2
#>   postalCode   district   city          county  state country  type
#> 1       3014      Wyler   Bern Bern-Mittelland     BE     CHE point
#> 2       <NA>       <NA>   <NA>            <NA>   <NA>    <NA>  <NA>
#> 3      10785 Tiergarten Berlin          Berlin Berlin     DEU point
#>                    geometry
#> 1  POINT (7.44657 46.96138)
#> 2               POINT EMPTY
#> 3 POINT (13.37525 52.51005)

(z <- reverse_geocode(y))
#> Warning in (function (res) : Request failed: HTTP status code 400.
#> Simple feature collection with 2 features and 13 fields
#> geometry type:  POINT
#> dimension:      XY
#> bbox:           xmin: 7.44657 ymin: 46.96138 xmax: 13.37525 ymax: 52.51005
#> epsg (SRID):    4326
#> proj4string:    +proj=longlat +datum=WGS84 +no_defs
#>   id rank distance       level
#> 1  1    1        0 houseNumber
#> 2  2    1        0 houseNumber
#>                                          label country  state
#> 1    Wylerstrasse 123, 3014 Bern Bern, Schweiz     CHE     BE
#> 2 Potsdamer Platz 2, 10785 Berlin, Deutschland     DEU Berlin
#>            county   city   district          street houseNumber postalCode
#> 1 Bern-Mittelland   Bern      Wyler    Wylerstrasse         123       3014
#> 2          Berlin Berlin Tiergarten Potsdamer Platz           2      10785
#>                    geometry
#> 1  POINT (7.44657 46.96138)
#> 2 POINT (13.37525 52.51005)

This warning occurs because the NAs are sent as coordinates to the API:

#> Warning in (function (res) : Request failed: HTTP status code 400.

Empty geometries should therefore be avoided in the input of reverese_geocode() by checking the sf object via st_is_empty() and an error should be thrown if some are detected.

Session info
devtools::session_info()
#> ─ Session info ──────────────────────────────────────────────────────────
#>  setting  value                       
#>  version  R version 3.6.1 (2019-07-05)
#>  os       macOS Catalina 10.15.1      
#>  system   x86_64, darwin15.6.0        
#>  ui       X11                         
#>  language (EN)                        
#>  collate  de_CH.UTF-8                 
#>  ctype    de_CH.UTF-8                 
#>  tz       Europe/Zurich               
#>  date     2019-12-08                  
#> 
#> ─ Packages ──────────────────────────────────────────────────────────────
#>  package     * version    date       lib source        
#>  assertthat    0.2.1      2019-03-21 [1] CRAN (R 3.6.0)
#>  backports     1.1.5      2019-10-02 [1] CRAN (R 3.6.0)
#>  callr         3.3.2      2019-09-22 [1] CRAN (R 3.6.0)
#>  class         7.3-15     2019-01-01 [1] CRAN (R 3.6.1)
#>  classInt      0.4-2      2019-10-17 [1] CRAN (R 3.6.0)
#>  cli           1.1.0      2019-03-19 [1] CRAN (R 3.6.0)
#>  crayon        1.3.4      2017-09-16 [1] CRAN (R 3.6.0)
#>  curl          4.2        2019-09-24 [1] CRAN (R 3.6.0)
#>  data.table    1.12.6     2019-10-18 [1] CRAN (R 3.6.0)
#>  DBI           1.0.0      2018-05-02 [1] CRAN (R 3.6.0)
#>  desc          1.2.0      2018-05-01 [1] CRAN (R 3.6.0)
#>  devtools      2.2.1      2019-09-24 [1] CRAN (R 3.6.0)
#>  digest        0.6.22     2019-10-21 [1] CRAN (R 3.6.0)
#>  e1071         1.7-2      2019-06-05 [1] CRAN (R 3.6.0)
#>  ellipsis      0.3.0      2019-09-20 [1] CRAN (R 3.6.0)
#>  evaluate      0.14       2019-05-28 [1] CRAN (R 3.6.0)
#>  fs            1.3.1      2019-05-06 [1] CRAN (R 3.6.0)
#>  glue          1.3.1      2019-03-12 [1] CRAN (R 3.6.0)
#>  hereR       * 0.2.0.9000 2019-12-07 [1] local         
#>  htmltools     0.4.0      2019-10-04 [1] CRAN (R 3.6.0)
#>  jsonlite      1.6        2018-12-07 [1] CRAN (R 3.6.0)
#>  KernSmooth    2.23-16    2019-10-15 [1] CRAN (R 3.6.0)
#>  knitr         1.25       2019-09-18 [1] CRAN (R 3.6.0)
#>  magrittr      1.5        2014-11-22 [1] CRAN (R 3.6.0)
#>  memoise       1.1.0      2017-04-21 [1] CRAN (R 3.6.0)
#>  pkgbuild      1.0.6      2019-10-09 [1] CRAN (R 3.6.0)
#>  pkgload       1.0.2      2018-10-29 [1] CRAN (R 3.6.0)
#>  prettyunits   1.0.2      2015-07-13 [1] CRAN (R 3.6.0)
#>  processx      3.4.1      2019-07-18 [1] CRAN (R 3.6.0)
#>  ps            1.3.0      2018-12-21 [1] CRAN (R 3.6.0)
#>  R6            2.4.1      2019-11-12 [1] CRAN (R 3.6.0)
#>  Rcpp          1.0.3      2019-11-08 [1] CRAN (R 3.6.0)
#>  remotes       2.1.0      2019-06-24 [1] CRAN (R 3.6.0)
#>  rlang         0.4.1      2019-10-24 [1] CRAN (R 3.6.0)
#>  rmarkdown     1.16       2019-10-01 [1] CRAN (R 3.6.0)
#>  rprojroot     1.3-2      2018-01-03 [1] CRAN (R 3.6.0)
#>  sessioninfo   1.1.1      2018-11-05 [1] CRAN (R 3.6.0)
#>  sf          * 0.8-0      2019-09-17 [1] CRAN (R 3.6.0)
#>  stringi       1.4.3      2019-03-12 [1] CRAN (R 3.6.0)
#>  stringr       1.4.0      2019-02-10 [1] CRAN (R 3.6.0)
#>  testthat      2.2.1      2019-07-25 [1] CRAN (R 3.6.0)
#>  units         0.6-5      2019-10-08 [1] CRAN (R 3.6.0)
#>  usethis       1.5.1      2019-07-04 [1] CRAN (R 3.6.0)
#>  withr         2.1.2      2018-03-15 [1] CRAN (R 3.6.0)
#>  xfun          0.10       2019-10-01 [1] CRAN (R 3.6.0)
#>  yaml          2.2.0      2018-07-25 [1] CRAN (R 3.6.0)
#> 
#> [1] /Library/Frameworks/R.framework/Versions/3.6/Resources/library

Feature: Remove limits in case of paid plan

Inspired by mobilityinstitute@867f1d7:

  • New environment variable HERE_FREEMIUM and hereR::set_freemium(FALSE)
  • Deactivate rate limits in request in paid plans, deprecate hereR::set_rate_limits(FALSE)
  • Remove limits of matrix size in route_matrix in paid plans using .get_freemium()
  • Remove further restricitons?

Fix CRAN Package Check Warnings for Package

Fix the Warnings for:

Error message r-patched-solaris-x86 and r-release-osx-x86_64:

checking re-building of vignette outputs ... [37s/43s] WARNING
Error(s) in re-building vignettes:
  ...
--- re-building ‘authentication.Rmd’ using rmarkdown
Warning in engine$weave(file, quiet = quiet, encoding = enc) :
  Pandoc (>= 1.12.3) and/or pandoc-citeproc not available. Falling back to R Markdown v1.
--- finished re-building ‘authentication.Rmd’

--- re-building ‘geocoder.Rmd’ using rmarkdown
Warning in engine$weave(file, quiet = quiet, encoding = enc) :
  Pandoc (>= 1.12.3) and/or pandoc-citeproc not available. Falling back to R Markdown v1.
Quitting from lines 51-58 (geocoder.Rmd) 
Error: processing vignette 'geocoder.Rmd' failed with diagnostics:
cannot open the connection
--- failed re-building ‘geocoder.Rmd’

--- re-building ‘routing.Rmd’ using rmarkdown
Warning in engine$weave(file, quiet = quiet, encoding = enc) :
  Pandoc (>= 1.12.3) and/or pandoc-citeproc not available. Falling back to R Markdown v1.
Quitting from lines 40-48 (routing.Rmd) 
Error: processing vignette 'routing.Rmd' failed with diagnostics:
cannot open the connection
--- failed re-building ‘routing.Rmd’

--- re-building ‘traffic.Rmd’ using rmarkdown
Warning in engine$weave(file, quiet = quiet, encoding = enc) :
  Pandoc (>= 1.12.3) and/or pandoc-citeproc not available. Falling back to R Markdown v1.
Quitting from lines 44-52 (traffic.Rmd) 
Error: processing vignette 'traffic.Rmd' failed with diagnostics:
cannot open the connection
--- failed re-building ‘traffic.Rmd’

--- re-building ‘weather.Rmd’ using rmarkdown
Warning in engine$weave(file, quiet = quiet, encoding = enc) :
  Pandoc (>= 1.12.3) and/or pandoc-citeproc not available. Falling back to R Markdown v1.
Quitting from lines 52-59 (weather.Rmd) 
Error: processing vignette 'weather.Rmd' failed with diagnostics:
cannot open the connection
--- failed re-building ‘weather.Rmd’

SUMMARY: processing the following files failed:
  ‘geocoder.Rmd’ ‘routing.Rmd’ ‘traffic.Rmd’ ‘weather.Rmd’

Error: Vignette re-building failed.
Execution halted

Error message r-oldrel-osx-x86_64 :

checking re-building of vignette outputs ... [4s/4s] WARNING
Error in re-building vignettes:
  ...
Warning in engine$weave(file, quiet = quiet, encoding = enc) :
  Pandoc (>= 1.12.3) and/or pandoc-citeproc not available. Falling back to R Markdown v1.
Warning in engine$weave(file, quiet = quiet, encoding = enc) :
  Pandoc (>= 1.12.3) and/or pandoc-citeproc not available. Falling back to R Markdown v1.
Quitting from lines 51-58 (geocoder.Rmd) 
Error: processing vignette 'geocoder.Rmd' failed with diagnostics:
cannot open the connection
Execution halted

The solution could be adding to add the chunk option screenshot.force = FALSE,
see: rstudio/DT#395.

Bug: Request 'id = 1' failed: Status 400 when using Isoline

When trying to use isoline(), I get the error

Warning message:
In .parse_response(i, out$responses()[[i]]) :
Request 'id = 1' failed: Status 400.

My code is as follows

poi = st_as_sf(GEO, coords = c("LON", "LAT"), crs = 4326)
isolines = isoline(poi = poi,
range = seq(10, 10, 1)*1000, range_type = "distance",
transport_mode = "truck", routing_mode = "short", traffic = FALSE,
url_only = FALSE)

where GEO is a single-row dataframe with geocordinates of LON and LAT.

Bug: `flow` function return 403

Describe the bug
flow function return 403. the API Key have no problem because I tried using httr and it return 200.

Reproducible example

library(hereR)
set_key(here_api_key)
flow(aoi, min_jam_factor = 0)

# NULL
# Warning messages:
#   1: In .parse_response(i, out$responses()[[i]]) :
#   https://traffic.ls.hereapi.com/traffic/6.2/flow.json: Request 'id = 1' failed. 
# Status 403; Forbidden; Request forbidden -- authorization will not help.
# 2: In .parse_response(i, out$responses()[[i]]) :
#   https://traffic.ls.hereapi.com/traffic/6.2/flow.json: Request 'id = 2' failed. 
# Status 403; Forbidden; Request forbidden -- authorization will not help.

Contrasting to this one using httr

url <- "https://data.traffic.hereapi.com/v7/flow?in=circle:52.50811,13.47853;r=2000&locationReferencing=olr&apiKey="
complete_url <- paste0(url, here_api_key)
response <- GET(complete_url)

# Response [https://data.traffic.hereapi.com/v7/flow?in=circle:52.50811,13.47853;r=2000&locationReferencing=olr&apiKey={here_api_key}]
# Date: 2023-07-08 15:18
# Status: 200
# Content-Type: application/json
# Size: 49.3 kB

Expected behavior
This clearly not API key as expected in #157 issue

Thanks for reporting, the issue you're experiencing is likely caused by an invalid API key.

Go to the projects view on HERE developer. Then create a new project and select REST. There you should be able to create an API key using the button “Create API key”. Copy paste the key and set it using set_key(...). Or alternatively export it to the environment export HERE_API_KEY=<YOUR-VALID-KEY-HERE>.

Additionally
I'm not sure, but is this package using flow API v6? In that case, this might be because its on maintenance

Adjust .get_content() to handle failing requests

If a requests fails, then this entry is deleted from the API result list. This means that the order of the output is not correct, which disables joining the output to the input based on the "id" column.

The following code has to be adjusted:

.get_content <- function(url, encoding = "UTF-8") {
...
      if (res$status != 200) {
        warning(sprintf("Request failed: HTTP status code %s.", res$status))
        ids <<- ids[ids != id]
...
}

The output of .get_content() has to be of the same length as the input URLs. The list entry of a failing request has to exist, but can be empty.

route_matrix() does not accept all row dimensions as input

The function route_matrix() does not accept entries for origin and destination with a number of rows that are divisible by the maximum permitted dimensions (M:N = 15:100) of the HERE Traffic API’s route matrix end point.

Construct a dummy data set and test:

library(sf)
#> Linking to GEOS 3.7.2, GDAL 2.4.2, PROJ 5.2.0
n <- 15*2
l <- n*n
sf <- 
  data.frame(
    idx = seq(1, n),
    lng = runif(n, 7.5, 8.5),
    lat = runif(n, 47.25, 47.75)
  ) %>% 
  st_as_sf(coords = c("lng", "lat")) %>% 
  st_set_crs(4326)

route_matrix(sf)
#> Error in seq.default(0 + i, length(origin_batch) - 1 + i, 1): wrong sign in 'by' argument
Session info
devtools::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#>  setting  value                       
#>  version  R version 3.6.2 (2019-12-12)
#>  os       macOS Catalina 10.15.2      
#>  system   x86_64, darwin15.6.0        
#>  ui       X11                         
#>  language (EN)                        
#>  collate  de_CH.UTF-8                 
#>  ctype    de_CH.UTF-8                 
#>  tz       Europe/Zurich               
#>  date     2020-01-18                  
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────
#>  package     * version date       lib source        
#>  assertthat    0.2.1   2019-03-21 [1] CRAN (R 3.6.0)
#>  backports     1.1.5   2019-10-02 [1] CRAN (R 3.6.0)
#>  callr         3.4.0   2019-12-09 [1] CRAN (R 3.6.0)
#>  class         7.3-15  2019-01-01 [1] CRAN (R 3.6.2)
#>  classInt      0.4-2   2019-10-17 [1] CRAN (R 3.6.0)
#>  cli           2.0.0   2019-12-09 [1] CRAN (R 3.6.0)
#>  crayon        1.3.4   2017-09-16 [1] CRAN (R 3.6.0)
#>  DBI           1.1.0   2019-12-15 [1] CRAN (R 3.6.0)
#>  desc          1.2.0   2018-05-01 [1] CRAN (R 3.6.0)
#>  devtools      2.2.1   2019-09-24 [1] CRAN (R 3.6.0)
#>  digest        0.6.23  2019-11-23 [1] CRAN (R 3.6.0)
#>  e1071         1.7-3   2019-11-26 [1] CRAN (R 3.6.0)
#>  ellipsis      0.3.0   2019-09-20 [1] CRAN (R 3.6.0)
#>  evaluate      0.14    2019-05-28 [1] CRAN (R 3.6.0)
#>  fansi         0.4.0   2018-10-05 [1] CRAN (R 3.6.0)
#>  fs            1.3.1   2019-05-06 [1] CRAN (R 3.6.0)
#>  glue          1.3.1   2019-03-12 [1] CRAN (R 3.6.0)
#>  hereR       * 0.3.0   2020-01-07 [1] CRAN (R 3.6.0)
#>  htmltools     0.4.0   2019-10-04 [1] CRAN (R 3.6.0)
#>  KernSmooth    2.23-16 2019-10-15 [1] CRAN (R 3.6.2)
#>  knitr         1.26    2019-11-12 [1] CRAN (R 3.6.0)
#>  magrittr      1.5     2014-11-22 [1] CRAN (R 3.6.0)
#>  memoise       1.1.0   2017-04-21 [1] CRAN (R 3.6.0)
#>  pkgbuild      1.0.6   2019-10-09 [1] CRAN (R 3.6.0)
#>  pkgload       1.0.2   2018-10-29 [1] CRAN (R 3.6.0)
#>  prettyunits   1.0.2   2015-07-13 [1] CRAN (R 3.6.0)
#>  processx      3.4.1   2019-07-18 [1] CRAN (R 3.6.0)
#>  ps            1.3.0   2018-12-21 [1] CRAN (R 3.6.0)
#>  R6            2.4.1   2019-11-12 [1] CRAN (R 3.6.0)
#>  Rcpp          1.0.3   2019-11-08 [1] CRAN (R 3.6.0)
#>  remotes       2.1.0   2019-06-24 [1] CRAN (R 3.6.0)
#>  rlang         0.4.2   2019-11-23 [1] CRAN (R 3.6.0)
#>  rmarkdown     2.0     2019-12-12 [1] CRAN (R 3.6.0)
#>  rprojroot     1.3-2   2018-01-03 [1] CRAN (R 3.6.0)
#>  sessioninfo   1.1.1   2018-11-05 [1] CRAN (R 3.6.0)
#>  sf          * 0.8-0   2019-09-17 [1] CRAN (R 3.6.0)
#>  stringi       1.4.3   2019-03-12 [1] CRAN (R 3.6.0)
#>  stringr       1.4.0   2019-02-10 [1] CRAN (R 3.6.0)
#>  testthat      2.3.1   2019-12-01 [1] CRAN (R 3.6.0)
#>  units         0.6-5   2019-10-08 [1] CRAN (R 3.6.0)
#>  usethis       1.5.1   2019-07-04 [1] CRAN (R 3.6.0)
#>  withr         2.1.2   2018-03-15 [1] CRAN (R 3.6.0)
#>  xfun          0.11    2019-11-12 [1] CRAN (R 3.6.0)
#>  yaml          2.2.0   2018-07-25 [1] CRAN (R 3.6.0)
#> 
#> [1] /Library/Frameworks/R.framework/Versions/3.6/Resources/library

Missing combinations in route_matrix()

Route combinations are missing in the matrix returned by route_matrix() from the HERE Routing API. This is the case if the maximum size of 100 in the dimension N is exceeded in M:N and 1:N input combinations.

Construct a dummy data set:

library(sf)
#> Linking to GEOS 3.7.2, GDAL 2.4.2, PROJ 5.2.0
n <- 200
l <- n*n
(sf <- 
  data.frame(
    idx = seq(1, n),
    lng = runif(n, 7.5, 8.5),
    lat = runif(n, 47.25, 47.75)
  ) %>% 
  st_as_sf(coords = c("lng", "lat")) %>% 
  st_set_crs(4326))
#> Simple feature collection with 200 features and 1 field
#> geometry type:  POINT
#> dimension:      XY
#> bbox:           xmin: 7.501636 ymin: 47.25102 xmax: 8.499705 ymax: 47.74729
#> epsg (SRID):    4326
#> proj4string:    +proj=longlat +datum=WGS84 +no_defs
#> First 10 features:
#>    idx                  geometry
#> 1    1 POINT (8.437796 47.32556)
#> 2    2 POINT (7.952149 47.64342)
#> 3    3 POINT (8.113918 47.30319)
#> 4    4 POINT (8.164873 47.36452)
#> 5    5 POINT (7.948922 47.44872)
#> 6    6 POINT (7.840909 47.56165)
#> 7    7 POINT (7.556707 47.68344)
#> 8    8 POINT (7.966527 47.36275)
#> 9    9 POINT (8.462874 47.35851)
#> 10  10 POINT (7.833083 47.44759)

Functions for testing inputs, requests and return values:

n_request <- function(x, y = NULL) {
  message(
    sprintf(
      "Number of requests: %s",
      ifelse(
        is.null(y),
        length(route_matrix(x, url_only = TRUE)),
        length(route_matrix(x, y, url_only = TRUE))
      )
    )
  )
}

test_one_input <- function(x) {
  message("* Only origin *")
  n_request(x)
  el <- route_matrix(x)
  message(sprintf(
    "Orig rows: %s, edgelist rows: %s \nInput combinations: %s, ouput combinations: %s",
     nrow(x), nrow(x)*nrow(x), nrow(el),
    length(unique(paste0(el$origIndex, "_", el$destIndex)))))
  return(el)
}

test_two_inputs <- function(x, y) {
  message("* Origin and destination*")
  n_request(x, y)
  el <- route_matrix(x, y)
  message(sprintf(
    "Orig rows: %s, dest rows: %s, edgelist rows: %s \ninput combinations: %s, Ouput combinations: %s",
    nrow(x), nrow(y), nrow(el), nrow(x)*nrow(y),
    length(unique(paste0(el$origIndex, "_", el$destIndex)))))
  return(el)
}

Calculate all input variants in route_matrix() and compare the number of combinations in the inputs with the combinations in the returned edge lists.

  • M - Only origin
el1 <- test_one_input(sf)
#> * Only origin *
#> Number of requests: 14
#> Orig rows: 200, edgelist rows: 40000 
#> Input combinations: 20000, ouput combinations: 20000
  • M:N - Origin and destination of same length
el2 <- test_two_inputs(sf[1:(n/2), ], sf[(n/2 + 1):n, ])
#> * Origin and destination*
#> Number of requests: 7
#> Orig rows: 100, dest rows: 100, edgelist rows: 10000 
#> input combinations: 10000, Ouput combinations: 10000
  • M:N - Origin and destination of different length
el3 <- test_two_inputs(sf[(n/3 + 1):n, ], sf[1:(n/2), ])
#> * Origin and destination*
#> Number of requests: 7
#> Orig rows: 133, dest rows: 100, edgelist rows: 10000 
#> input combinations: 13300, Ouput combinations: 10000
el4 <- test_two_inputs(sf[1:(n/2), ], sf[(n/3 + 1):n, ])
#> * Origin and destination*
#> Number of requests: 7
#> Orig rows: 100, dest rows: 133, edgelist rows: 10000 
#> input combinations: 13300, Ouput combinations: 10000
  • M:1 - Origin and destination
el6 <- test_two_inputs(sf[1:(n - 1), ], sf[n, ])
#> * Origin and destination*
#> Number of requests: 1
#> Orig rows: 199, dest rows: 1, edgelist rows: 100 
#> input combinations: 199, Ouput combinations: 100
  • 1:N - Origin and destination
el5 <- test_two_inputs(sf[1, ], sf[2:n, ])
#> * Origin and destination*
#> Number of requests: 1
#> Orig rows: 1, dest rows: 199, edgelist rows: 100 
#> input combinations: 199, Ouput combinations: 100
Session info
devtools::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#>  setting  value                       
#>  version  R version 3.6.2 (2019-12-12)
#>  os       macOS Catalina 10.15.2      
#>  system   x86_64, darwin15.6.0        
#>  ui       X11                         
#>  language (EN)                        
#>  collate  de_CH.UTF-8                 
#>  ctype    de_CH.UTF-8                 
#>  tz       Europe/Zurich               
#>  date     2020-01-18                  
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────
#>  package     * version date       lib source        
#>  assertthat    0.2.1   2019-03-21 [1] CRAN (R 3.6.0)
#>  backports     1.1.5   2019-10-02 [1] CRAN (R 3.6.0)
#>  callr         3.4.0   2019-12-09 [1] CRAN (R 3.6.0)
#>  class         7.3-15  2019-01-01 [1] CRAN (R 3.6.2)
#>  classInt      0.4-2   2019-10-17 [1] CRAN (R 3.6.0)
#>  cli           2.0.0   2019-12-09 [1] CRAN (R 3.6.0)
#>  crayon        1.3.4   2017-09-16 [1] CRAN (R 3.6.0)
#>  curl          4.3     2019-12-02 [1] CRAN (R 3.6.0)
#>  data.table    1.12.8  2019-12-09 [1] CRAN (R 3.6.0)
#>  DBI           1.1.0   2019-12-15 [1] CRAN (R 3.6.0)
#>  desc          1.2.0   2018-05-01 [1] CRAN (R 3.6.0)
#>  devtools      2.2.1   2019-09-24 [1] CRAN (R 3.6.0)
#>  digest        0.6.23  2019-11-23 [1] CRAN (R 3.6.0)
#>  e1071         1.7-3   2019-11-26 [1] CRAN (R 3.6.0)
#>  ellipsis      0.3.0   2019-09-20 [1] CRAN (R 3.6.0)
#>  evaluate      0.14    2019-05-28 [1] CRAN (R 3.6.0)
#>  fansi         0.4.0   2018-10-05 [1] CRAN (R 3.6.0)
#>  fs            1.3.1   2019-05-06 [1] CRAN (R 3.6.0)
#>  glue          1.3.1   2019-03-12 [1] CRAN (R 3.6.0)
#>  hereR       * 0.3.0   2020-01-07 [1] CRAN (R 3.6.0)
#>  htmltools     0.4.0   2019-10-04 [1] CRAN (R 3.6.0)
#>  jsonlite      1.6     2018-12-07 [1] CRAN (R 3.6.0)
#>  KernSmooth    2.23-16 2019-10-15 [1] CRAN (R 3.6.2)
#>  knitr         1.26    2019-11-12 [1] CRAN (R 3.6.0)
#>  magrittr      1.5     2014-11-22 [1] CRAN (R 3.6.0)
#>  memoise       1.1.0   2017-04-21 [1] CRAN (R 3.6.0)
#>  pkgbuild      1.0.6   2019-10-09 [1] CRAN (R 3.6.0)
#>  pkgload       1.0.2   2018-10-29 [1] CRAN (R 3.6.0)
#>  prettyunits   1.0.2   2015-07-13 [1] CRAN (R 3.6.0)
#>  processx      3.4.1   2019-07-18 [1] CRAN (R 3.6.0)
#>  ps            1.3.0   2018-12-21 [1] CRAN (R 3.6.0)
#>  R6            2.4.1   2019-11-12 [1] CRAN (R 3.6.0)
#>  Rcpp          1.0.3   2019-11-08 [1] CRAN (R 3.6.0)
#>  remotes       2.1.0   2019-06-24 [1] CRAN (R 3.6.0)
#>  rlang         0.4.2   2019-11-23 [1] CRAN (R 3.6.0)
#>  rmarkdown     2.0     2019-12-12 [1] CRAN (R 3.6.0)
#>  rprojroot     1.3-2   2018-01-03 [1] CRAN (R 3.6.0)
#>  sessioninfo   1.1.1   2018-11-05 [1] CRAN (R 3.6.0)
#>  sf          * 0.8-0   2019-09-17 [1] CRAN (R 3.6.0)
#>  stringi       1.4.3   2019-03-12 [1] CRAN (R 3.6.0)
#>  stringr       1.4.0   2019-02-10 [1] CRAN (R 3.6.0)
#>  testthat      2.3.1   2019-12-01 [1] CRAN (R 3.6.0)
#>  units         0.6-5   2019-10-08 [1] CRAN (R 3.6.0)
#>  usethis       1.5.1   2019-07-04 [1] CRAN (R 3.6.0)
#>  withr         2.1.2   2018-03-15 [1] CRAN (R 3.6.0)
#>  xfun          0.11    2019-11-12 [1] CRAN (R 3.6.0)
#>  yaml          2.2.0   2018-07-25 [1] CRAN (R 3.6.0)
#> 
#> [1] /Library/Frameworks/R.framework/Versions/3.6/Resources/library

Bug: NOTE, Objects in \usage without \alias

Version: 0.9.1 
Check: Rd \usage sections 
Result: NOTE 
    Objects in \usage without \alias in documentation object ‘autocomplete-defunct’:
     ‘autocomplete’
    
    Objects in \usage without \alias in documentation object ‘set_auth-defunct’:
     ‘set_auth’
    
    Objects in \usage without \alias in documentation object ‘set_proxy-defunct’:
     ‘set_proxy’
    
    Objects in \usage without \alias in documentation object ‘traffic-defunct’:
     ‘traffic’
    
    Functions with \usage entries need to have the appropriate \alias
    entries, and all their arguments documented.
    The \usage entries must correspond to syntactically valid R code.
    See chapter ‘Writing R documentation files’ in the ‘Writing R
    Extensions’ manual. 
Flavors: [r-devel-linux-x86_64-debian-clang](https://www.r-project.org/nosvn/R.check/r-devel-linux-x86_64-debian-clang/hereR-00check.html), [r-devel-linux-x86_64-debian-gcc](https://www.r-project.org/nosvn/R.check/r-devel-linux-x86_64-debian-gcc/hereR-00check.html), [r-devel-linux-x86_64-fedora-clang](https://www.r-project.org/nosvn/R.check/r-devel-linux-x86_64-fedora-clang/hereR-00check.html), [r-devel-linux-x86_64-fedora-gcc](https://www.r-project.org/nosvn/R.check/r-devel-linux-x86_64-fedora-gcc/hereR-00check.html), [r-devel-windows-x86_64](https://www.r-project.org/nosvn/R.check/r-devel-windows-x86_64/hereR-00check.html)

Return an empty instead of a NULL response when geocoding?

With respect to #8 and #9, I am wondering, whether it would be better to return an empty response (i.e. NA) instead of no response (NULL), when no data is found by the geocode API. I.e. the following ought to have a row for “not_an_address” IMHO (and the same for "" and NA_character_).

library(hereR)
geocode(c("Hamburg", "not_an_address"))
#> Address 'not_an_address' not found.
#> Simple feature collection with 1 feature and 7 fields
#> geometry type:  POINT
#> dimension:      XY
#> bbox:           xmin: 9.99183 ymin: 53.55375 xmax: 9.99183 ymax: 53.55375
#> epsg (SRID):    4326
#> proj4string:    +proj=longlat +datum=WGS84 +no_defs
#>                address postalCode    city  county   state country  type
#> 1 Hamburg, Deutschland      20354 Hamburg Hamburg Hamburg     DEU point
#>                   geometry
#> 1 POINT (9.99183 53.55375)

Feature: Avoid features in routing

The HERE Routing API offers the possibility to avoid features and areas in requested routes:

  • &avoid[areas]=bbox:13.082,52.416,13.628,52.626
  • &avoid[features]=tollRoad

Avoidance of areas and features should also be an option in the route function of the hereR package, e.g.:

  • route(…, avoid_feature = c("tollRoad", "...")).
  • route(…, avoid_area = sf_bbox)
  • route(…, avoid_area = sf_polygon)

Timezone conversion is useless...? Here converts the time from REST API to local time

Hi, I have done some testing and some reading and it seems to me that the current approach with .encode_datetime is doing more harm than good. According to the Here API documentation (perhaps this is a new behaviour... and previously it worked in UTC???) :

departureTime specifies the time of departure as defined by either date-time or full-date T partial-time in RFC 3339, section 5.6 (for example, 2019-06-24T01:23:45). The requested time is converted to the local time at origin. When the optional timezone offset is not specified, time is assumed to be local. If neither departureTime or arrivalTime are specified, current time at departure location will be used. All Time values in the response are returned in the timezone of each location.

So when the iso and routing functions convert the time to UTC for sending to the Here REST API, they are simply passing something like 2020-09-17T15:00:00. Here sees no Z and no optional timezone offset. It then thinks that this is local time. So it returns the iso or the route for the incorrect time.

To check that, try your own API key and run:

library(sf)
library(hereR)
# hereR::set_key("YOURKEY")

point <- st_sf(st_sfc(st_point(c(37.52523, 55.64005)), crs = 4326))

area_18 <- isoline(poi = point,
        datetime = as.POSIXct("2020-09-17 18:00:00", tz = "Europe/Moscow"),
        arrival = F,
        range = 1800,
        range_type = "time",
        type = "fastest",
        mode = "car",
        traffic = T,
        aggregate = F) %>% st_area()

area_21 <- isoline(poi = point,
        datetime = as.POSIXct("2020-09-17 21:00:00", tz = "Europe/Moscow"),
        arrival = F,
        range = 1800,
        range_type = "time",
        type = "fastest",
        mode = "car",
        traffic = T,
        aggregate = F) %>% st_area()

area_no_traffic <- isoline(poi = point,
        arrival = F,
        range = 1800,
        range_type = "time",
        type = "fastest",
        mode = "car",
        traffic = F,
        aggregate = F) %>% st_area()

area_18/area_21
area_21/area_no_traffic
area_18/area_no_traffic

You will get:

> area_18/area_21
1.258702 [1]
> area_21/area_no_traffic
0.3900247 [1]
> area_18/area_no_traffic
0.4909249 [1]

This basically means that an isochrone for 18:00 in Moscow during the heaviest traffic time is 25% larger than at 21:00, which is highly unlikely. I think that supports my argument converting the time to UTC is undesirable and currently leads to incorrect results for all functions (isochrones, routing...).

If you agree with me, I can find some time in the next week or so to try and update the code as necessary and submit a pull request. The two possible solutions, I guess, are:

  • remove the .encode_datetime altogether
  • rewrite the .encode_datetime to format the date for the URL with the offset according to the RFC 3339, that is instead of converting "2020-09-17 18:00:00", tz = "Europe/Moscow" to "2020-09-17T15:00:00" (so now it is in UTC), convert it to "2020-09-17T15:00:00-03:00", so that Here knows that we need the offset time (I guess this will yield the same results as the first option, but is probably more reliable in the long run).

Request 'id = 1' failed: Status 400.

Hi!

I'm using reverse_geocode() to bring back address from coordinates. But when I'm using the same script and API key on another computer I get the Request 'id = 1' failed: Status 400.

Update: I tried to install an older version (0.4.1) and works fine. I guess something related to API URL.

Bug: hereR::isoline fails: "Error in decode(encoded[[x]]): Invalid format version"

For specific parameter combinations, hereR::isoline fails. In these cases, I would expect the function to either (1) return a polygon or (2) throw an error that makes my mistake more obvious.

This bug was the motivation to propose workaround #118 . As noted there, it probably makes sense to close that issue and just address the bug directly here.

Below I induce an error by playing with range.

library(hereR)
library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1

# A test point.
point <- 
  c(-73.51263, 44.20958) %>% 
  st_point() %>% st_sfc() %>% st_sf(crs = "WGS84")

# Range 1800 (30 min) succeeds.
isoline(point, range = 1800)
#> Simple feature collection with 1 feature and 5 fields
#> geometry type:  POLYGON
#> dimension:      XY
#> bbox:           xmin: -73.88306 ymin: 43.82996 xmax: -73.31863 ymax: 44.64157
#> geographic CRS: WGS 84
#>   id rank           departure             arrival range
#> 1 NA    1 2021-05-12 16:07:03 2021-05-12 16:37:03  1800
#>                         geometry
#> 1 POLYGON ((-73.87688 44.2309...

# Range 3600 (60 min) fails.
isoline(point, range = 3600)
#> Error in decode(encoded[[x]]): Invalid format version

Created on 2021-05-12 by the reprex package (v2.0.0)

lwgeom no longer exports st_make_valid

... but sf does. This will break hereR with e.g.

  > test_check("hereR")
  ── 1. Error: isoline works  ────────────────────────────────────────────────────
  'st_make_valid' is not an exported object from 'namespace:lwgeom'
  Backtrace:
   1. hereR::isoline(poi = poi, aggregate = TRUE)
   2. lwgeom::st_make_valid
   3. base::getExportedValue(pkg, name)

Please fix and resubmit to CRAN to avoid errors in CRAN checks.

Error with Geocode

Hello,
System : Windows 10, R 3.6

I just took the exemple :
geocode(c("Schweighofstrasse 190, Zürich, Schweiz", "Hardstrasse 48, Zürich, Schweiz"))
and I got this error :
NULL
Warning messages:
1: In (function (res) : Request 'id = 1' failed: Status 401.
2: In (function (res) : Request 'id = 2' failed: Status 401.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.