Accidentabilidad de VMPs en Barcelona e incidencia sobre peatones¶

Según datos de la Guàrdia Urbana del año 2022¶

Parte I. Limpieza y adecuación de los datos¶

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.

In [1]:
# Carga de las librerias necesarias

import pandas as pd
import matplotlib.pyplot as plt

1. Fuente de datos¶

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

  • 2022_accidents_gu_bcn.csv Información genérica de los accidentes reportados.
  • 2022_accidents_persones_gu_bcn.csv Información de todas las personas implicadas en cada accidente.
  • 2022_accidents_vehicles_gu_bcn.csv Información de los vehículos implicados en cada accidente.
  • 2022_accidents_causes_gubcn.csv
  • 2022_accidents_tipus_gu_bcn.csv

2. Estrategia para el análisis¶

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.

3. Extracción de la información general (accidentes reportados, distritos, barrios)¶

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.

In [2]:
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.

In [3]:
#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.

In [4]:
# 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  
In [5]:
# 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  
In [6]:
# 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  

4. Obtención de la información adicional de cada accidente reportado necesaria para el análisis específico¶

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.

  • Tipo de vehículo: VMP, Bicicleta, Otros
  • Tipo de persona: Conductor, Pasajero, Peatón (Vianant)
  • Causa del peatón: Sí | No --> El accidente, ¿es a causa del peatón?
  • Lugar atropello del peatón: En qué parte de la vía pública se halla el peatón. ¿Es una zona exclusiva o protegida para el tránsito de personas a pie?

4.1 Tipos de vehículo¶

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.

In [7]:
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]
In [8]:
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
In [9]:
# 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()
Out[9]:
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:

  • Bicicleta --> Bicicleta
  • Veh. mobilitat personal amb motor --> VMP
  • Veh. mobilitat personal sense motor --> VMP
  • Resto de categorías --> Otros_veh

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.

In [10]:
# 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
In [11]:
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
In [12]:
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

4.2 Tipos de persona con lesiones¶

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.

In [13]:
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]
In [14]:
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()
Out[14]:
array(['Conductor', 'Passatger', 'Vianant'], dtype=object)
In [15]:
# 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
In [16]:
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

4.3 Responsabilidad y ubicación del peatón, si hay alguno implicado y ha sufrido lesiones¶

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.

In [17]:
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                                    ...  
In [18]:
# 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                                                                                                                              ']
In [19]:
# 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()
In [20]:
# 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:

  • Desconegut --> Desconocido
  • En zona peatonal --> Zona Peatonal
  • Fora del pas --> Fuera del Paso
  • En pas regulat per semàfor --> Paso Regulado
  • En pas sense regular --> Paso No Regulado
  • A la vorera / Andana --> Zona Peatonal
  • Altres --> Otras
  • En pas sense senyalitzar --> Paso Sin Señalizar

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.

In [21]:
# 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

5. Unión de los dataframes (join)¶

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.

In [22]:
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

In [26]:
# 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  
In [27]:
# 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
In [28]:
# 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)
In [ ]: