1. Carga de librerías

Cargamos el ecosistema tidyverse, que agrupa los paquetes principales para importación, transformación y visualización de datos en R.

library(tidyverse)

2. Importación de datos

Leemos el archivo CSV con read_csv(), que devuelve directamente un tibble e infiere automáticamente los tipos de cada columna.

seguridad_aerolineas <- read_csv("//Users//cristiancpv//Downloads//seguridad_aerolineas.csv")

3. Exploración inicial: estructura del dataset

glimpse() ofrece una vista compacta del dataframe: número de filas y columnas, nombre de cada variable, su tipo y los primeros valores observados.

glimpse(seguridad_aerolineas)
## Rows: 56
## Columns: 8
## $ aerolinea                      <chr> "Aer Lingus", "Aeroflot*", "Aerolineas …
## $ asientos_disponibles_km_semana <dbl> 320906734, 1197672318, 385803648, 59687…
## $ incidentes_1985_1999           <dbl> 2, 76, 6, 3, 2, 14, 2, 3, 5, 7, 3, 21, …
## $ accidentes_fatales_1985_1999   <dbl> 0, 14, 0, 1, 0, 4, 1, 0, 0, 2, 1, 5, 0,…
## $ fallecimientos_1985_1999       <dbl> 0, 128, 0, 64, 0, 79, 329, 0, 0, 50, 1,…
## $ incidentes_2000_2014           <dbl> 0, 6, 1, 5, 2, 6, 4, 5, 5, 4, 7, 17, 1,…
## $ accidentes_fatales_2000_2014   <dbl> 0, 1, 0, 0, 0, 2, 1, 1, 1, 0, 0, 3, 0, …
## $ fallecimientos_2000_2014       <dbl> 0, 88, 0, 0, 0, 337, 158, 7, 88, 0, 0, …

El dataset contiene 56 observaciones y 8 variables:

Variable Descripción
aerolinea Nombre de la compañía aérea
aviones_disponibles_asiento_km Capacidad operativa en asientos-kilómetro
incidentes_1985_1999 Incidentes registrados entre 1985 y 1999
accidentes_fatales_1985_1999 Accidentes con víctimas mortales (1985–1999)
fallecimientos_1985_1999 Número de fallecimientos (1985–1999)
incidentes_2000_2014 Incidentes registrados entre 2000 y 2014
accidentes_fatales_2000_2014 Accidentes con víctimas mortales (2000–2014)
fallecimientos_2000_2014 Número de fallecimientos (2000–2014)

4. Ranking de aerolíneas por incidentes y fallecimientos (2000–2014)

Aerolíneas con menos incidentes

Ordenamos de menor a mayor por incidentes_2000_2014 y seleccionamos las 10 primeras. Solo una aerolínea registra 0 incidentes; a partir de ahí, el orden es numérico (y alfabético en caso de empate).

menos_incidentes <- seguridad_aerolineas %>%
  arrange(incidentes_2000_2014) %>%
  filter(row_number() <= 10) %>%
  select(aerolinea, incidentes_2000_2014)

menos_incidentes
## # A tibble: 10 × 2
##    aerolinea             incidentes_2000_2014
##    <chr>                                <dbl>
##  1 Aer Lingus                               0
##  2 Avianca                                  0
##  3 Condor                                   0
##  4 COPA                                     0
##  5 Finnair                                  0
##  6 Japan Airlines                           0
##  7 LAN Airlines                             0
##  8 TAP - Air Portugal                       0
##  9 Virgin Atlantic                          0
## 10 Aerolineas Argentinas                    1

Aerolíneas con más fallecimientos

Ordenamos de mayor a menor por fallecimientos_2000_2014.

mas_fallecimientos <- seguridad_aerolineas %>%
  arrange(desc(fallecimientos_2000_2014)) %>%
  filter(row_number() <= 10) %>%
  select(aerolinea, fallecimientos_2000_2014)

mas_fallecimientos
## # A tibble: 10 × 2
##    aerolinea             fallecimientos_2000_2014
##    <chr>                                    <dbl>
##  1 Malaysia Airlines                          537
##  2 American*                                  416
##  3 Air France                                 337
##  4 Kenya Airways                              283
##  5 China Airlines                             225
##  6 TAM                                        188
##  7 Air India*                                 158
##  8 Gulf Air                                   143
##  9 SAS*                                       110
## 10 United / Continental*                      109

5. Media de fallecimientos (2000–2014)

Calculamos la media aritmética sobre el subconjunto de las 10 aerolíneas con más fallecimientos. Usamos na.rm = TRUE para que la función ignore valores perdidos en caso de haberlos.

mas_fallecimientos %>%
  summarise(media = mean(fallecimientos_2000_2014, na.rm = TRUE))
## # A tibble: 1 × 1
##   media
##   <dbl>
## 1  251.

6. Verificación de valores perdidos

Comprobamos si existe algún NA en el dataset completo y cuántos hay en total.

# ¿Hay algún NA?
any(is.na(seguridad_aerolineas))
## [1] FALSE
# ¿Cuántos en total?
sum(is.na(seguridad_aerolineas))
## [1] 0

El dataset no presenta valores perdidos.


7. Verificación de filas duplicadas

Identificamos si existen filas completamente duplicadas y las almacenamos en un objeto para posible inspección posterior.

duplicados_aerolineas <- seguridad_aerolineas %>%
  filter(duplicated(seguridad_aerolineas))

# ¿Cuántos duplicados hay?
nrow(duplicados_aerolineas)
## [1] 0

No se detectan filas duplicadas.


8. Conteo de valores distintos por variable

Usamos summarise() con across() y n_distinct() para obtener el número de valores únicos en cada columna. pivot_longer() transforma el resultado a formato vertical para facilitar su lectura en consola.

seguridad_aerolineas %>%
  summarise(across(everything(), n_distinct)) %>%
  pivot_longer(everything(), names_to = "variable", values_to = "n_distinct")
## # A tibble: 8 × 2
##   variable                       n_distinct
##   <chr>                               <int>
## 1 aerolinea                              56
## 2 asientos_disponibles_km_semana         56
## 3 incidentes_1985_1999                   19
## 4 accidentes_fatales_1985_1999           11
## 5 fallecimientos_1985_1999               38
## 6 incidentes_2000_2014                   14
## 7 accidentes_fatales_2000_2014            4
## 8 fallecimientos_2000_2014               23

9. Transformación a formato largo con pivot_longer()

Las seis últimas columnas del dataset corresponden a métricas de accidentalidad en dos periodos temporales. Con pivot_longer() las unificamos en dos columnas: accidents (nombre del indicador) y count (valor).

seguridad_pivot <- seguridad_aerolineas %>%
  pivot_longer(
    cols      = last_col(offset = 5):last_col(),
    names_to  = "accidents",
    values_to = "count"
  )

glimpse(seguridad_pivot)
## Rows: 336
## Columns: 4
## $ aerolinea                      <chr> "Aer Lingus", "Aer Lingus", "Aer Lingus…
## $ asientos_disponibles_km_semana <dbl> 320906734, 320906734, 320906734, 320906…
## $ accidents                      <chr> "incidentes_1985_1999", "accidentes_fat…
## $ count                          <dbl> 2, 0, 0, 0, 0, 0, 76, 14, 128, 6, 1, 88…

10. Separación de la columna accidents con separate()

La columna accidents codifica dos dimensiones en un mismo campo: el tipo de evento y el periodo temporal (ej. accidentes_fatales_1985_1999). Las separamos usando una expresión regular que detecta el guión bajo inmediatamente antes del primer dígito (_(?=\\d)), sin afectar a los guiones bajos internos del tipo.

seguridad_separate <- seguridad_pivot %>%
  separate(
    col  = accidents,
    into = c("type", "years"),
    sep = "_(?=19|20)"
  )

# Verificamos los valores únicos de cada nueva columna
unique(seguridad_separate$type)
## [1] "incidentes"         "accidentes_fatales" "fallecimientos"
unique(seguridad_separate$years)
## [1] "1985" "2000"

11. Transformación a formato ancho con pivot_wider()

Finalmente, expandimos la columna type para que cada categoría de accidente ocupe su propia columna, recuperando una estructura más analítica.

seguridad_wider <- seguridad_separate %>%
  pivot_wider(
    names_from  = type,
    values_from = count
  )

glimpse(seguridad_wider)
## Rows: 112
## Columns: 6
## $ aerolinea                      <chr> "Aer Lingus", "Aer Lingus", "Aeroflot*"…
## $ asientos_disponibles_km_semana <dbl> 320906734, 320906734, 1197672318, 11976…
## $ years                          <chr> "1985", "2000", "1985", "2000", "1985",…
## $ incidentes                     <dbl> 2, 0, 76, 6, 6, 1, 3, 5, 2, 2, 14, 6, 2…
## $ accidentes_fatales             <dbl> 0, 0, 14, 1, 0, 0, 1, 0, 0, 0, 4, 2, 1,…
## $ fallecimientos                 <dbl> 0, 0, 128, 88, 0, 0, 64, 0, 0, 0, 79, 3…

Análisis realizado con R 4.5.2 y tidyverse 2.0.0.