opencage tutorial

for v0.1.0

This package is an interface to the OpenCage API that allows forward and reverse geocoding. To use the package, you will need an API key. To get an API key for OpenCage geocoding, register at https://geocoder.opencagedata.com/pricing. The free API key provides up to 2,500 calls a day. For ease of use, save your API key as an environment variable as described at http://stat545.com/bit003_api-key-env-var.html.

Both functions of the package will conveniently look for your API key using Sys.getenv("OPENCAGE_KEY") so if your API key is an environment variable called "OPENCAGE_KEY" you don't need to input it manually.

Geocoding

The OpenCage API supports forward and reverse geocoding. Sources of OpenCage are open geospatial data including OpenStreetMap, Yahoo! GeoPlanet, Natural Earth Data, Thematic Mapping, Ordnance Survey OpenSpace, Statistics New Zealand, Zillow, MaxMind, GeoNames, the US Census Bureau and Flickr's shapefiles plus a whole lot more besides. See this page for the full list of credits.

Both forward and reverse geocoding typically return multiple results. Regarding these multiple results, the API doc states, "In cases where the geocoder is able to find multiple matches, the geocoder will return multiple results. The confidence or coordinates for each result should be examined to determine whether each result from an ambiguous query is sufficiently high to warrant using a result or not. A good strategy to reduce ambiguity is to use the optional bounds parameter described below to limit the area searched." Multiple results might mean you get a result for the airport and a road when querying a city name, or results for cities with the same name in different countries.

Installation

Stable version from CRAN

install.packages("opencage")

Development version from GitHub

if (!require("devtools")) install.packages("devtools")
devtools::install_github("ropenscilabs/opencage")
library("opencage")

Usage

Forward geocoding

Forward geocoding is from placename to latitude and longitude tuplet(s).

output <- opencage_forward(placename = "Sarzeau")
library("dplyr")
output$rate_info
#> # A tibble: 1 × 3
#>   limit remaining               reset
#>   <int>     <int>              <dttm>
#> 1  2500      2483 2016-09-04 17:00:00
output$results
#> # A tibble: 2 × 44
#>    annotations.DMS.lat annotations.DMS.lng annotations.MGRS
#>                  <chr>               <chr>            <chr>
#> 1 47° 31' 43.56984'' N 2° 45' 51.11856'' W  30TWT1774963954
#> 2 47° 31' 40.80828'' N  2° 46' 7.68144'' W  30TWT1740363867
#> # ... with 41 more variables: annotations.Maidenhead <chr>,
#> #   annotations.Mercator.x <chr>, annotations.Mercator.y <chr>,
#> #   annotations.OSM.edit_url <chr>, annotations.OSM.type <chr>,
#> #   annotations.OSM.url <chr>, annotations.callingcode <fctr>,
#> #   annotations.geohash <chr>, annotations.sun.rise.apparent <fctr>,
#> #   annotations.sun.rise.astronomical <fctr>,
#> #   annotations.sun.rise.civil <fctr>,
#> #   annotations.sun.rise.nautical <fctr>,
#> #   annotations.sun.set.apparent <fctr>,
#> #   annotations.sun.set.astronomical <fctr>,
#> #   annotations.sun.set.civil <fctr>, annotations.sun.set.nautical <fctr>,
#> #   annotations.timezone.name <fctr>,
#> #   annotations.timezone.now_in_dst <fctr>,
#> #   annotations.timezone.offset_sec <fctr>,
#> #   annotations.timezone.offset_string <fctr>,
#> #   annotations.timezone.short_name <fctr>,
#> #   annotations.what3words.words <chr>, bounds.northeast.lat <chr>,
#> #   bounds.northeast.lng <chr>, bounds.southwest.lat <chr>,
#> #   bounds.southwest.lng <chr>, components._type <chr>,
#> #   components.city <fctr>, components.country <fctr>,
#> #   components.country_code <fctr>, components.county <fctr>,
#> #   components.postcode <fctr>, components.state <fctr>, confidence <chr>,
#> #   formatted <chr>, geometry.lat <dbl>, geometry.lng <dbl>,
#> #   components.post_office <fctr>, components.road <fctr>,
#> #   components.suburb <fctr>, components.village <fctr>

Reverse geocoding

Reverse geocoding is from latitude and longitude to placename(s).

output2 <- opencage_reverse(latitude = 51.5034070,
                            longitude = -0.1275920)
output2$rate_info
#> # A tibble: 1 × 3
#>   limit remaining               reset
#>   <int>     <int>              <dttm>
#> 1  2500      2475 2016-09-04 17:00:00
output2$results
#> # A tibble: 1 × 43
#>    annotations.DMS.lat annotations.DMS.lng annotations.MGRS
#>                 <fctr>              <fctr>           <fctr>
#> 1 51° 30' 12.38490'' N  0° 7' 39.74919'' E  30UXC9933909723
#> # ... with 40 more variables: annotations.Maidenhead <fctr>,
#> #   annotations.Mercator.x <fctr>, annotations.Mercator.y <fctr>,
#> #   annotations.OSGB.easting <fctr>, annotations.OSGB.gridref <fctr>,
#> #   annotations.OSGB.northing <fctr>, annotations.OSM.edit_url <fctr>,
#> #   annotations.OSM.type <fctr>, annotations.OSM.url <fctr>,
#> #   annotations.callingcode <fctr>, annotations.geohash <fctr>,
#> #   annotations.sun.rise.apparent <fctr>,
#> #   annotations.sun.rise.astronomical <fctr>,
#> #   annotations.sun.rise.civil <fctr>,
#> #   annotations.sun.rise.nautical <fctr>,
#> #   annotations.sun.set.apparent <fctr>,
#> #   annotations.sun.set.astronomical <fctr>,
#> #   annotations.sun.set.civil <fctr>, annotations.sun.set.nautical <fctr>,
#> #   annotations.timezone.name <fctr>,
#> #   annotations.timezone.now_in_dst <fctr>,
#> #   annotations.timezone.offset_sec <fctr>,
#> #   annotations.timezone.offset_string <fctr>,
#> #   annotations.timezone.short_name <fctr>,
#> #   annotations.what3words.words <fctr>, components._type <fctr>,
#> #   components.attraction <fctr>, components.city <fctr>,
#> #   components.country <fctr>, components.country_code <fctr>,
#> #   components.house_number <fctr>, components.postcode <fctr>,
#> #   components.road <fctr>, components.state <fctr>,
#> #   components.state_district <fctr>, components.suburb <fctr>,
#> #   confidence <fctr>, formatted <fctr>, geometry.lat <dbl>,
#> #   geometry.lng <dbl>

Parameters

Optional parameters of both opencage_forward and opencage_reverse can make the query more precise:

  • bounds: Provides the geocoder with a hint to the region that the query resides in. This value will restrict the possible results to the supplied region. The bounds parameter should be specified as 4 coordinate points forming the south-west and north-east corners of a bounding box. For example, bounds = c(-0.563160, 51.280430, 0.278970, 51.683979) (min long, min lat, max long, max lat).

Below is an example of the use of bounds where the rectangle given in the second call does not include Europe so that we don't get results for Berlin in Germany.

results1 <- opencage_forward(placename = "Berlin")
results1$results
#> # A tibble: 9 × 41
#>    annotations.DMS.lat  annotations.DMS.lng annotations.MGRS
#>                  <chr>                <chr>            <chr>
#> 1  52° 31' 1.33140'' N 13° 23' 19.89564'' E  33UUU9067619766
#> 2  44° 28' 7.21056'' N  71° 11' 6.27612'' W  19TCK2619726251
#> 3 41° 37' 17.35680'' N 72° 44' 44.34648'' W  18TXM8780710206
#> 4 39° 47' 28.41432'' N 74° 55' 44.59260'' W  18SWK0607404588
#> 5 42° 22' 52.33440'' N 71° 38' 13.24320'' W  19TBG8291095470
#> 6 38° 19' 21.41544'' N  75° 13' 3.68076'' W  18SVH8097141633
#> 7  43° 58' 4.93140'' N 88° 56' 36.41136'' W  16TCP4410170158
#> 8 39° 55' 14.29068'' N 78° 57' 28.08756'' W  17SPE7452920945
#> 9  4° 48' 37.67346'' N 75° 40' 55.66247'' W  18NVL2435931751
#> # ... with 38 more variables: annotations.Maidenhead <chr>,
#> #   annotations.Mercator.x <chr>, annotations.Mercator.y <chr>,
#> #   annotations.OSM.edit_url <chr>, annotations.OSM.type <chr>,
#> #   annotations.OSM.url <chr>, annotations.callingcode <chr>,
#> #   annotations.geohash <chr>, annotations.sun.rise.apparent <chr>,
#> #   annotations.sun.rise.astronomical <chr>,
#> #   annotations.sun.rise.civil <chr>, annotations.sun.rise.nautical <chr>,
#> #   annotations.sun.set.apparent <chr>,
#> #   annotations.sun.set.astronomical <chr>,
#> #   annotations.sun.set.civil <chr>, annotations.sun.set.nautical <chr>,
#> #   annotations.timezone.name <chr>,
#> #   annotations.timezone.now_in_dst <chr>,
#> #   annotations.timezone.offset_sec <chr>,
#> #   annotations.timezone.offset_string <chr>,
#> #   annotations.timezone.short_name <chr>,
#> #   annotations.what3words.words <chr>, bounds.northeast.lat <chr>,
#> #   bounds.northeast.lng <chr>, bounds.southwest.lat <chr>,
#> #   bounds.southwest.lng <chr>, components._type <chr>,
#> #   components.city <chr>, components.country <chr>,
#> #   components.country_code <chr>, components.state <chr>,
#> #   confidence <chr>, formatted <chr>, geometry.lat <dbl>,
#> #   geometry.lng <dbl>, components.county <chr>, components.town <fctr>,
#> #   components.city_district <fctr>
results2 <- opencage_forward(placename = "Berlin",
                             bounds = c(-90,38,0, 45))
results2$results
#> # A tibble: 10 × 41
#>     annotations.DMS.lat  annotations.DMS.lng annotations.MGRS
#>                   <chr>                <chr>            <chr>
#> 1   44° 28' 7.21056'' N  71° 11' 6.27612'' W  19TCK2619726251
#> 2  41° 37' 17.35680'' N 72° 44' 44.34648'' W  18TXM8780710206
#> 3  39° 47' 28.41432'' N 74° 55' 44.59260'' W  18SWK0607404588
#> 4  42° 22' 52.33440'' N 71° 38' 13.24320'' W  19TBG8291095470
#> 5  38° 19' 21.41544'' N  75° 13' 3.68076'' W  18SVH8097141633
#> 6   43° 58' 4.93140'' N 88° 56' 36.41136'' W  16TCP4410170158
#> 7  39° 55' 14.29068'' N 78° 57' 28.08756'' W  17SPE7452920945
#> 8  39° 45' 32.17932'' N 89° 54' 11.38824'' W  16SBK5129805033
#> 9  42° 41' 35.28636'' N 73° 22' 19.39728'' W  18TXN3335128023
#> 10 40° 33' 40.22424'' N 81° 47' 39.48144'' W  17TME3275690348
#> # ... with 38 more variables: annotations.Maidenhead <chr>,
#> #   annotations.Mercator.x <chr>, annotations.Mercator.y <chr>,
#> #   annotations.OSM.edit_url <chr>, annotations.OSM.type <chr>,
#> #   annotations.OSM.url <chr>, annotations.callingcode <fctr>,
#> #   annotations.geohash <chr>, annotations.sun.rise.apparent <chr>,
#> #   annotations.sun.rise.astronomical <chr>,
#> #   annotations.sun.rise.civil <chr>, annotations.sun.rise.nautical <chr>,
#> #   annotations.sun.set.apparent <chr>,
#> #   annotations.sun.set.astronomical <chr>,
#> #   annotations.sun.set.civil <chr>, annotations.sun.set.nautical <chr>,
#> #   annotations.timezone.name <chr>,
#> #   annotations.timezone.now_in_dst <fctr>,
#> #   annotations.timezone.offset_sec <chr>,
#> #   annotations.timezone.offset_string <chr>,
#> #   annotations.timezone.short_name <chr>,
#> #   annotations.what3words.words <chr>, bounds.northeast.lat <chr>,
#> #   bounds.northeast.lng <chr>, bounds.southwest.lat <chr>,
#> #   bounds.southwest.lng <chr>, components._type <chr>,
#> #   components.city <chr>, components.country <fctr>,
#> #   components.country_code <fctr>, components.county <chr>,
#> #   components.state <chr>, confidence <chr>, formatted <chr>,
#> #   geometry.lat <dbl>, geometry.lng <dbl>, components.town <fctr>,
#> #   components.village <fctr>
  • countrycode: Restricts the results to the given country. The country code is a two letter code as defined by the ISO 3166-1 Alpha 2 standard. E.g. "GB" for the United Kingdom, "FR" for France, "US" for United States. See example below.
results3 <- opencage_forward(placename = "Berlin", country = "DE")
results3$results
#> # A tibble: 9 × 52
#>    annotations.DMS.lat  annotations.DMS.lng annotations.MGRS
#>                  <chr>                <chr>            <chr>
#> 1  52° 31' 1.33140'' N 13° 23' 19.89564'' E  33UUU9067619766
#> 2  54° 2' 10.89780'' N 10° 26' 46.07268'' E  32UNE9470788534
#> 3 54° 24' 18.42840'' N  9° 25' 55.18776'' E  32UNF2804128682
#> 4 52° 22' 12.67680'' N  9° 45' 10.62252'' E  32UND5126202479
#> 5  53° 51' 4.53384'' N 10° 40' 56.93196'' E  32UPE1067368285
#> 6 52° 27' 24.31584'' N 13° 34' 45.17324'' E  33UVU0346012790
#> 7 53° 33' 34.54560'' N 13° 15' 17.89236'' E  33UUV8441535940
#> 8  52° 25' 7.43664'' N 13° 11' 47.05872'' E  33UUU7734509142
#> 9 52° 34' 59.62044'' N 13° 23' 56.74524'' E  33UUU9153427113
#> # ... with 49 more variables: annotations.Maidenhead <chr>,
#> #   annotations.Mercator.x <chr>, annotations.Mercator.y <chr>,
#> #   annotations.OSM.edit_url <chr>, annotations.OSM.type <chr>,
#> #   annotations.OSM.url <chr>, annotations.callingcode <fctr>,
#> #   annotations.geohash <chr>, annotations.sun.rise.apparent <chr>,
#> #   annotations.sun.rise.astronomical <chr>,
#> #   annotations.sun.rise.civil <chr>, annotations.sun.rise.nautical <chr>,
#> #   annotations.sun.set.apparent <chr>,
#> #   annotations.sun.set.astronomical <chr>,
#> #   annotations.sun.set.civil <chr>, annotations.sun.set.nautical <chr>,
#> #   annotations.timezone.name <fctr>,
#> #   annotations.timezone.now_in_dst <fctr>,
#> #   annotations.timezone.offset_sec <fctr>,
#> #   annotations.timezone.offset_string <fctr>,
#> #   annotations.timezone.short_name <fctr>,
#> #   annotations.what3words.words <chr>, bounds.northeast.lat <chr>,
#> #   bounds.northeast.lng <chr>, bounds.southwest.lat <chr>,
#> #   bounds.southwest.lng <chr>, components._type <chr>,
#> #   components.city <chr>, components.country <fctr>,
#> #   components.country_code <fctr>, components.state <chr>,
#> #   confidence <chr>, formatted <chr>, geometry.lat <dbl>,
#> #   geometry.lng <dbl>, components.county <chr>,
#> #   components.postcode <chr>, components.village <chr>,
#> #   components.road <chr>, components.city_district <chr>,
#> #   components.suburb <chr>, components.unknown <fctr>,
#> #   components.building <fctr>, components.house_number <chr>,
#> #   components.residential <fctr>, components.restaurant <fctr>,
#> #   components.town <fctr>, components.artwork <fctr>,
#> #   components.house <fctr>
  • language: an IETF format language code (such as "es" for Spanish or "pt-BR" for Brazilian Portuguese). If no language is explicitly specified, we will look for an HTTP Accept-Language header like those sent by a brower and use the first language specified and if none are specified "en" (English) will be assumed. See example below.
results4 <- opencage_forward(placename = "Berlin", country = "DE", language = "de")
results4$results
#> # A tibble: 9 × 52
#>    annotations.DMS.lat  annotations.DMS.lng annotations.MGRS
#>                  <chr>                <chr>            <chr>
#> 1  52° 31' 1.33140'' N 13° 23' 19.89564'' E  33UUU9067619766
#> 2  54° 2' 10.89780'' N 10° 26' 46.07268'' E  32UNE9470788534
#> 3 54° 24' 18.42840'' N  9° 25' 55.18776'' E  32UNF2804128682
#> 4 52° 22' 12.67680'' N  9° 45' 10.62252'' E  32UND5126202479
#> 5  53° 51' 4.53384'' N 10° 40' 56.93196'' E  32UPE1067368285
#> 6 52° 27' 24.31584'' N 13° 34' 45.17324'' E  33UVU0346012790
#> 7 53° 33' 34.54560'' N 13° 15' 17.89236'' E  33UUV8441535940
#> 8  52° 25' 7.43664'' N 13° 11' 47.05872'' E  33UUU7734509142
#> 9 52° 34' 59.62044'' N 13° 23' 56.74524'' E  33UUU9153427113
#> # ... with 49 more variables: annotations.Maidenhead <chr>,
#> #   annotations.Mercator.x <chr>, annotations.Mercator.y <chr>,
#> #   annotations.OSM.edit_url <chr>, annotations.OSM.type <chr>,
#> #   annotations.OSM.url <chr>, annotations.callingcode <fctr>,
#> #   annotations.geohash <chr>, annotations.sun.rise.apparent <chr>,
#> #   annotations.sun.rise.astronomical <chr>,
#> #   annotations.sun.rise.civil <chr>, annotations.sun.rise.nautical <chr>,
#> #   annotations.sun.set.apparent <chr>,
#> #   annotations.sun.set.astronomical <chr>,
#> #   annotations.sun.set.civil <chr>, annotations.sun.set.nautical <chr>,
#> #   annotations.timezone.name <fctr>,
#> #   annotations.timezone.now_in_dst <fctr>,
#> #   annotations.timezone.offset_sec <fctr>,
#> #   annotations.timezone.offset_string <fctr>,
#> #   annotations.timezone.short_name <fctr>,
#> #   annotations.what3words.words <chr>, bounds.northeast.lat <chr>,
#> #   bounds.northeast.lng <chr>, bounds.southwest.lat <chr>,
#> #   bounds.southwest.lng <chr>, components._type <chr>,
#> #   components.city <chr>, components.country <fctr>,
#> #   components.country_code <fctr>, components.state <chr>,
#> #   confidence <chr>, formatted <chr>, geometry.lat <dbl>,
#> #   geometry.lng <dbl>, components.county <chr>,
#> #   components.postcode <chr>, components.village <chr>,
#> #   components.road <chr>, components.city_district <chr>,
#> #   components.suburb <chr>, components.unknown <fctr>,
#> #   components.building <fctr>, components.house_number <chr>,
#> #   components.residential <fctr>, components.restaurant <fctr>,
#> #   components.town <fctr>, components.artwork <fctr>,
#> #   components.house <fctr>
  • limit: How many results should be returned (1-100). Default is 10.

  • min_confidence: an integer from 1-10. Only results with at least this confidence will be returned.

  • no_annotations: Logical (default FALSE), when TRUE the output will not contain annotations.

  • no_dedupe: Logical (default FALSE), when TRUE the output will not be deduplicated.

For more information about the output and the query parameters, see the package documentation, the API doc and OpenCage FAQ.

Caching

The underlying data at OpenCage is updated about once a day. Note that the package uses memoise with no timeout argument so that results are cached inside an active R session.

system.time(opencage_reverse(latitude = 10, longitude = 10))
#>    user  system elapsed 
#>       0       0       0
system.time(opencage_reverse(latitude = 10, longitude = 10))
#>    user  system elapsed 
#>   0.000   0.000   0.001
memoise::forget(opencage_reverse)
#> [1] TRUE
system.time(opencage_reverse(latitude = 10, longitude = 10))
#>    user  system elapsed 
#>   0.014   0.001   0.890

Privacy

Both functions have a parameter no_record. It is FALSE by default.

  • When no_record is FALSE a log of the query is made by OpenCage. The company uses them to better generally understand how people are using its service (forward or reverse geocoding, what parts of the world are people most interested in, etc) and for debugging. The overwhelming majority (99.9999+% of queries) are never specifically looked at (sheer volume prevents that) and are automatically deleted after a few days. More information about privacy can be found here.

  • When no_record is TRUE the actual query is replaced with FILTERED in OpenCage logs, so that the company has no chance to see what your request was.

Citing

Maëlle Salmon. 2016. opencage: Interface to the OpenCage API. R package version 0.1.0. https://cran.rstudio.com/package=opencage

License and bugs

Back to top

comments powered by Disqus