En este cuaderno utilizaremos las librerías de Pandas y Folium para leer una API que importaremos como archivo .csv sobre accidentes de tráfico en Zaragoza registrados por su Ayuntamiento. El objetivo es que Python lea esos datos para poder explorarlos con distintas funciones para representar la ubicación de los accidentes en un mapa. Lo primero lo podremos hacer con Pandas, una librería de código abierto de Python que proporciona herramientas de análisis y manipulación de datos. Lo segundo lo haremos con Folium, una librería de creación de mapas web interactivos con Python.
La relación entre ambas librerías para el manejo y representación de este conjunto de datos es que una de sus catergorías es calle
y sus datos son coordenadas geográficas. De ahí que supongan datos propicios para la combinación de ambas herramientas.
Definimos las variables con las que vamos a trabajar para que Python conozca los datos. Una variable es aquello que puedo crear como tal al nombrarlo. Su sintaxis es =
, por ejemplo, x = x. Vamos a definir como variables los elementos básicos de nuestro trabajo, a saber, los datos (para trabajarlos con Pandas) y las coordenadas geográficas de Zaragoza, escenario de los datos a representar (para hacerlo con Folium).
url_zrgz = "https://www.zaragoza.es/sede/servicio/transporte/accidentalidad-trafico/accidente.csv"
geo_zrgz = [41.646693,-0.887712]
Al definir estas variables no es necesario volver a copiar el link cuando queramos vincular los datos, sino que lo haremos con la referencia que hemos creado, en este caso url_zrgz
y geo_zrgz
. Como vemos, la sintaxis de la primera es con ""
y de la segunda con []
, puesto que se trata de un intervalo con ambos valores incluidos.
No es imprescindible definir estas referencias en primer lugar, pero sí forma parte de los pasos previos al inicio propiamente dicho del proceso exploratorio de los datos. Podemos resumir estos pasos previos en tres:
Procedemos al segundo punto:
La preparación de las librerías es la condición de posibilidad de nuestro trabajo. Conlleva dos pasos:
!pip install
librería)import
librería o import
librería as
su abreviación)Solo es necesaria la instalación de la librería que vayamos a utilizar a contunuación. Por lo que no es imprescindible instalar ahora Pandas. Podríamos hacerlo cuando el documento lo requiriese. Pero vamos a tenerla ya preparada. Tampoco es imprescindible instalar librerías si ya lo hemos hecho en otros cuadernos y Python las ha utilizado con anterioridad. Por ello no necesito instalarme Pandas de nuevo. La importación siempre es necesaria.
Instalo Folium: !pip install folium
!pip install folium
Ahora ya tengo las dos librerías instaladas en Python. Pero eso no significa que las tenga ya aquí en este documento para trabajar con ellas. Para ello necesito importarlas. Por eso, a diferencia que la instalación, que puede realizarse una sola vez, la importación es obligatoria en cada notebook en que quiera usarse. Con el comando import
importo ambas librerías.La de pandas lo hago con su abreviación típica pd.
import pandas as pd
import folium
Una vez tenemos las variables definidas (los datos y las coordenadas) y las librerías preparadas es hora de empezar a trabajar con los datos. Necesito abrirlos desde este documento creando un dataframe que los abra. Pero antes (aunque puedo no hacerlo así) abro el mapa para tener presente el espacio en el que quiero proceder a la representación de los datos.
De la librería Folium quiero que Python me muestre un mapa: el folio map con las cooredenadas anteriormente señaladas con la referencia geo_zrgz
. Definiremos esta acción mapa_zrgz con =
.
mapa_zrgz = folium.Map(location=geo_zrgz)
Hemos definido la variable, que a continuación decimos que la ejecute.
mapa_zrgz
Ahora que tenemos este mapa necesitamos que Python lea los datos que queremos que en él represente. La librería que puede hacer esto es Pandas. Auqnue tengamos la librería instalada e importada, aún no vemos en este archivo los datos. Tenemos que pedir a Python que con la librería Pandas nos lea los datos. Para ello creamos un dataframe (df_zrgz) que será el resultado (esto lo indicamos con =) de leer el documento al que lo hemos vinculado. Esto último lo hace con la función .read_
tipodocumento. En este caso vamos a indicarle que es un documento .csv aunque los datos no lo sean, porque de esta forma le decimos a Python que cada dato está delimitado por ;
. Al indicarle eso también haremos que el propio Python genere un archivo csv (como podemos comprobar en la interfaz de nuestro servidor) a partir de los datos de la api.
Una vez indicado el tipo de archivo, corresponde en la sintaxis introducir la referencia del mismo. En nuestro caso es la base de datos, pero no es necesario copiar su link ya que anteriormente la hemos definido como variable, por lo que le damos la referencia (url_zrgz). Por último, le especificamos que introduzca los datos delimitados: pd.read_csv(url_zrgz,delimiter=';')
.
NOTA: Un delimitador es una secuencia de uno o más caracteres para especificar el límite entre regiones separadas e independientes en flujos de datos. Así logramos que presente los datos, que no son tabulados, en categorías.
df_zrgz = pd.read_csv(url_zrgz,delimiter=';')
df_zrgz
Una vez tenemos el dataframe creado lo exploramos con distintas funciones. En primer lugar, .info
para saber qué contiene el dataframe.
df_zrgz.info
Esto es un resumen de los datos de la tabla. .info
nos informa sobre el conjunto de datos que estamos tratando. Estos son sobre la naturaleza de una serie de accidentes de tráfico: año, motivo, dirección... A continuación queremos conocer la razón de cada accidente de tráfico, para lo que ponemos ['reason]
detrás de df_zrgz. No lleva .
porque no se trata de una función sobre los datos sino una forma de visualización diferente en la que nosotros pedimos el dato que queremos que nos muestre. La sisntaxis es df['categoría']
, en este caso el motivo del accidente.
df_zrgz['reason']
Si queremos ver el conjunto de los datos (en este caso razones de los dintintos accidentes) sin una distinción por filas o el número de cada uno de los accidentes recogidos en la base de datos utilizamos la función unique()
.
df_zrgz['reason'].unique()
La función .unique()
sirve para delimitar los valores únicos en columnas. Es decir, las razones (categoría reason que elegimos visualizar antes) de los motivos del accidente que no se repiten en este conjunto de datos. Con la sintaxis descrita anteriormente cambiamos la categoría que queremos que nos muestre para acercarnos más a los datos e ir extrayendo toda su información.
df_zrgz['type'].unique()
Tras explorar los datos los representamos en el mapa.
Pedimos que nos enseñe los datos de las coordenadas geográficas a representar en el mapa que son los que se encuentran en la categoría geometry.
df_zrgz['geometry']
Le pedimos que nos enseñe el nombre de dichas coordenadas para tenerlas a mano para poder escribir su nombre en el mapa. La categoría es firstAddress. Añado la función .unique()
para acortar su extensión. Esto no podía realizarlo en la función anterior porque trabajaba con números y era necesaria la distinción por líneas de cada una de las coordenadas para poder diferenciarlas. Pero ahora puedo prescindir de ello ya que trabajo con texto.
df_zrgz['firstAddress'].unique()
Creamos un mapa (m) a partir del anterior al que añadimos marcardores con las coordenadas y nombres de las calles correspondientes utilizando la función folium.Marquer
.
La sintaxis de la función folium.map
es la siguiente:
location=
coordenadas de referencia,
zoom_start=
número pertinente al caso,
tiles=
estilo de mapa que queramos). En este caso he borrado esta opción ya que tras probar distintos estilos como 'Stamen Terrain' o 'Stamen Toner' he preferido el que viene definido en Folium y por tanto no necesita ser espedificado.
La sintaxis de folium.Marker
, que forma parte de nuestro nuevo mapa "m", es la siguiente:
([*coordenadas],
popup=
nombre de la calle,
tooltip=
lo que quiera que se vea al posicionar el cursor en el marcador)
Puedo definir esta variable con antelación para dejarla preestablecida si quiero poner en todas las localizaciones la misma etiqueta; 'accidente' en este caso. La sintaxis entonces es para todos los marcadores tooltip=tooltip)
.add_to(m)
para añadir los cambios al nuevo mapa resultante. Lo he llevado a cabo con las dos primeras coordenadas como ejemplo pero el proceso es el mismo para todas.
m=folium.Map(location=geo_zrgz,zoom_start=13)
tooltip='Accidente'
folium.Marker([-0.8818527060979306,41.649027473051156], popup='Calle Joaquín Costa', tooltip=tooltip).add_to(m)
folium.Marker([-0.8645810716721081,41.661585829868585], popup='Calle Marqués de la Cadena', tooltip=tooltip).add_to(m)
m
Vemos así los puntos de los accidentes marcados en el mapa.