rgeospatialhere-api

here.com isoline routing using R - df as result?


This is related to here.com and the developer side on a freemium account.

Problem: Is creating an empty dataframe or only ID instead of giving me a full data table with a polygon each row based in the isoline routing based in time.

Below piece could please guide anyone into a way to solve this? Code obtained through this example

  1. My input centroids as df + my funcion
  2. Bad result, but one by one it works perfectly
set_key(api_key = "12345") # not it
df <- structure(list(address = c("853, Boul. Albiny-Paquette", "790 Boul. Wilfrid-Lavigne", 
"495 Vanier", "209, Chemin Aylmer", "585 Boul. Des Grives", "265 Boul. Saint-Raymond", 
"725 Boul. Des Hautes-Plaines", "9 Rue Daniel-Johnson", "480 Boul. St-Joseph", 
"15 Rue Eddy"), city = c("Mont-Laurier", "Gatineau", "Gatineau", 
"Gatineau", "Gatineau", "Gatineau", "Gatineau", "Gatineau", "Gatineau", 
"Gatineau"), state = c("QC", "QC", "QC", "QC", "QC", "QC", "QC", 
"QC", "QC", "QC"), zip_code = c("J9L 1L6", "J9J 2S5", "J9J 1Z4", 
"J9H 1A3", "J9A 3W9", "J9A 3G6", "J8Z 2W9", "J8Z 1X6", "J8Y 3Y7", 
"J8X 4B3"), county = c("Antoine-Labelle", "Communauté-Urbaine-de-l'Outaouais", 
"Communauté-Urbaine-de-l'Outaouais", "Communauté-Urbaine-de-l'Outaouais", 
"Communauté-Urbaine-de-l'Outaouais", "Communauté-Urbaine-de-l'Outaouais", 
"Communauté-Urbaine-de-l'Outaouais", "Communauté-Urbaine-de-l'Outaouais", 
"Communauté-Urbaine-de-l'Outaouais", "Communauté-Urbaine-de-l'Outaouais"
), country = c("Canada", "Canada", "Canada", "Canada", "Canada", 
"Canada", "Canada", "Canada", "Canada", "Canada"), geometry = structure(list(
    structure(c(-75.4880697, 46.5512158), class = c("XY", "POINT", 
    "sfg")), structure(c(-75.8386017, 45.4110993), class = c("XY", 
    "POINT", "sfg")), structure(c(-75.8070987999999, 45.4161897
    ), class = c("XY", "POINT", "sfg")), structure(c(-75.8322898, 
    45.3959535), class = c("XY", "POINT", "sfg")), structure(c(-75.7859960999999, 
    45.4435358), class = c("XY", "POINT", "sfg")), structure(c(-75.7611743, 
    45.4269774), class = c("XY", "POINT", "sfg")), structure(c(-75.7719339, 
    45.474538), class = c("XY", "POINT", "sfg")), structure(c(-75.7475764, 
    45.4625748), class = c("XY", "POINT", "sfg")), structure(c(-75.7323619, 
    45.4464210999999), class = c("XY", "POINT", "sfg")), structure(c(-75.7202519, 
    45.4251762), class = c("XY", "POINT", "sfg"))), class = c("sfc_POINT", 
"sfc"), precision = 0, bbox = structure(c(xmin = -75.8386017, 
ymin = 45.3959535, xmax = -75.4880697, ymax = 46.5512158), class = "bbox"), crs = structure(list(
    input = "WGS84", wkt = "GEOGCRS[\"WGS 84\",\n    DATUM[\"World Geodetic System 1984\",\n        ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n            LENGTHUNIT[\"metre\",1]]],\n    PRIMEM[\"Greenwich\",0,\n        ANGLEUNIT[\"degree\",0.0174532925199433]],\n    CS[ellipsoidal,2],\n        AXIS[\"geodetic latitude (Lat)\",north,\n            ORDER[1],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n        AXIS[\"geodetic longitude (Lon)\",east,\n            ORDER[2],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n    ID[\"EPSG\",4326]]"), class = "crs"), n_empty = 0L)), sf_column = "geometry", agr = structure(c(store_number = NA_integer_, 
store_type = NA_integer_, address = NA_integer_, city = NA_integer_, 
state = NA_integer_, zip_code = NA_integer_, phone_number = NA_integer_, 
store_hours = NA_integer_, services = NA_integer_, website_address = NA_integer_, 
latitude = NA_integer_, longitude = NA_integer_, country_code = NA_integer_, 
county = NA_integer_, country = NA_integer_, geo_accuracy = NA_integer_
), class = "factor", levels = c("constant", "aggregate", "identity"
)), row.names = c(NA, 10L), class = "data.frame")

iso <- as.data.frame(c())
for (i in 1:nrow(df)){
  iso[i,] <- isoline(
    st_sf(df[i,]),  
    range = (5*60),                 
    range_type = "time",            
    routing_mode = "fast",          
    transport_mode = "car",         
    aggregate = TRUE,
    traffic = TRUE              
  ) 
  print(iso)
 iso$store_number[i] <- df$store_number[i]
}

st_write(obj = iso, dsn = "5min_isoline.shp", factorsAsCharacter = T, delete_layer = T)

ERROR:

<[1] id <0 rows> (or 0-length row.names) Error in $<-.data.frame(*tmp*, "zip", value = "J9L 1L6") : replacement has 1 row, data has 0 In addition: Warning messages: 1: In [<-.data.frame(*tmp*, i, value = list(id = NA, rank = 1, : replacement element 1 has 1 row to replace 0 rows 2: In [<-.data.frame(*tmp*, i, value = list(id = NA, rank = 1, : replacement element 2 has 1 row to replace 0 rows 3: In [<-.data.frame(*tmp*, i, value = list(id = NA, rank = 1, : replacement element 3 has 1 row to replace 0 rows 4: In [<-.data.frame(*tmp*, i, value = list(id = NA, rank = 1, : replacement element 4 has 1 row to replace 0 rows 5: In [<-.data.frame(*tmp*, i, value = list(id = NA, rank = 1, : replacement element 5 has 1 row to replace 0 rows 6: In [<-.data.frame(*tmp*, i, value = list(id = NA, rank = 1, : replacement element 6 has 1 row to replace 0 rows 7: In [<-.data.frame(*tmp*, i, value = list(id = NA, rank = 1, : provided 6 variables to replace 1 variables >

Results :( <structure(list(id = logical(0)), row.names = integer(0), class = "data.frame")>


Solution

  • The error is not on the HERE library but on the data structure of the data frame used for saving the returned isoline.

    > for (i in 1:nrow(df)){
    +   result <- isoline(
    +     st_sf(df[i,]),  
    +     range = (5*60),                 
    +     range_type = "time",            
    +     routing_mode = "fast",          
    +     transport_mode = "car",         
    +     aggregate = TRUE,
    +     traffic = TRUE              
    +   )
    +   print(result)
    + }
    Simple feature collection with 1 feature and 5 fields
    Geometry type: POLYGON
    Dimension:     XY
    Bounding box:  xmin: -75.5571 ymin: 46.52435 xmax: -75.41428 ymax: 46.58615
    Geodetic CRS:  WGS 84
      id rank           departure             arrival range                       geometry
    1 NA    1 2023-05-22 17:39:07 2023-05-22 17:44:07   300 POLYGON ((-75.55676 46.5641...
    Simple feature collection with 1 feature and 5 fields
    Geometry type: POLYGON
    Dimension:     XY
    Bounding box:  xmin: -75.8963 ymin: 45.38796 xmax: -75.78884 ymax: 45.44014
    Geodetic CRS:  WGS 84
      id rank           departure             arrival range                       geometry
    1 NA    1 2023-05-22 17:39:08 2023-05-22 17:44:08   300 POLYGON ((-75.89626 45.4259...
    Simple feature collection with 1 feature and 5 fields
    Geometry type: POLYGON
    Dimension:     XY
    Bounding box:  xmin: -75.8448 ymin: 45.39791 xmax: -75.78129 ymax: 45.44151
    Geodetic CRS:  WGS 84
      id rank           departure             arrival range                       geometry
    1 NA    1 2023-05-22 17:39:08 2023-05-22 17:44:08   300 POLYGON ((-75.84476 45.4105...
    Simple feature collection with 1 feature and 5 fields
    Geometry type: POLYGON
    Dimension:     XY
    Bounding box:  xmin: -75.86815 ymin: 45.37937 xmax: -75.77717 ymax: 45.4192
    Geodetic CRS:  WGS 84
      id rank           departure             arrival range                       geometry
    1 NA    1 2023-05-22 17:39:09 2023-05-22 17:44:09   300 POLYGON ((-75.86811 45.4088...
    Simple feature collection with 1 feature and 5 fields
    Geometry type: POLYGON
    Dimension:     XY
    Bounding box:  xmin: -75.82935 ymin: 45.42332 xmax: -75.74078 ymax: 45.45971
    Geodetic CRS:  WGS 84
      id rank           departure             arrival range                       geometry
    1 NA    1 2023-05-22 17:39:09 2023-05-22 17:44:09   300 POLYGON ((-75.82931 45.4414...
    Simple feature collection with 1 feature and 5 fields
    Geometry type: POLYGON
    Dimension:     XY
    Bounding box:  xmin: -75.80154 ymin: 45.39757 xmax: -75.72601 ymax: 45.4525
    Geodetic CRS:  WGS 84
      id rank           departure             arrival range                       geometry
    1 NA    1 2023-05-22 17:39:09 2023-05-22 17:44:09   300 POLYGON ((-75.80146 45.4262...
    Simple feature collection with 1 feature and 5 fields
    Geometry type: POLYGON
    Dimension:     XY
    Bounding box:  xmin: -75.81459 ymin: 45.44632 xmax: -75.73013 ymax: 45.51773
    Geodetic CRS:  WGS 84
      id rank           departure             arrival range                       geometry
    1 NA    1 2023-05-22 17:39:09 2023-05-22 17:44:09   300 POLYGON ((-75.81425 45.5177...
    Simple feature collection with 1 feature and 5 fields
    Geometry type: POLYGON
    Dimension:     XY
    Bounding box:  xmin: -75.78438 ymin: 45.43327 xmax: -75.69855 ymax: 45.48477
    Geodetic CRS:  WGS 84
      id rank           departure             arrival range                       geometry
    1 NA    1 2023-05-22 17:39:10 2023-05-22 17:44:10   300 POLYGON ((-75.78429 45.4736...
    Simple feature collection with 1 feature and 5 fields
    Geometry type: POLYGON
    Dimension:     XY
    Bounding box:  xmin: -75.78438 ymin: 45.42091 xmax: -75.68687 ymax: 45.47996
    Geodetic CRS:  WGS 84
      id rank           departure             arrival range                       geometry
    1 NA    1 2023-05-22 17:39:10 2023-05-22 17:44:10   300 POLYGON ((-75.78429 45.4447...
    Simple feature collection with 1 feature and 5 fields
    Geometry type: POLYGON
    Dimension:     XY
    Bounding box:  xmin: -75.7679 ymin: 45.40924 xmax: -75.69374 ymax: 45.47104
    Geodetic CRS:  WGS 84
      id rank           departure             arrival range                       geometry
    1 NA    1 2023-05-22 17:39:10 2023-05-22 17:44:10   300 POLYGON ((-75.76756 45.4154...
    

    And you can even skip the for loop since hereR can process data in bulk, just remember to put aggregate value to FALSE:

    result <- isoline(
        st_sf(df), # not need to loop through the data frame
        range = (5 * 60),
        range_type = "time",
        routing_mode = "fast",
        transport_mode = "car",
        aggregate = FALSE, # when aggregate is off it returns 10 results
        traffic = TRUE
    )
    # if in need, convert the feature data back to data frame
    as.data.frame(result)