Skip to content

Instantly share code, notes, and snippets.

@geblanco
Created May 5, 2021 11:28
Show Gist options
  • Save geblanco/28b03aed8c59f72aa22e3c6d39ca4036 to your computer and use it in GitHub Desktop.
Save geblanco/28b03aed8c59f72aa22e3c6d39ca4036 to your computer and use it in GitHub Desktop.
Simple script to paint in an interactive map a set of addreses from a csv file.
# !pip install requests urllib3 geopy pandas folium
# partially taken from:
# https://towardsdatascience.com/pythons-geocoding-convert-a-list-of-addresses-into-a-map-f522ef513fd6\
import requests
import json
import urllib
from geopy.geocoders import Nominatim, GoogleV3
import pandas as pd
import folium
from folium.plugins import MarkerCluster
from pathlib import Path
# MapQuest is also avialable in geocoders, it's free.
# Requires signup to get an API key
base_url= "https://maps.googleapis.com/maps/api/geocode/json?"
AUTH_KEY = "<PUT YOUR TOKEN HERE>"
geolocator = GoogleV3(api_key=AUTH_KEY)
# just a test
# parameters = {"address": "Tuscany, Italy", "key": AUTH_KEY}
# print(f"{base_url}{urllib.parse.urlencode(parameters)}")
# r = requests.get(f"{base_url}{urllib.parse.urlencode(parameters)}")
# data = json.loads(r.content)
# data
# data file
data_file = "./oficinas_registro.csv"
# data with geolocalization data
geoloc_processed_file = "./oficinas_registro_geoloc.csv"
# output map file
map_file = "./oficinas_registro_map.html"
popup_field = "DENOMINACION OFICINA DE REGISTRO"
tooltip_field = "DENOMINACION OFICINA DE REGISTRO"
# Preprocess data to get addresses field
def add_address_field(data):
data["address"] = \
data[["TIPO VIA","NOMBRE VIA"]]\
.dropna(axis=1)\
.astype(str)\
.agg(" ".join, axis=1) + \
data[["N? VIA","CP","RESTO DIRECCION","LOCALIDAD","PROVINCIA","ISLA","COMUNIDAD AUTONOMA"]]\
.dropna(axis=1)\
.astype(str)\
.agg(", ".join, axis=1)
return data
# Add geolocalization data, requires API KEY
def apply_geoloc(data, geolocator):
data["loc"] = data["address"].apply(geolocator.geocode)
data["point"] = data["loc"].apply(
lambda loc: tuple(loc.point) if loc else None
)
data[["lat", "lon", "altitude"]] = pd.DataFrame(
data["point"].to_list(), index=data.index
)
return data
def load_data(geoloc_processed_file, data_file, geolocator):
if Path(geoloc_processed_file).exists():
data = pd.read_csv(geoloc_processed_file)
else:
data = add_address_field(pd.read_csv(data_file))
data = apply_geoloc(data, geolocator)
data.to_csv(geoloc_processed_file)
return data
def build_map(data, popup_field, tooltip_field):
# center to the mean of all points
m = folium.Map(location=data[["lat", "lon"]].mean().to_list(), zoom_start=2)
# if the points are too close to each other, cluster them, create a cluster overlay with MarkerCluster
marker_cluster = MarkerCluster().add_to(m)
# draw the markers and assign popup and hover texts
# add the markers the the cluster layers so that they are automatically clustered
for i,r in data.iterrows():
location = (r["lat"], r["lon"])
folium.Marker(
location=location,
popup = r[popup_field],
tooltip=r[tooltip_field]
).add_to(marker_cluster)
return m
data = load_data(geoloc_processed_file, data_file, geolocator)
m = build_map(data, popup_field, tooltip_field)
m.save(map_file)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment