Jupyter Notebook en acción

Gracias a Martín Nadal conocí esta capacidad de Jupyter de conectar con una API y trabajar el tratamiento de datos con Pandas, una forma de consumir y analizar en tiempo real el contenido de la API.

Accidentes en tráfico en Zaragoza

¿Qué vamos a hacer?

  • obtener los datos
  • transformar el campo coordenadas
  • construir un tabla con motivo del accidente, latitud y longitud

Origen de datos

https://www.zaragoza.es/sede/servicio/catalogo/1500#API

Se observa que:

  • El delimitador es el ;
  • Tiene dos parámetros, rows y start

Empieza el juego

Para ello primero instalamos Pandas y Folium:

pip install pandas folium
Requirement already satisfied: pandas in /home/flow/.local/pipx/venvs/jupyter/lib/python3.11/site-packages (2.0.1)
Requirement already satisfied: folium in /home/flow/.local/pipx/venvs/jupyter/lib/python3.11/site-packages (0.14.0)
Requirement already satisfied: python-dateutil>=2.8.2 in /home/flow/.local/pipx/venvs/jupyter/lib/python3.11/site-packages (from pandas) (2.8.2)
Requirement already satisfied: pytz>=2020.1 in /home/flow/.local/pipx/venvs/jupyter/lib/python3.11/site-packages (from pandas) (2023.3)
Requirement already satisfied: tzdata>=2022.1 in /home/flow/.local/pipx/venvs/jupyter/lib/python3.11/site-packages (from pandas) (2023.3)
Requirement already satisfied: numpy>=1.21.0 in /home/flow/.local/pipx/venvs/jupyter/lib/python3.11/site-packages (from pandas) (1.24.3)
Requirement already satisfied: branca>=0.6.0 in /home/flow/.local/pipx/venvs/jupyter/lib/python3.11/site-packages (from folium) (0.6.0)
Requirement already satisfied: jinja2>=2.9 in /home/flow/.local/pipx/venvs/jupyter/lib/python3.11/site-packages (from folium) (3.1.2)
Requirement already satisfied: requests in /home/flow/.local/pipx/venvs/jupyter/lib/python3.11/site-packages (from folium) (2.31.0)
Requirement already satisfied: MarkupSafe>=2.0 in /home/flow/.local/pipx/venvs/jupyter/lib/python3.11/site-packages (from jinja2>=2.9->folium) (2.1.2)
Requirement already satisfied: six>=1.5 in /home/flow/.local/pipx/venvs/jupyter/lib/python3.11/site-packages (from python-dateutil>=2.8.2->pandas) (1.16.0)
Requirement already satisfied: charset-normalizer<4,>=2 in /home/flow/.local/pipx/venvs/jupyter/lib/python3.11/site-packages (from requests->folium) (3.2.0)
Requirement already satisfied: idna<4,>=2.5 in /home/flow/.local/pipx/venvs/jupyter/lib/python3.11/site-packages (from requests->folium) (3.4)
Requirement already satisfied: urllib3<3,>=1.21.1 in /home/flow/.local/pipx/venvs/jupyter/lib/python3.11/site-packages (from requests->folium) (2.0.4)
Requirement already satisfied: certifi>=2017.4.17 in /home/flow/.local/pipx/venvs/jupyter/lib/python3.11/site-packages (from requests->folium) (2023.7.22)

[notice] A new release of pip is available: 23.1 -> 23.2.1
[notice] To update, run: /home/flow/.local/pipx/venvs/jupyter/bin/python -m pip install --upgrade pip
Note: you may need to restart the kernel to use updated packages.

Luego importamos Pandas y Folium:

import pandas as pd
import folium

Crear variable

Las variables se asignan con el símbolo “=” y se redactará entrecomillado, ya que se trata de una cadena de caracteres.

url = 'https://www.zaragoza.es/sede/servicio/transporte/accidentalidad-trafico/accidente.csv?rows=100'

Para saber cual es el valor de esta variable, en caso de querer conocerlo, tendremos que introducir el termino “miurl” y este tendrá que marcar un resultado igual a la url propuesta.

url
'https://www.zaragoza.es/sede/servicio/transporte/accidentalidad-trafico/accidente.csv?rows=100'

Si colocamos “miurl” dentro de un parentesis precedido por el comando “type”, mostrará que se trata de una cadena de caracteres.

type(url)
str

A lo cual responde que es de tipo str, de string o cadena de caracteres, texto.

Empieza la magia de Pandas

Crear dataframe

La abreviatura que se emplea para los dataframe es “dl”. Existe una función “read_csv()” que lee el formato “csv”. Dentro del paréntesis indicaremos el valor de lo que queremos que lea, en este caso la url.

df = pd.read_csv(url,delimiter=';')
df

id year type accidentType firstAddress secondAddress geometry reason area creationDate daniosMateriales falloMecanico estadoPavimento tipoEstadoPavimento estadoAtmosfera tipoEstadoAtmosfera afectado vehiculo
0 https://www.zaragoza.es/sede/servicio/transpor... 2014 SALIDA CALZADA NaN COSTA, JOAQUIN PERAL, ISAAC -0.8818527060979306,41.649027473051156 PERDIDA del control por FALTA de ATENCIÓN NaN 2014-10-09T00:00:00Z True False BUEN ESTADO NaN BUEN ESTADO NaN NaN https://www.zaragoza.es/sede/servicio/transpor...
1 https://www.zaragoza.es/sede/servicio/transpor... 2014 COLISIÓN ALCANCE NaN CADENA(MARQUES DE LA) NaN -0.8645810716721081,41.661585829868585 DISTANCIA DE SEGURIDAD, no mantener 2560.0 2014-10-23T00:00:00Z False False BUEN ESTADO NaN BUEN ESTADO NaN https://www.zaragoza.es/sede/servicio/transpor... https://www.zaragoza.es/sede/servicio/transpor...
2 https://www.zaragoza.es/sede/servicio/transpor... 2014 COLISIÓN ALCANCE NaN GOMEZ AVELLANEDA, G. CASTRO, R. (POETA) -0.887776415002892,41.666992622958105 PERDIDA del control por FALTA de ATENCIÓN 2598.0 2014-10-23T00:00:00Z False False BUEN ESTADO NaN BUEN ESTADO NaN https://www.zaragoza.es/sede/servicio/transpor... https://www.zaragoza.es/sede/servicio/transpor...
3 https://www.zaragoza.es/sede/servicio/transpor... 2014 COLIS FRONTOLATERAL NaN MONZON GARCIA CONDOY, H. -0.8825260453930127,41.62957498750602 CEDA EL PASO, no respetar prioridad de paso 2555.0 2014-10-23T00:00:00Z False False BUEN ESTADO NaN BUEN ESTADO NaN https://www.zaragoza.es/sede/servicio/transpor... https://www.zaragoza.es/sede/servicio/transpor...
4 https://www.zaragoza.es/sede/servicio/transpor... 2014 SALIDA CALZADA NaN RIOJA NAVARRA, AVENIDA DE -0.908314757720389,41.6562121210704 PERDIDA del control por VELOCIDAD INADECUADA 2554.0 2014-10-24T00:00:00Z False False BUEN ESTADO NaN BUEN ESTADO NaN https://www.zaragoza.es/sede/servicio/transpor... https://www.zaragoza.es/sede/servicio/transpor...
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
95 https://www.zaragoza.es/sede/servicio/transpor... 2014 OTRAS NaN MIRAL, DOMINGO NaN -0.8990662796872798,41.63977012001253 PERDIDA del control por FALTA de ATENCIÓN NaN 2014-07-30T00:00:00Z True False BUEN ESTADO NaN BUEN ESTADO NaN NaN https://www.zaragoza.es/sede/servicio/transpor...
96 https://www.zaragoza.es/sede/servicio/transpor... 2014 COLISIÓN ALCANCE NaN BUÑUEL,LUIS (PARQUE DEL AGUA) NaN -0.9072756956226459,41.670910841846876 PERDIDA del control por FALTA de ATENCIÓN 2071.0 2014-07-31T00:00:00Z True False BUEN ESTADO NaN BUEN ESTADO NaN NaN https://www.zaragoza.es/sede/servicio/transpor...
97 https://www.zaragoza.es/sede/servicio/transpor... 2014 SALIDA CALZADA NaN ALBAR, MANUEL GL. ILUSTRACION, AV. DE LA -0.9226018969034585,41.62757051008441 PERDIDA del control por FALTA de ATENCIÓN 1969.0 2014-07-25T00:00:00Z False False BUEN ESTADO NaN BUEN ESTADO NaN https://www.zaragoza.es/sede/servicio/transpor... https://www.zaragoza.es/sede/servicio/transpor...
98 https://www.zaragoza.es/sede/servicio/transpor... 2014 COLIS FRONTOLATERAL NaN ECHEGARAY Y CABALLERO SAN VICENTE PAUL -0.8735234620830842,41.65507219335992 SEMÁFORO, no respetar prioridad de paso 1970.0 2014-07-26T00:00:00Z False False BUEN ESTADO NaN BUEN ESTADO NaN https://www.zaragoza.es/sede/servicio/transpor... https://www.zaragoza.es/sede/servicio/transpor...
99 https://www.zaragoza.es/sede/servicio/transpor... 2014 SALIDA CALZADA NaN CESAR AUGUSTO, AVDA NaN -0.8869504077778204,41.65022964156985 PERDIDA del control por FALTA de ATENCIÓN 1971.0 2014-07-09T00:00:00Z True False BUEN ESTADO NaN BUEN ESTADO NaN NaN https://www.zaragoza.es/sede/servicio/transpor...

100 rows × 18 columns

Aquí tenemos todos los datos pero mejor si lo evitamos, son 27000 accidentes y puede ir lento.

df = pd.read_csv('http://muimota.net/ojoaldato/accidentes.csv')
df

id year type accidentType firstAddress secondAddress geometry reason area creationDate daniosMateriales falloMecanico estadoPavimento tipoEstadoPavimento estadoAtmosfera tipoEstadoAtmosfera afectado vehiculo
0 https://www.zaragoza.es/sede/servicio/transpor... 2014 SALIDA CALZADA NaN COSTA, JOAQUIN PERAL, ISAAC -0.8818527060979306,41.649027473051156 PERDIDA del control por FALTA de ATENCIÓN NaN 2014-10-09T00:00:00Z True False BUEN ESTADO NaN BUEN ESTADO NaN NaN https://www.zaragoza.es/sede/servicio/transpor...
1 https://www.zaragoza.es/sede/servicio/transpor... 2014 COLISIÓN ALCANCE NaN CADENA(MARQUES DE LA) NaN -0.8645810716721081,41.661585829868585 DISTANCIA DE SEGURIDAD, no mantener 2560.0 2014-10-23T00:00:00Z False False BUEN ESTADO NaN BUEN ESTADO NaN https://www.zaragoza.es/sede/servicio/transpor... https://www.zaragoza.es/sede/servicio/transpor...
2 https://www.zaragoza.es/sede/servicio/transpor... 2014 COLISIÓN ALCANCE NaN GOMEZ AVELLANEDA, G. CASTRO, R. (POETA) -0.887776415002892,41.666992622958105 PERDIDA del control por FALTA de ATENCIÓN 2598.0 2014-10-23T00:00:00Z False False BUEN ESTADO NaN BUEN ESTADO NaN https://www.zaragoza.es/sede/servicio/transpor... https://www.zaragoza.es/sede/servicio/transpor...
3 https://www.zaragoza.es/sede/servicio/transpor... 2014 COLIS FRONTOLATERAL NaN MONZON GARCIA CONDOY, H. -0.8825260453930127,41.62957498750602 CEDA EL PASO, no respetar prioridad de paso 2555.0 2014-10-23T00:00:00Z False False BUEN ESTADO NaN BUEN ESTADO NaN https://www.zaragoza.es/sede/servicio/transpor... https://www.zaragoza.es/sede/servicio/transpor...
4 https://www.zaragoza.es/sede/servicio/transpor... 2014 SALIDA CALZADA NaN RIOJA NAVARRA, AVENIDA DE -0.908314757720389,41.6562121210704 PERDIDA del control por VELOCIDAD INADECUADA 2554.0 2014-10-24T00:00:00Z False False BUEN ESTADO NaN BUEN ESTADO NaN https://www.zaragoza.es/sede/servicio/transpor... https://www.zaragoza.es/sede/servicio/transpor...
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
27495 https://www.zaragoza.es/sede/servicio/transpor... 2019 COLISIÓN LATERAL NaN PLEYADES, LAS BOYERO -0.9337782877014544,41.63888841722081 INCORPORARSE sin las debidas precauciones 2512.0 2019-09-20T00:00:00Z False False BUEN ESTADO NaN BUEN ESTADO NaN https://www.zaragoza.es/sede/servicio/transpor... https://www.zaragoza.es/sede/servicio/transpor...
27496 https://www.zaragoza.es/sede/servicio/transpor... 2019 COLISIÓN LATERAL NaN UNIVERSITAS, VIA NaN -0.9067375759951974,41.644789184898926 INCORPORARSE sin las debidas precauciones 2513.0 2019-09-18T00:00:00Z True False BUEN ESTADO NaN BUEN ESTADO NaN NaN https://www.zaragoza.es/sede/servicio/transpor...
27497 https://www.zaragoza.es/sede/servicio/transpor... 2019 COLISIÓN LATERAL NaN CANOVAS, ANTONIO NaN -0.8907497377774148,41.64811436227578 INVADIR otro carril en el mismo sentido de cir... 2707.0 2019-09-21T00:00:00Z True False BUEN ESTADO NaN BUEN ESTADO NaN NaN https://www.zaragoza.es/sede/servicio/transpor...
27498 https://www.zaragoza.es/sede/servicio/transpor... 2019 SALIDA CALZADA NaN LEGAZ LACAMBRA, LUIS GOMEZ AVELLANEDA, G. -0.8908180267513072,41.676074625860785 PERDIDA del control por FALTA de ATENCIÓN 2572.0 2019-09-22T00:00:00Z True False BUEN ESTADO NaN BUEN ESTADO NaN NaN https://www.zaragoza.es/sede/servicio/transpor...
27499 https://www.zaragoza.es/sede/servicio/transpor... 2019 COLISIÓN LATERAL NaN RODRIGUEZ AYUSO, MANUEL BIEL -0.9245669583272559,41.645615385662296 INVADIR otro carril en el mismo sentido de cir... 2540.0 2019-09-20T00:00:00Z False False BUEN ESTADO NaN BUEN ESTADO NaN https://www.zaragoza.es/sede/servicio/transpor... https://www.zaragoza.es/sede/servicio/transpor...

27500 rows × 18 columns

Viendo estos datos a Martín le interesó explorar la columna reason y saber qué valores únicos había:

df['reason'].unique()
array(['PERDIDA del control por FALTA de ATENCIÓN',
       'DISTANCIA DE SEGURIDAD, no mantener',
       'CEDA EL PASO, no respetar prioridad de paso',
       'PERDIDA del control por VELOCIDAD INADECUADA',
       'Caída de ocupante en Transporte Público',
       'PEATÓN cruza calz SIN PREFER. fuera de paso',
       'INVADIR otro carril en el mismo sentido de circulación',
       'PEATÓN cruza calz SIN PREFER. en PASO CON semáforo',
       'PUERTA abierta incorrectamente', 'MARCHA ATRÁS',
       'SEMÁFORO, no respetar prioridad de paso', 'OTRAS CAUSAS',
       'PEATÓN cruza calz CON PREFER. en PASO  CON semáforo',
       'PEATÓN cruza calz CON PREFER. en PASO  SIN semáforo',
       'PEATÓN cruza calz CON PREFER. en PASO SIN semáforo',
       'INCORPORARSE sin las debidas precauciones',
       'GIROS: no respetar señal ó no ceñirse a la dirección',
       'PEATÓN cruza calz CON PREFER. en PASO CON semáforo',
       'Infracción Penal (con denuncia)',
       'PEATÓN atropellado sobre la acera ó refugio',
       'PEATÓN cruza calz SIN PREFER. en PASO  CON semáforo',
       'STOP, no respetar prioridad de paso',
       'SIN PODER DETERMINAR,  faltan datos',
       'INVADIR otro carril en sentido contrario a la circulación',
       'PREFERENCIA EN GLORIETA, no respetar',
       'PEATÓN cruza calz CON PREFER. fuera de PASO (esquina)',
       'DIRECCIÓN CONTRARIA, circular en',
       'SIN PODER DETERMINAR, faltan datos',
       'ESTACIONADO INCORRECTAMENTE',
       'PREFERENCIA A LA  DERECHA, no respetar',
       'PREFERENCIA A LA DERECHA, no respetar',
       'ADELANTAMIENTO incorrecto', 'Daños propiedad', 'Otras causas',
       'INCORPORARSE un BUS URBANO a la circulac. desde parada señaliz.',
       'CAIDA DE PEATÓN EN AUTOBUS', 'Daños (Propiedad)', nan,
       'INCORPORARSE sin las debidas precauciones)',
       'PEATÓN cruza calz  fuera de PASO (esquina)',
       'Infracción Penal (sin denuncia)'], dtype=object)

Ademá, se propuso ver si podía utilizar el valor de la columna geometry:

df['geometry']
0        -0.8818527060979306,41.649027473051156
1        -0.8645810716721081,41.661585829868585
2         -0.887776415002892,41.666992622958105
3         -0.8825260453930127,41.62957498750602
4           -0.908314757720389,41.6562121210704
                          ...                  
27495     -0.9337782877014544,41.63888841722081
27496    -0.9067375759951974,41.644789184898926
27497     -0.8907497377774148,41.64811436227578
27498    -0.8908180267513072,41.676074625860785
27499    -0.9245669583272559,41.645615385662296
Name: geometry, Length: 27500, dtype: object

Resulta que era un objeto de tipo cadena, que contenía las dos coordenadas y, además, que estaban invertidas en el orden. Había que convertirlo. Primero las longitudes y luego las latitudes:

longitudes = []
for coordenadasStr in df['geometry']:
    pointStr = coordenadasStr.split(',')
    longitudes += [float(pointStr[0])]
latitudes = []
for coordenadasStr in df['geometry']:
    pointStr = coordenadasStr.split(',')
    latitudes += [float(pointStr[1])]

Con esto crea un dataframe concreto:

coordenadas = pd.DataFrame({'long':longitudes,'lat':latitudes})
coordenadas

long lat
0 -0.881853 41.649027
1 -0.864581 41.661586
2 -0.887776 41.666993
3 -0.882526 41.629575
4 -0.908315 41.656212
... ... ...
27495 -0.933778 41.638888
27496 -0.906738 41.644789
27497 -0.890750 41.648114
27498 -0.890818 41.676075
27499 -0.924567 41.645615

27500 rows × 2 columns

Y se crea otro dataframe de la unión de la columna type y del dataframe coordenadas:

accidentes = pd.concat([df['type'],coordenadas],axis=1)
accidentes

type long lat
0 SALIDA CALZADA -0.881853 41.649027
1 COLISIÓN ALCANCE -0.864581 41.661586
2 COLISIÓN ALCANCE -0.887776 41.666993
3 COLIS FRONTOLATERAL -0.882526 41.629575
4 SALIDA CALZADA -0.908315 41.656212
... ... ... ...
27495 COLISIÓN LATERAL -0.933778 41.638888
27496 COLISIÓN LATERAL -0.906738 41.644789
27497 COLISIÓN LATERAL -0.890750 41.648114
27498 SALIDA CALZADA -0.890818 41.676075
27499 COLISIÓN LATERAL -0.924567 41.645615

27500 rows × 3 columns

Crea el mapa con Folium

mapa = folium.Map(location=[41.64,-0.88])
mapa
Make this Notebook Trusted to load map: File -> Trust Notebook

De la misma forma que se crea un marcador child se crea un bucle para añadir todos los marcadores con las correspondientes coordenadas y textos:

for indice, fila in accidentes.iterrows():
    marcador = folium.Marker([fila['lat'],fila['long']],\
                             popup=fila['type'])
    mapa.add_child(marcador)
mapa
Make this Notebook Trusted to load map: File -> Trust Notebook