El Ayuntamiento de París ha decidido dar por finalizada la concesión de uso del espacio público a los operadores de VMPs compartidos a partir del 1 de septiembre de 2023, una decisión tomada tras una consulta popular celebrada en abril en la que cerca del 90% de los participantes votó a favor de esta medida. Sorprendido por esta noticia he querido comprobar la situación en la ciudad de Barcelona. Será un análisis exploratorio sencillo en el que comprobaré la accidentabilidad de VMPs (sin distinguir entre eléctricos y no eléctricos) y la incidencia de estos accidentes en los peatones. Para ello usaré los datos de la Guàrdia Urbana del año 2022 publicados en el portal de Open Data del Ajuntament de Barcelona.
El objetivo de este proyecto es obtener una imagen superficial que permita dar una idea de esta situación en Barcelona. De entrada se va a comprobar cuántos de los accidentes reportados el año 2022 tienen, al menos, un VMP implicado y, de todos estos, en cuántos se ha causado lesiones a un peatón. Se va a comprobar a qué horas se producen estos accidentes en función del día de la semana, y se va a comprobar también la incidencia por barrio. Finalmente se va a visualizar en un mapa los accidentes con VMPs implicados en la ciudad, distinguiendo aquellos en que hay por lo menos un peatón lesionado y la responsabilidad o no del peatón en la colisión.
En cuanto a la presentación de los resultados se ha decidido visualizar la información en la herramienta flourish, por tanto se van a crear los ficheros csv adecuados para exportar la información necesaria y poderla mostrar.
En esta primera parte se presenta la limpieza y adecuación de los datos originales para llevar a cabo el análisis deseado, que es la parte II de este proyecto.
# Carga de las librerias necesarias
import pandas as pd
import matplotlib.pyplot as plt
La información de la accidentabilidad en la ciudad de Barcelona, según los expedientes de la Guàrdia Urbana, se facilita a través del portal de Open Data en 5 ficheros CSV diferentes. Se publican los datos correspondientes a cada año en ficheros separados, para este análisis solo se tendrán en cuenta los datos correspondientes al año 2022. https://opendata-ajuntament.barcelona.cat/data/es/organization/seguretat
Se decide recoger la información necesaria para el análisis a llevar a cabo en un único dataframe, exportándola a un fichero CSV master que permita la lectura directa sin tener que ejecutar de nuevo este script (notebook) para adecuarla.
La información general de cada accidente, incluida en cada uno de los cinco ficheros proporcionados, que se incluirá en el fichero master es: número de expediente, código de distrito, código de barrio, fecha y hora, y coordenadas geográficas (longitud y latitud).
A parte de la información general de cada accidente reportado se decide incluir el número de VMPs implicados, el número de bicicletas, el número de otros vehículos, el número de conductores, pasajeros y peatones lesionados, así como si el accidente ha sido causado por el peatón y la ubicación del mismo en el momento del accidente. Se ha decidido incluir las bicicletas para poder aprovechar el fichero master creado en este script en un futuro análisis análogo para este tipo de vehículo.
Respecto a la información de los distritos y barrios de Barcelona, se decide incluir en el CSV master únicamente los códigos. Se crearán dos ficheros auxiliares con las etiquetas de cada una de las divisiones administrativas de la ciudad correspondientes a cada código, para evitar incluir información redundante en el proceso de análisis que pudiera añadir complejidad computacional.
En este paso se extraerá la información general de los accidentes reportados, común a los cinco ficheros originales, y se crearán los ficheros CSV auxiliares con los nombres de los distritos y barrios de Barcelona asociados a su código. Esta información se extraerá del fichero 2022_accidents_gu_bcn.csv.
accs_df = pd.read_csv("raw_data/2022_accidents_gu_bcn.csv")
print(accs_df.head())
Numero_expedient Codi_districte Nom_districte Codi_barri Nom_barri \ 0 2022S007749 -1 Desconegut -1 Desconegut 1 2022S003422 -1 Desconegut -1 Desconegut 2 2022S003346 -1 Desconegut -1 Desconegut 3 2022S006073 -1 Desconegut -1 Desconegut 4 2022S005123 -1 Desconegut -1 Desconegut Codi_carrer Nom_carrer \ 0 -1 Fernando Pessoa ... 1 -1 Bac de Roda / Ramon Turró ... 2 -1 Viladrosa ... 3 -1 A Zona Franca / Número 3 Zona Franca ... 4 -1 Carles Pi i Sunyer ... Num_postal_caption Descripcio_dia_setmana NK_Any ... \ 0 17 Dilluns 2022 ... 1 Desconegut Dissabte 2022 ... 2 97-103 Dimecres 2022 ... 3 Desconegut Dissabte 2022 ... 4 10 Divendres 2022 ... Descripcio_causa_vianant Numero_morts Numero_lesionats_lleus \ 0 No és causa del vianant 0 1 1 No és causa del vianant 0 2 2 No és causa del vianant 0 1 3 No és causa del vianant 0 0 4 No és causa del vianant 0 1 Numero_lesionats_greus Numero_victimes Numero_vehicles_implicats \ 0 0 1 2 1 0 2 2 2 0 1 2 3 0 0 1 4 0 1 2 Coordenada_UTM_X_ED50 Coordenada_UTM_Y_ED50 Longitud Latitud 0 432684.59 4588039.29 2.193098 41.439261 1 433936.91 4584121.59 2.208515 41.404080 2 431308.23 4588533.51 2.176568 41.443596 3 428020.43 4576283.26 2.138671 41.332974 4 431029.88 4582053.59 2.173975 41.385209 [5 rows x 25 columns]
Extracción de los nombres y códigos de los barrios y distritos de la ciudad de Barcelona y exportación a los ficheros CSV auxiliares.
#print(accs_df.groupby('Codi_districte').first())
#print(accs_df.groupby('Codi_districte')['Nom_districte'])
#print(accs_df.groupby('Codi_districte')['Nom_districte'].first())
#print(accs_df.groupby(['Codi_districte','Codi_barri'])['Nom_districte','Nom_barri'].first())
#print(accs_df.groupby(['Codi_districte','Codi_barri'])['Nom_districte','Nom_barri'].first().reset_index())
#rename(columns={"index":"date",})
accs_df.groupby(['Codi_districte','Codi_barri'])['Nom_districte','Nom_barri'].first()\
.reset_index().to_csv('clean_data/bcn_barris.csv', index=False)
accs_df.groupby(['Codi_districte'])['Nom_districte'].first()\
.reset_index().to_csv('clean_data/bcn_districtes.csv', index=False)
/tmp/ipykernel_11220/3819481415.py:9: FutureWarning: Indexing with multiple keys (implicitly converted to a tuple of keys) will be deprecated, use a list instead. accs_df.groupby(['Codi_districte','Codi_barri'])['Nom_districte','Nom_barri'].first()\
Extracción y transformaciones necesarias de la información general de interés de los accidentes reportados.
# Seleccion de los campos comunes de interés en el dataframe leido
keep_feats = ["Numero_expedient","Codi_districte","Codi_barri",
"NK_Any","Mes_any","Dia_mes","Hora_dia",
"Longitud","Latitud"]
accs_df = accs_df[keep_feats]
print(accs_df.head())
Numero_expedient Codi_districte Codi_barri NK_Any Mes_any Dia_mes \ 0 2022S007749 -1 -1 2022 12 19 1 2022S003422 -1 -1 2022 6 4 2 2022S003346 -1 -1 2022 6 1 3 2022S006073 -1 -1 2022 10 8 4 2022S005123 -1 -1 2022 8 26 Hora_dia Longitud Latitud 0 11 2.193098 41.439261 1 14 2.208515 41.404080 2 21 2.176568 41.443596 3 21 2.138671 41.332974 4 16 2.173975 41.385209
# Creacion del campo Dia_Hora (datetime) a partir de NK_Any, Mes_any, Dia_mes, Hora_dia
accs_df["Dia_Hora"] = pd.to_datetime(accs_df["NK_Any"].apply(str) +\
accs_df["Mes_any"].apply(lambda x: '{0:0>2}'.format(x)) +\
accs_df["Dia_mes"].apply(lambda x: '{0:0>2}'.format(x)) +\
accs_df["Hora_dia"].apply(lambda x: '{0:0>2}'.format(x)),
format='%Y%m%d%H')
print(accs_df.head())
Numero_expedient Codi_districte Codi_barri NK_Any Mes_any Dia_mes \ 0 2022S007749 -1 -1 2022 12 19 1 2022S003422 -1 -1 2022 6 4 2 2022S003346 -1 -1 2022 6 1 3 2022S006073 -1 -1 2022 10 8 4 2022S005123 -1 -1 2022 8 26 Hora_dia Longitud Latitud Dia_Hora 0 11 2.193098 41.439261 2022-12-19 11:00:00 1 14 2.208515 41.404080 2022-06-04 14:00:00 2 21 2.176568 41.443596 2022-06-01 21:00:00 3 21 2.138671 41.332974 2022-10-08 21:00:00 4 16 2.173975 41.385209 2022-08-26 16:00:00
# Eliminacion de los campos redundantes y obtencion del csv con la informacion comun
keep_feats = ["Numero_expedient","Codi_districte","Codi_barri",
"Dia_Hora","Latitud","Longitud"]
accs_df = accs_df[keep_feats]
accs_df.to_csv('clean_data/common_info.csv', index=False)
print(accs_df.head())
Numero_expedient Codi_districte Codi_barri Dia_Hora Latitud \ 0 2022S007749 -1 -1 2022-12-19 11:00:00 41.439261 1 2022S003422 -1 -1 2022-06-04 14:00:00 41.404080 2 2022S003346 -1 -1 2022-06-01 21:00:00 41.443596 3 2022S006073 -1 -1 2022-10-08 21:00:00 41.332974 4 2022S005123 -1 -1 2022-08-26 16:00:00 41.385209 Longitud 0 2.193098 1 2.208515 2 2.176568 3 2.138671 4 2.173975
En este paso se hará el recuento del tipo de vehículos implicados y del tipo de persona lesionados en cada uno de los accidentes reportados. En el caso de haber algún peatón implicado, se extraerá la información sobre la responsabilidad del peatón y su ubicación en el momento del atropello.
A efectos de este análisis, solo se considerarán tres categorías de vehículos: VMP (patinetes), bicicletas y resto de vehículos (otros). En este análiis solo se tiene interés en la accientabilidad de VMPs y su afectación en peatones, sin entrar en el detalle del resto de vehículos. Se extraerá la información del número de bicicletas implicadas para permitir el uso del mismo fichero master en futuros análisis de accidentabilidad de este tipo de vehículo.
accs_veh_df = pd.read_csv("raw_data/2022_accidents_vehicles_gu_bcn.csv")
print(accs_veh_df.head())
Numero_expedient Codi_districte Nom_districte Codi_barri Nom_barri \
0 2022S000792 -1 Desconegut -1 Desconegut
1 2022S000792 -1 Desconegut -1 Desconegut
2 2022S001565 -1 Desconegut -1 Desconegut
3 2022S001565 -1 Desconegut -1 Desconegut
4 2022S001568 -1 Desconegut -1 Desconegut
Codi_carrer Nom_carrer Num_postal \
0 -1 Elisabeth Eidenbenz ... 8-24
1 -1 Elisabeth Eidenbenz ... NaN
2 -1 Sant Cugat ... 49-55
3 -1 Sant Cugat ... NaN
4 -1 Pallars ... 279-285
Descripcio_dia_setmana NK_Any ... Descripcio_tipus_vehicle \
0 Dijous 2022 ... Taxi
1 Dijous 2022 ... Turisme
2 Dijous 2022 ... Bicicleta
3 Dijous 2022 ... Bicicleta
4 Dijous 2022 ... Motocicleta
Descripcio_model Descripcio_marca Descripcio_color Descripcio_carnet \
0 TOYOTA PRIUS PLUS TOYOTA Negre/Groc B
1 LEON ST SEAT Gris B
2 Desconegut Desconegut Negre B
3 Desconegut Desconegut Vermell A
4 JET 14 SYM Blau B
Antiguitat_carnet Coordenada_UTM_X_ED50 Coordenada_UTM_Y_ED50 Longitud \
0 20 426794.73 4581925.76 2.123343
1 23 426794.73 4581925.76 2.123343
2 17 426417.43 4586500.99 2.118274
3 2 426417.43 4586500.99 2.118274
4 10 433391.56 4584170.99 2.201986
Latitud
0 41.383684
1 41.383684
2 41.424856
3 41.424856
4 41.404479
[5 rows x 26 columns]
keep_feats = ["Numero_expedient","Descripcio_tipus_vehicle"]
accs_veh_df = accs_veh_df[keep_feats]
print(accs_veh_df.head())
Numero_expedient Descripcio_tipus_vehicle 0 2022S000792 Taxi 1 2022S000792 Turisme 2 2022S001565 Bicicleta 3 2022S001565 Bicicleta 4 2022S001568 Motocicleta
# Simplificar les categories de vehicles a tres: VMP, Bicicleta, Altres
# Categorías / Valores existentes en la variable Descripcio_tipus_vehicle
accs_veh_df.Descripcio_tipus_vehicle.unique()
array(['Taxi', 'Turisme', 'Bicicleta', 'Motocicleta', 'Furgoneta',
'Camió rígid > 3,5 tones', 'Veh. mobilitat personal amb motor',
'Tot terreny', 'Altres vehicles amb motor', 'Tractor camió',
'Ciclomotor', 'Autobús', 'Camió rígid <= 3,5 tones',
'Quadricicle < 75 cc', 'Autobús articulat', 'Desconegut',
"Maquinària d'obres i serveis",
'Veh. mobilitat personal sense motor', 'Ambulància', 'Autocar',
nan, 'Pick-up', 'Tricicle', 'Tren o tramvia', 'Autocaravana',
'Quadricicle > 75 cc', 'Altres vehicles sense motor'], dtype=object)
Conversión de categorias para la variable Descripcio_tipus_vehicle:
A efectos del análisis a realizar se van a considerar de la misma manera los vehículos de movilidad personal con motor o sin motor.
# Creación de un nuevo atributo 'TipusVeh' con la categorizacion simplificada
accs_veh_df["TipusVeh"] = "Otros_veh"
accs_veh_df.loc[ accs_veh_df["Descripcio_tipus_vehicle"] == "Bicicleta", "TipusVeh"] = "Bicicleta"
accs_veh_df.loc[ accs_veh_df["Descripcio_tipus_vehicle"] == "Veh. mobilitat personal amb motor", "TipusVeh"] = "VMP"
accs_veh_df.loc[ accs_veh_df["Descripcio_tipus_vehicle"] == "Veh. mobilitat personal sense motor", "TipusVeh"] = "VMP"
print(accs_veh_df.head())
Numero_expedient Descripcio_tipus_vehicle TipusVeh 0 2022S000792 Taxi Otros_veh 1 2022S000792 Turisme Otros_veh 2 2022S001565 Bicicleta Bicicleta 3 2022S001565 Bicicleta Bicicleta 4 2022S001568 Motocicleta Otros_veh
accs_veh_df = accs_veh_df[["Numero_expedient","TipusVeh"]]
accs_veh_dummies = pd.get_dummies(accs_veh_df, columns=["TipusVeh"])
print(accs_veh_dummies.head())
Numero_expedient TipusVeh_Bicicleta TipusVeh_Otros_veh TipusVeh_VMP 0 2022S000792 0 1 0 1 2022S000792 0 1 0 2 2022S001565 1 0 0 3 2022S001565 1 0 0 4 2022S001568 0 1 0
accs_veh_dummies = accs_veh_dummies.groupby(['Numero_expedient']).sum().reset_index()
print(accs_veh_dummies.head())
Numero_expedient TipusVeh_Bicicleta TipusVeh_Otros_veh TipusVeh_VMP 0 2022S000001 0 2 0 1 2022S000002 0 2 0 2 2022S000003 2 0 0 3 2022S000004 0 2 0 4 2022S000005 0 2 0
En el caso de los tipos de persona lesionadas en cada accidente se considerarán las tres categorías establecidas en los expedientes de la GUB: Conductor, pasajero (passatger) y peatón (vianant)
Dado que tan solo se tendrán en cuenta las consecuencias para los peatones, en el caso de conductores y pasajeros no se tendrá en cuenta el vehículo en el que circulaban.
accs_pers_df = pd.read_csv("raw_data/2022_accidents_persones_gu_bcn.csv")
print(accs_pers_df.head())
Numero_expedient Codi_districte Nom_districte Codi_barri \
0 2022S000001 2 Eixample 9
1 2022S000002 2 Eixample 7
2 2022S000003 2 Eixample 9
3 2022S000003 2 Eixample 9
4 2022S000004 7 Horta-Guinardó 33
Nom_barri Codi_carrer Nom_carrer Num_postal \
0 la Nova Esquerra de l'Eixample 110803 Entença 0198B0198B
1 la Dreta de l'Eixample 289105 Rosselló 0294B0294B
2 la Nova Esquerra de l'Eixample 268003 Provença 0092 0094
3 la Nova Esquerra de l'Eixample 268003 Provença 0092 0094
4 el Baix Guinardó 152905 Guinardó 0030B0030B
Descripcio_dia_setmana NK_ Any ... Edat Descripcio_tipus_persona \
0 Dissabte 2022 ... 31 Conductor
1 Dissabte 2022 ... 26 Conductor
2 Dissabte 2022 ... 31 Conductor
3 Dissabte 2022 ... 38 Conductor
4 Dissabte 2022 ... 37 Conductor
Descripcio_Lloc_atropellament_vianant \
0 Desconegut ...
1 Desconegut ...
2 Desconegut ...
3 Desconegut ...
4 Desconegut ...
Descripcio_Motiu_desplaçament_vianant \
0 Desconegut
1 Desconegut
2 Desconegut
3 Desconegut
4 Desconegut
Descripcio_Motiu_desplaçament_conductor \
0 Oci i entreteniment
1 Oci i entreteniment
2 Es desconeix
3 Es desconeix
4 Oci i entreteniment
Descripcio_victimitzacio Coordenada_UTM_X_ED50 \
0 Ferit lleu: Amb assistència sanitària en lloc ... 428502.72
1 Ferit lleu: Hospitalització fins a 24h 430409.20
2 Ferit lleu: Hospitalització fins a 24h 428869.16
3 Ferit lleu: Amb assistència sanitària en lloc ... 428869.16
4 Ferit lleu: Hospitalització fins a 24h 430243.82
Coordenada_UTM_Y_ED50 Longitud Latitud
0 4582056.71 2.144854 41.386863
1 4583691.07 2.167466 41.401750
2 4582000.36 2.149243 41.386388
3 4582000.36 2.149243 41.386388
4 4584996.80 2.165337 41.413496
[5 rows x 28 columns]
accs_pers_df = accs_pers_df[["Numero_expedient","Descripcio_tipus_persona"]]
# Categorías / Valores existentes en la variable Descripcio_tipus_persona
accs_pers_df.Descripcio_tipus_persona.unique()
array(['Conductor', 'Passatger', 'Vianant'], dtype=object)
# Renombrar la columna a 'Pers'
accs_pers_df = accs_pers_df.rename(columns={"Descripcio_tipus_persona": "Pers"})
print(accs_pers_df.head())
Numero_expedient Pers 0 2022S000001 Conductor 1 2022S000002 Conductor 2 2022S000003 Conductor 3 2022S000003 Conductor 4 2022S000004 Conductor
accs_pers_dummies = pd.get_dummies(accs_pers_df, columns=["Pers"]).\
groupby(['Numero_expedient']).sum().reset_index()
print(accs_pers_dummies.head())
Numero_expedient Pers_Conductor Pers_Passatger Pers_Vianant 0 2022S000001 1 0 0 1 2022S000002 1 0 0 2 2022S000003 2 0 0 3 2022S000004 1 0 0 4 2022S000007 1 0 0
En este paso se extraerá la información de la responsabilidad del peatón en el accidente, así como su ubicación en el momento de la colisión.
accs_vian_df = pd.read_csv("raw_data/2022_accidents_persones_gu_bcn.csv")
accs_vian_df = accs_vian_df[["Numero_expedient","Descripcio_causa_vianant","Descripcio_Lloc_atropellament_vianant"]]
print(accs_vian_df.head())
Numero_expedient Descripcio_causa_vianant \
0 2022S000001 No és causa del vianant
1 2022S000002 No és causa del vianant
2 2022S000003 No és causa del vianant
3 2022S000003 No és causa del vianant
4 2022S000004 No és causa del vianant
Descripcio_Lloc_atropellament_vianant
0 Desconegut ...
1 Desconegut ...
2 Desconegut ...
3 Desconegut ...
4 Desconegut ...
# Agrupacion de expedientes por ID, para obtener una unica fila por expediente
accs_vian_df = accs_vian_df.groupby(['Numero_expedient']).first().reset_index()
print(accs_vian_df.Descripcio_causa_vianant.unique())
print(accs_vian_df.Descripcio_Lloc_atropellament_vianant.unique())
['No és causa del vianant' 'Creuar per fora pas de vianants' 'Desobeir el senyal del semàfor' 'Altres' 'Transitar a peu per la calçada'] ['Desconegut ' 'En zona peatonal ' 'Fora del pas ' 'En pas regulat per semàfor ' 'En pas sense regular ' 'A la vorera / Andana ' 'Altres ' 'En pas sense senyalitzar ']
# Eliminar los espacios en blanco finales del atributo 'Descripcio_Lloc_atropellament_vianant'
accs_vian_df['Descripcio_Lloc_atropellament_vianant'] = accs_vian_df['Descripcio_Lloc_atropellament_vianant'].\
str.strip()
# Establecer si el peaton es responsable del atropello o no
accs_vian_df.loc[accs_vian_df["Descripcio_causa_vianant"] != "No és causa del vianant", "Descripcio_causa_vianant"] = "Sí"
accs_vian_df.loc[accs_vian_df["Descripcio_causa_vianant"] == "No és causa del vianant", "Descripcio_causa_vianant"] = "No"
# Renombrar el atributo a 'Es_causa_peaton'
accs_vian_df = accs_vian_df.rename(columns={"Descripcio_causa_vianant": "Es_causa_peaton"})
print(accs_vian_df.head())
Numero_expedient Es_causa_peaton Descripcio_Lloc_atropellament_vianant 0 2022S000001 No Desconegut 1 2022S000002 No Desconegut 2 2022S000003 No Desconegut 3 2022S000004 No Desconegut 4 2022S000007 No Desconegut
Conversión de categorias para la variable Descripcio_Lloc_atropellament_vianant:
A efectos del análisis a realizar se van a considerar como zonas peatonales tanto las zonas peatonalizadas como aceras y andenes. Se mantiene la distinción original entre los distintos tipos de paso.
# Establecer la ubicacion del peaton en el momento de la colision
accs_vian_df.loc[accs_vian_df["Descripcio_Lloc_atropellament_vianant"] == "Desconegut", "Descripcio_Lloc_atropellament_vianant"] = "Desconocido"
accs_vian_df.loc[accs_vian_df["Descripcio_Lloc_atropellament_vianant"] == "En zona peatonal", "Descripcio_Lloc_atropellament_vianant"] = "Zona Peatonal"
accs_vian_df.loc[accs_vian_df["Descripcio_Lloc_atropellament_vianant"] == "Fora del pas", "Descripcio_Lloc_atropellament_vianant"] = "Fuera del Paso"
accs_vian_df.loc[accs_vian_df["Descripcio_Lloc_atropellament_vianant"] == "En pas regulat per semàfor", "Descripcio_Lloc_atropellament_vianant"] = "Paso Regulado"
accs_vian_df.loc[accs_vian_df["Descripcio_Lloc_atropellament_vianant"] == "En pas sense regular", "Descripcio_Lloc_atropellament_vianant"] = "Paso No Regulado"
accs_vian_df.loc[accs_vian_df["Descripcio_Lloc_atropellament_vianant"] == "A la vorera / Andana", "Descripcio_Lloc_atropellament_vianant"] = "Zona Peatonal"
accs_vian_df.loc[accs_vian_df["Descripcio_Lloc_atropellament_vianant"] == "Altres", "Descripcio_Lloc_atropellament_vianant"] = "Otras"
accs_vian_df.loc[accs_vian_df["Descripcio_Lloc_atropellament_vianant"] == "En pas sense senyalitzar", "Descripcio_Lloc_atropellament_vianant"] = "Paso Sin Señalizar"
# Renombrar el atributo a 'Ubicacion_peaton'
accs_vian_df = accs_vian_df.rename(columns={"Descripcio_Lloc_atropellament_vianant": "Ubicacion_peaton"})
print(accs_vian_df.head())
Numero_expedient Es_causa_peaton Ubicacion_peaton 0 2022S000001 No Desconocido 1 2022S000002 No Desconocido 2 2022S000003 No Desconocido 3 2022S000004 No Desconocido 4 2022S000007 No Desconocido
En este paso se unen mediante una operación merge (similar a un join) los dataframes con la información adicional obtenida en el paso 4 con el dataframe con la información general extraída en el paso 3 de cada accidente reportado, con la finalidad de obtener el fichero csv master que se usará en el análisis.
accs_bcn_df = pd.merge(accs_df, accs_veh_dummies, how="left", on="Numero_expedient")
accs_bcn_df = pd.merge(accs_bcn_df, accs_pers_dummies, how="left", on="Numero_expedient")
accs_bcn_df = pd.merge(accs_bcn_df, accs_vian_df, how="left", on="Numero_expedient")
print(accs_bcn_df.head())
Numero_expedient Codi_districte Codi_barri Dia_Hora Latitud \ 0 2022S007749 -1 -1 2022-12-19 11:00:00 41.439261 1 2022S003422 -1 -1 2022-06-04 14:00:00 41.404080 2 2022S003346 -1 -1 2022-06-01 21:00:00 41.443596 3 2022S006073 -1 -1 2022-10-08 21:00:00 41.332974 4 2022S005123 -1 -1 2022-08-26 16:00:00 41.385209 Longitud TipusVeh_Bicicleta TipusVeh_Otros_veh TipusVeh_VMP \ 0 2.193098 0.0 2.0 0.0 1 2.208515 0.0 2.0 0.0 2 2.176568 0.0 1.0 1.0 3 2.138671 0.0 1.0 0.0 4 2.173975 0.0 0.0 1.0 Pers_Conductor Pers_Passatger Pers_Vianant Es_causa_peaton \ 0 1.0 0.0 0.0 No 1 1.0 1.0 0.0 No 2 1.0 0.0 0.0 No 3 NaN NaN NaN NaN 4 1.0 0.0 0.0 No Ubicacion_peaton 0 Desconocido 1 Desconocido 2 Desconocido 3 NaN 4 Desconocido
NOTA: Aparecen valores NaN ya que si no hay lesionados no aparece el expediente en el fichero de personas. Conviene recodificar los NaN a 0 para los valores numéricos y 'No' o 'Desconocido' según el atributo los categóricos.
NOTA 2: Al hacer merge la función ha convertido los Integer a float (decimales). Conviene reconvertir estos valores a tipo Integer
# Conversion de valores NaN a 0 'No' o 'Desconocido'
int_fields = ["TipusVeh_Bicicleta",
"TipusVeh_Otros_veh",
"TipusVeh_VMP",
"Pers_Conductor",
"Pers_Passatger",
"Pers_Vianant"]
accs_bcn_df[int_fields] = accs_bcn_df[int_fields].fillna(0.0)
accs_bcn_df["Es_causa_peaton"] = accs_bcn_df["Es_causa_peaton"].fillna("No")
accs_bcn_df["Ubicacion_peaton"] = accs_bcn_df["Ubicacion_peaton"].fillna("Desconocido")
print(accs_bcn_df.head())
Numero_expedient Codi_districte Codi_barri Dia_Hora Latitud \ 0 2022S007749 -1 -1 2022-12-19 11:00:00 41.439261 1 2022S003422 -1 -1 2022-06-04 14:00:00 41.404080 2 2022S003346 -1 -1 2022-06-01 21:00:00 41.443596 3 2022S006073 -1 -1 2022-10-08 21:00:00 41.332974 4 2022S005123 -1 -1 2022-08-26 16:00:00 41.385209 Longitud TipusVeh_Bicicleta TipusVeh_Otros_veh TipusVeh_VMP \ 0 2.193098 0.0 2.0 0.0 1 2.208515 0.0 2.0 0.0 2 2.176568 0.0 1.0 1.0 3 2.138671 0.0 1.0 0.0 4 2.173975 0.0 0.0 1.0 Pers_Conductor Pers_Passatger Pers_Vianant Es_causa_peaton \ 0 1.0 0.0 0.0 No 1 1.0 1.0 0.0 No 2 1.0 0.0 0.0 No 3 0.0 0.0 0.0 No 4 1.0 0.0 0.0 No Ubicacion_peaton 0 Desconocido 1 Desconocido 2 Desconocido 3 Desconocido 4 Desconocido
# Conversion de float a integer de los campos numericos con decimales
int_fields = ["TipusVeh_Bicicleta",
"TipusVeh_Otros_veh",
"TipusVeh_VMP",
"Pers_Conductor",
"Pers_Passatger",
"Pers_Vianant"]
accs_bcn_df[int_fields] = accs_bcn_df[int_fields].astype(int)
display(accs_bcn_df.dtypes)
Numero_expedient object Codi_districte int64 Codi_barri int64 Dia_Hora datetime64[ns] Latitud float64 Longitud float64 TipusVeh_Bicicleta int64 TipusVeh_Otros_veh int64 TipusVeh_VMP int64 Pers_Conductor int64 Pers_Passatger int64 Pers_Vianant int64 Es_causa_peaton object Ubicacion_peaton object dtype: object
# Escritura del fichero CSV master con la informacion que se utilizara en el analisis
accs_bcn_df.to_csv('clean_data/accs_whole_info.csv', index=False)