A tutorial with code examples in python
For some initiatives it may be helpful to attract routes on a map. Right here yow will discover all the knowledge you want: packages, API’s and code examples. In the long run, you possibly can create stunning interactive maps.
We’re going to use geopy and folium, each packages are designed for working with geospatial information in python. First, set up the packages utilizing conda or pip:
# conda
conda set up -c conda-forge folium
conda set up -c conda-forge geopy# pip
pip set up folium
pip set up geopy
Apart from these packages, you want to have the ability to name an API that provides route coordinates in multiline segments. An API that does that is the route and route API. You can also make an account on RapidAPI and subscribe to the route and route API. The RapidAPI free plan consists of 30 000 free calls each month, a pleasant quantity to start out with. There are different (extra business) choices out there like ArcGIS or Google Maps instructions, so select what matches your case.
The code on the finish of this part makes use of the route and route API I discussed earlier. It’s very easy to get the instructions between two factors: it’s good to specify the latitude and longitude of the 2 factors. In case your dataset comprises addresses with out latitude and longitude values, don’t fear, it’s straightforward to transform them. This course of is known as geocoding. With geopy, it really works as follows:
from geopy.geocoders import Nominatimdef get_lat_long_from_address(tackle):
locator = Nominatim(user_agent='myGeocoder')
location = locator.geocode(tackle)
return location.latitude, location.longitude# instance
tackle = 'Zeeweg 94, 2051 EC Overveen'
get_lat_long_from_address(tackle)
>>> (52.4013046, 4.5425025)
Within the route and route API, you may also specify the transportation mode you wish to use: drive, truck, bicycle, stroll or transit.
To name the API, you want an API key. After subscribing yow will discover it right here:
Name the API to get the instructions from the primary tackle to the second:
import requestsdef get_directions_response(lat1, long1, lat2, long2, mode='drive'):
url = "https://route-and-directions.p.rapidapi.com/v1/routing"
key = "YOUR-API-KEY"
host = "route-and-directions.p.rapidapi.com"
headers = {"X-RapidAPI-Key": key, "X-RapidAPI-Host": host}
querystring = {"waypoints":f"{str(lat1)},{str(long1)}|{str(lat2)},{str(long2)}","mode":mode}
response = requests.request("GET", url, headers=headers, params=querystring)
return responseresponse = get_directions_response(52.4013, 4.5425, 52.402, 4.5426)
The response
variable seems like this (click on to enlarge):
For our route plot, we want the geometry: it comprises all of the coordinates between which we’ve got to attract traces, it will create the route on the map.
Be aware that the response additionally comprises driver directions, like: ‘Enter the roundabout and take the 2nd exit onto Zeeweg/N200.’ Cool, isn’t it? You should utilize them for navigation functions.
Now we are able to use the info to visualise the route!
The perform beneath creates a map with a route between two factors. The enter is the response we obtained from the API name to the route and instructions API. We extract the coordinates from the response. Than we add markers (for the beginning and finish level) and draw the traces utilizing PolyLine
. An necessary a part of the script creates the optimum zoom, this ensures that your route will all the time be within the middle of the map. For this we use the minimal and most latitude and longitude values and fit_bounds
.
import foliumdef create_map(response):
# use the response
mls = response.json()['features'][0]['geometry']['coordinates']
factors = [(i[1], i[0]) for i in mls[0]] m = folium.Map() # add marker for the beginning and ending factors
for level in [points[0], factors[-1]]:
folium.Marker(level).add_to(m) # add the traces
folium.PolyLine(factors, weight=5, opacity=1).add_to(m) # create optimum zoom
df = pd.DataFrame(mls[0]).rename(columns={0:'Lon', 1:'Lat'})[['Lat', 'Lon']]
sw = df[['Lat', 'Lon']].min().values.tolist()
ne = df[['Lat', 'Lon']].max().values.tolist()
m.fit_bounds([sw, ne])
return mm = create_map(response)
Should you’re working in a Pocket book, you possibly can name m
and also you see:
Stunning! Another choice is to save lots of the picture as html and open it in a browser:
m.save('./route_map.html')
An enchancment of the perform could possibly be so as to add extra addresses. Let’s create a metropolis stroll alongside the highlights of Paris.
First we specify our addresses:
# touristic route by means of Paris (Eiffel Tower, Arc de Triomphe, ...)
address1 = '5 Avenue Anatole France, 75007 Paris, France'
address2 = 'Place Charles de Gaulle, 75008 Paris, France'
address3 = '60 Avenue des Champs-Élysées, 75008 Paris, France'
address4 = "Place de l'Opéra, 75009 Paris, France"
address5 = 'Rue de Rivoli, 75001 Paris, France'
address6 = '10 Bd du Palais, 75001 Paris, France'
address7 = '3 Rue Guynemer, 75006 Paris, France'
address8 = '33 Avenue du Maine, 75015 Paris, France' addresses = [address1, address2, address3, address4, address5, address6, address7, address8]
As a substitute of addresses we want coordinates, so we create an inventory with latitudes and longitudes utilizing the get_lat_long_from_address
perform we created earlier:
lat_lons = [get_lat_long_from_address(addr) for addr in addresses]
Then, we name the API to get the instructions between the factors with the get_directions_response
perform:
responses = []for n in vary(len(lat_lons)-1):
lat1, lon1, lat2, lon2 = lat_lons[n][0], lat_lons[n][1], lat_lons[n+1][0], lat_lons[n+1][1]
response = get_directions_response(lat1, lon1, lat2, lon2, mode='stroll')
responses.append(response)
Now we modify the create_map
perform to deal with a number of responses:
def create_map(responses, lat_lons):
m = folium.Map()
df = pd.DataFrame() # add markers for the locations we go to
for level in lat_lons:
folium.Marker(level).add_to(m) # loop over the responses and plot the traces of the route
for response in responses:
mls = response.json()['features'][0]['geometry']['coordinates']
factors = [(i[1], i[0]) for i in mls[0]]# add the traces
temp = pd.DataFrame(mls[0]).rename(columns={0:'Lon', 1:'Lat'})[['Lat', 'Lon']]
folium.PolyLine(factors, weight=5, opacity=1).add_to(m)
df = pd.concat([df, temp]) # create optimum zoom
sw = df[['Lat', 'Lon']].min().values.tolist()
sw = [sw[0]-0.0005, sw[1]-0.0005]
ne = df[['Lat', 'Lon']].max().values.tolist()
ne = [ne[0]+0.0005, ne[1]+0.0005]
m.fit_bounds([sw, ne])
return mm = create_map(responses, lat_lons)
m
seems like this:
A enjoyable addition right here could be to calculate the shortest or quickest route between all of the addresses with optimization. Extra information within the article beneath (instance 2):