walkerke / mapboxapi

R interface to Mapbox web services
https://walker-data.com/mapboxapi/
Other
110 stars 8 forks source link

Optional Parameters for mb_matrix()? #13

Closed mrworthington closed 2 years ago

mrworthington commented 3 years ago

In replicating the matrices example for Travis County (Austin, TX), I noticed that the estimated drive times seem wildly inaccurate. Perhaps I'm misunderstanding how it's calculating drive times, but estimating that it takes nearly an hour and a half to drive from Lakeway (a suburb outside of Austin) to downtown is a huge stretch.

Suggested Solution

My guess is that the api is producing a very conservative drive time estimate, potentially based on lots of traffic. While even I think these figures are high for that, I can only conclude that this is how an estimated drive time from Lakeway to Downtown got that bad.

After reading through Mapbox's Direction API docs (which I believe is what powersmb_matrix()), I noticed that in version 5 there are optional drive time parameters, which can set specific times of day.

Would implementing these optional parameters help solve these? See the code and output below.

First Off, Here's The Reprex

library(mapboxapi)
#> Usage of the Mapbox APIs is governed by the Mapbox Terms of Service.
#> Please visit https://www.mapbox.com/legal/tos/ for more information.
library(tigris)
#> To enable 
#> caching of data, set `options(tigris_use_cache = TRUE)` in your R script or .Rprofile.
library(mapdeck)

austin_tracts <- tracts("TX", "Travis", cb = TRUE, class = "sf")
#>   |                                                                              |                                                                      |   0%  |                                                                              |                                                                      |   1%  |                                                                              |=                                                                     |   1%  |                                                                              |=                                                                     |   2%  |                                                                              |==                                                                    |   2%  |                                                                              |==                                                                    |   3%  |                                                                              |===                                                                   |   4%  |                                                                              |====                                                                  |   5%  |                                                                              |====                                                                  |   6%  |                                                                              |=====                                                                 |   7%  |                                                                              |======                                                                |   8%  |                                                                              |=======                                                               |   9%  |                                                                              |=======                                                               |  10%  |                                                                              |========                                                              |  11%  |                                                                              |=========                                                             |  12%  |                                                                              |=========                                                             |  14%  |                                                                              |==========                                                            |  14%  |                                                                              |===========                                                           |  16%  |                                                                              |=============                                                         |  18%  |                                                                              |==============                                                        |  19%  |                                                                              |==============                                                        |  21%  |                                                                              |===============                                                       |  22%  |                                                                              |================                                                      |  23%  |                                                                              |=================                                                     |  25%  |                                                                              |=========================                                             |  35%  |                                                                              |==========================                                            |  37%  |                                                                              |============================                                          |  40%  |                                                                              |==============================                                        |  43%  |                                                                              |====================================                                  |  52%  |                                                                              |============================================================          |  86%  |                                                                              |=============================================================         |  88%  |                                                                              |=================================================================     |  92%  |                                                                              |===================================================================   |  96%  |                                                                              |====================================================================  |  97%  |                                                                              |====================================================================  |  98%  |                                                                              |======================================================================| 100%
downtown_austin <- mb_geocode("Austin City Hall, Austin TX")

time_to_downtown <- mb_matrix(austin_tracts, downtown_austin, profile = "driving")
#> Splitting your matrix request into smaller chunks and re-assembling the result.
#> Using feature centroids for origins

austin_tracts$time <- time_to_downtown

mapdeck(style = mapdeck_style("light"), token = Sys.getenv("MAPDECK_TOKEN")) |> 
  add_polygon(data = austin_tracts,
              fill_colour = "time",
              fill_opacity = 0.6,
              legend = TRUE)
#> Registered S3 method overwritten by 'jsonify':
#>   method     from    
#>   print.json jsonlite

Created on 2021-08-24 by the reprex package (v2.0.1)

Session Info ```r R version 4.1.0 (2021-05-18) Platform: aarch64-apple-darwin20 (64-bit) Running under: macOS Big Sur 11.5 Matrix products: default LAPACK: /Library/Frameworks/R.framework/Versions/4.1-arm64/Resources/lib/libRlapack.dylib locale: [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8 attached base packages: [1] stats graphics grDevices utils datasets methods base other attached packages: [1] mapdeck_0.3.4 tigris_1.4.1 mapboxapi_0.2 loaded via a namespace (and not attached): [1] httr_1.4.2 tidyr_1.1.3 jsonlite_1.7.2 assertthat_0.2.1 [5] highr_0.9 sp_1.4-5 stats4_4.1.0 yaml_2.2.1 [9] backports_1.2.1 pillar_1.6.2 lattice_0.20-44 glue_1.4.2 [13] uuid_0.1-4 digest_0.6.27 RColorBrewer_1.1-2 colorspace_2.0-2 [17] jsonify_1.2.1 leaflet.providers_1.9.0 htmltools_0.5.1.1 clipr_0.7.1 [21] slippymath_0.3.1 pkgconfig_2.0.3 raster_3.4-13 magick_2.7.3 [25] s2_1.0.6 purrr_0.3.4 scales_1.1.1 webshot_0.5.2 [29] processx_3.5.2 satellite_1.0.2 tibble_3.1.3 proxy_0.4-26 [33] aws.s3_0.3.21 styler_1.5.1 generics_0.1.0 ellipsis_0.3.2 [37] withr_2.4.2 cli_3.0.1 mapview_2.10.0 magrittr_2.0.1 [41] crayon_1.4.1 ps_1.6.0 evaluate_0.14 maptools_1.1-1 [45] fs_1.5.0 fansi_0.5.0 xml2_1.3.2 foreign_0.8-81 [49] class_7.3-19 geojsonsf_2.0.1 tools_4.1.0 lifecycle_1.0.0 [53] protolite_2.1.1 stringr_1.4.0 munsell_0.5.0 reprex_2.0.1 [57] callr_3.7.0 compiler_4.1.0 e1071_1.7-8 sfheaders_0.4.0 [61] rlang_0.4.11 classInt_0.4-3 units_0.7-2 grid_4.1.0 [65] rstudioapi_0.13 rappdirs_0.3.3 htmlwidgets_1.5.3 aws.signature_0.6.0 [69] crosstalk_1.1.1 rmarkdown_2.10 leafem_0.1.6 base64enc_0.1-3 [73] wk_0.5.0 codetools_0.2-18 DBI_1.1.1 curl_4.3.2 [77] R6_2.5.1 knitr_1.33 dplyr_1.0.7 rgdal_1.5-23 [81] utf8_1.2.2 KernSmooth_2.23-20 stringi_1.7.3 Rcpp_1.0.7 [85] vctrs_0.3.8 sf_1.0-2 png_0.1-7 xfun_0.25 [89] leaflet_2.0.4.1 tidyselect_1.1.1 ```

Second, Here's The Output vs. Google Map Drive Times

You can see the yellow tract, which is the Lakeway area. Compared the Google Maps drive time estimates (which are about half as long), you can see why this is highly suspicious.

The Original Output from Mapbox

Screen Shot 2021-08-24 at 1 32 45 PM
The Google Maps Drive Times
Screen Shot 2021-08-24 at 1 35 02 PM
walkerke commented 3 years ago

This is a good question and potentially speaks to some underlying issues I need to figure out. mb_matrix() uses centroids of polygons by default when polygons are used as a matrix input. In suburban/rural areas, this can mean that centroids are placed in unroutable locations. Here's our offending tract centroid:

image

Usually, this triggers the fallback_speed parameter which will calculate a travel time based on a straight line between the locations. However, this result is actually succeeding. Here's the response from the API, returning a travel-time of 5100 seconds:

{"code":"Ok","durations":[[0.0,5149.5],[5051.1,0.0]],"destinations":[{"distance":308.940051864,"name":"Kollmeyer Drive","location":[-97.933931,30.366811]},{"distance":21.315213694,"name":"West 2nd Street","location":[-97.747122,30.265133]}],"sources":[{"distance":308.940051864,"name":"Kollmeyer Drive","location":[-97.933931,30.366811]},{"distance":21.315213694,"name":"West 2nd Street","location":[-97.747122,30.265133]}]}

The response suggests that the point is being snapped to the road network, as it is located on Kollmeyer Drive here:

image

However, mb_directions() between those locations returns a different (correct) result:

mb_directions(origin = c(-97.933931,30.366811),
              destination = downtown_austin)
Simple feature collection with 1 feature and 2 fields
Geometry type: LINESTRING
Dimension:     XY
Bounding box:  xmin: -97.96983 ymin: 30.23641 xmax: -97.74663 ymax: 30.37229
Geodetic CRS:  WGS 84
                        geometry distance duration
1 LINESTRING (-97.93393 30.36... 36.07321 36.85643

image

So I'm a bit perplexed by this. I'll ping Mapbox support and see if they have any suggestions.

mrworthington commented 3 years ago

I absolutely meant mb_matrix() but it was a day yesterday. Adjusting the main comment.

walkerke commented 2 years ago

@mrworthington looping back on this, I re-ran your example and it appears to be returning sensible results from Mapbox's side now:

image

Regarding your broader discussion: the directions and isochrone APIs support a depart_at parameter which allows for different time-of-day calculations. The Matrix API does accept this too but in testing it isn't returning different results, which makes me think it isn't implemented yet.