Soy Jeiner Velandia, licenciado en Psicología y Pedagogía, con formación en maestría en TI aplicadas a la educación. Actualmente curso un doctorado en Gestión de la Innovación Tecnológica y una especialización en Métodos Estadísticos para el Análisis de Datos.
En este documento presento los 6 pasos de la actividad: instalación de paquetes, selección y limpieza de datos, creación de data frames, cálculo de medidas de localización, dispersión y forma, y finalmente la generación de gráficos para el análisis.
Preámbulo. Ajusto el sistema con
options(digits = 4)
para que todos los números en consola
se muestren con máximo cuatro decimales. Esto facilita la lectura de
resultados y evita valores demasiado largos que pueden ser confusos.
Paso 1. Instalo y cargo librerías esenciales:
nycflights13
trae la base de datos de vuelos,
dplyr
sirve para manipular tablas, ggplot2
para graficar, e1071
y DescTools
para calcular
asimetría y curtosis, y readr
para importar o exportar CSV.
Se usan install.packages()
y luego library()
para tenerlas listas.
#Ajusto el sistema para que todos los datos se vean máximo 4 décimales
options(digits = 4)
#========================================== PASO 1 ===========================
# Instalo los paquetes
install.packages("nycflights13") # Base de datos de vuelos de NY en 2013
install.packages("dplyr") # Pauete de manipulacion de datos
install.packages("ggplot2") # Liberia para usar gráficos
install.packages("e1071") # skewness y kurtosis (Fisher-Pearson)
install.packages("DescTools") # Skew(), Kurt(), BowleySkew()
install.packages("readr") #importar/exportar CSV
## Cargo todas las librerias instaladas``
library(nycflights13)
library(dplyr)
library(ggplot2)
library(e1071)
library(DescTools)
library(readr)
Paso 2. Cargo la base flights
con
data()
. Primero exploro su estructura con
str()
y glimpse()
para conocer columnas y
tipos de datos. Después selecciono solo cuatro variables relevantes
(distance
, air_time
, dep_delay
,
arr_delay
) con dplyr::select()
. Reviso las
primeras y últimas filas con head()
, tail()
,
abro el conjunto con View()
, obtengo estadísticas básicas
con summary()
y cuento valores faltantes con
colSums(is.na())
.
#========================================== PASO 2 ===========================
# Cargar datos y seleccionar variables
data("flights") # TRAIGO LA DATA DE FLIGT
str(flights) # QUIERO VER LAS COLUMNAS Y EL TIPO DE DATOS QUE HAY
## tibble [336,776 × 19] (S3: tbl_df/tbl/data.frame)
## $ year : int [1:336776] 2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ...
## $ month : int [1:336776] 1 1 1 1 1 1 1 1 1 1 ...
## $ day : int [1:336776] 1 1 1 1 1 1 1 1 1 1 ...
## $ dep_time : int [1:336776] 517 533 542 544 554 554 555 557 557 558 ...
## $ sched_dep_time: int [1:336776] 515 529 540 545 600 558 600 600 600 600 ...
## $ dep_delay : num [1:336776] 2 4 2 -1 -6 -4 -5 -3 -3 -2 ...
## $ arr_time : int [1:336776] 830 850 923 1004 812 740 913 709 838 753 ...
## $ sched_arr_time: int [1:336776] 819 830 850 1022 837 728 854 723 846 745 ...
## $ arr_delay : num [1:336776] 11 20 33 -18 -25 12 19 -14 -8 8 ...
## $ carrier : chr [1:336776] "UA" "UA" "AA" "B6" ...
## $ flight : int [1:336776] 1545 1714 1141 725 461 1696 507 5708 79 301 ...
## $ tailnum : chr [1:336776] "N14228" "N24211" "N619AA" "N804JB" ...
## $ origin : chr [1:336776] "EWR" "LGA" "JFK" "JFK" ...
## $ dest : chr [1:336776] "IAH" "IAH" "MIA" "BQN" ...
## $ air_time : num [1:336776] 227 227 160 183 116 150 158 53 140 138 ...
## $ distance : num [1:336776] 1400 1416 1089 1576 762 ...
## $ hour : num [1:336776] 5 5 5 5 6 5 6 6 6 6 ...
## $ minute : num [1:336776] 15 29 40 45 0 58 0 0 0 0 ...
## $ time_hour : POSIXct[1:336776], format: "2013-01-01 05:00:00" "2013-01-01 05:00:00" ...
dplyr::glimpse(flights) #USO UNA LIBERIA DPLYR para con glimpse= vista rápida y compacta de un dataframe
## Rows: 336,776
## Columns: 19
## $ year <int> 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2…
## $ month <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ day <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ dep_time <int> 517, 533, 542, 544, 554, 554, 555, 557, 557, 558, 558, …
## $ sched_dep_time <int> 515, 529, 540, 545, 600, 558, 600, 600, 600, 600, 600, …
## $ dep_delay <dbl> 2, 4, 2, -1, -6, -4, -5, -3, -3, -2, -2, -2, -2, -2, -1…
## $ arr_time <int> 830, 850, 923, 1004, 812, 740, 913, 709, 838, 753, 849,…
## $ sched_arr_time <int> 819, 830, 850, 1022, 837, 728, 854, 723, 846, 745, 851,…
## $ arr_delay <dbl> 11, 20, 33, -18, -25, 12, 19, -14, -8, 8, -2, -3, 7, -1…
## $ carrier <chr> "UA", "UA", "AA", "B6", "DL", "UA", "B6", "EV", "B6", "…
## $ flight <int> 1545, 1714, 1141, 725, 461, 1696, 507, 5708, 79, 301, 4…
## $ tailnum <chr> "N14228", "N24211", "N619AA", "N804JB", "N668DN", "N394…
## $ origin <chr> "EWR", "LGA", "JFK", "JFK", "LGA", "EWR", "EWR", "LGA",…
## $ dest <chr> "IAH", "IAH", "MIA", "BQN", "ATL", "ORD", "FLL", "IAD",…
## $ air_time <dbl> 227, 227, 160, 183, 116, 150, 158, 53, 140, 138, 149, 1…
## $ distance <dbl> 1400, 1416, 1089, 1576, 762, 719, 1065, 229, 944, 733, …
## $ hour <dbl> 5, 5, 5, 5, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6…
## $ minute <dbl> 15, 29, 40, 45, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0…
## $ time_hour <dttm> 2013-01-01 05:00:00, 2013-01-01 05:00:00, 2013-01-01 0…
df <- dplyr::select(flights, distance, air_time, dep_delay, arr_delay) # para la actividad trabajaremos 4 variables
#View(flights)
##### Visualizo el DF en crudo
head(df,20) # Muestra las primeras 20 Filas
## # A tibble: 20 × 4
## distance air_time dep_delay arr_delay
## <dbl> <dbl> <dbl> <dbl>
## 1 1400 227 2 11
## 2 1416 227 4 20
## 3 1089 160 2 33
## 4 1576 183 -1 -18
## 5 762 116 -6 -25
## 6 719 150 -4 12
## 7 1065 158 -5 19
## 8 229 53 -3 -14
## 9 944 140 -3 -8
## 10 733 138 -2 8
## 11 1028 149 -2 -2
## 12 1005 158 -2 -3
## 13 2475 345 -2 7
## 14 2565 361 -2 -14
## 15 1389 257 -1 31
## 16 187 44 0 -4
## 17 2227 337 -1 -8
## 18 1076 152 0 -7
## 19 762 134 0 12
## 20 1023 147 1 -6
tail(df,20) # Muesta las ultimas 20 filas
## # A tibble: 20 × 4
## distance air_time dep_delay arr_delay
## <dbl> <dbl> <dbl> <dbl>
## 1 209 39 -9 -16
## 2 301 50 194 194
## 3 378 61 -2 8
## 4 764 97 27 7
## 5 872 120 72 57
## 6 273 48 -14 -21
## 7 2565 318 80 42
## 8 944 123 154 130
## 9 266 43 -8 -8
## 10 209 41 -5 -17
## 11 301 52 -10 -20
## 12 264 47 -5 -16
## 13 187 33 12 1
## 14 1617 196 -10 -25
## 15 764 NA NA NA
## 16 213 NA NA NA
## 17 198 NA NA NA
## 18 764 NA NA NA
## 19 419 NA NA NA
## 20 431 NA NA NA
#View(df) # Abre en otra pestaña el DF
summary(df) # Aplica los estadisticos básicos // (mínimo, cuartiles, media, máximo y los NA).
## distance air_time dep_delay arr_delay
## Min. : 17 Min. : 20 Min. : -43.0 Min. : -86.00
## 1st Qu.: 502 1st Qu.: 82 1st Qu.: -5.0 1st Qu.: -17.00
## Median : 872 Median :129 Median : -2.0 Median : -5.00
## Mean :1040 Mean :151 Mean : 12.6 Mean : 6.89
## 3rd Qu.:1389 3rd Qu.:192 3rd Qu.: 11.0 3rd Qu.: 14.00
## Max. :4983 Max. :695 Max. :1301.0 Max. :1272.00
## NA's :9430 NA's :8255 NA's :9430
colSums(is.na(df)) # cuenta exactamente cuántos NA hay por variable.
## distance air_time dep_delay arr_delay
## 0 9430 8255 9430
Paso 3. Elimino filas con datos faltantes usando
dplyr::filter()
junto con !is.na()
para cada
variable. Esto asegura que los cálculos no se vean afectados por huecos
en la información. Luego verifico que no haya NA con
colSums(is.na())
y reviso el nuevo dataframe limpio con
knitr::kable()
.
#========================================== PASO 3 ===========================
# Limpiamos la base de los NA
df <- dplyr::filter(df,
!is.na(distance),
!is.na(air_time),
!is.na(dep_delay),
!is.na(arr_delay))
# Vuelvo a psar el Colsum debe ser 0
knitr::kable(head(df,10)) # En mark Down no funciona el VIEW()
distance | air_time | dep_delay | arr_delay |
---|---|---|---|
1400 | 227 | 2 | 11 |
1416 | 227 | 4 | 20 |
1089 | 160 | 2 | 33 |
1576 | 183 | -1 | -18 |
762 | 116 | -6 | -25 |
719 | 150 | -4 | 12 |
1065 | 158 | -5 | 19 |
229 | 53 | -3 | -14 |
944 | 140 | -3 | -8 |
733 | 138 | -2 | 8 |
knitr::kable(tail(df,10)) #Uso este comando con Head y tail para ver 10 y 10
distance | air_time | dep_delay | arr_delay |
---|---|---|---|
872 | 120 | 72 | 57 |
273 | 48 | -14 | -21 |
2565 | 318 | 80 | 42 |
944 | 123 | 154 | 130 |
266 | 43 | -8 | -8 |
209 | 41 | -5 | -17 |
301 | 52 | -10 | -20 |
264 | 47 | -5 | -16 |
187 | 33 | 12 | 1 |
1617 | 196 | -10 | -25 |
colSums(is.na(df)) # Compruebo que en DF no hay NA con un conteo por variable
## distance air_time dep_delay arr_delay
## 0 0 0 0
Paso 4. Creo la función limites_iqr()
que define un rango aceptable de datos usando cuartiles
(quantile()
) e intervalo intercuartílico
(IQR()
). Aplico la función a distance
y
air_time
, obtengo límites inferior y superior y filtro
valores atípicos con dplyr::filter()
. El resultado se
guarda en df_clean
. Finalmente muestro cuántas filas quedan
con nrow()
y reviso el nuevo dataset con
knitr::kable()
.
#========================================== PASO 4 ===========================
# Voy a establecer los limittes para que no hayan datos "extraños"
# Creo una función limites_iqr
limites_iqr <- function(x) {
q1 <- quantile(x, 0.25, na.rm = TRUE)
q3 <- quantile(x, 0.75, na.rm = TRUE)
iqr <- IQR(x, na.rm = TRUE)
setNames(c(q1 - 1.5 * iqr, q3 + 1.5 * iqr), c("inf", "sup"))
}
##### Aplico la funcion Limites iqr a la variable distancia y tiempo de vuelo
### Guardo en un objeto los limites para los dos
lims_dist <- limites_iqr(df$distance)
lims_air <- limites_iqr(df$air_time)
print(lims_dist)
## inf sup
## -811 2709
print(lims_air)
## inf sup
## -83 357
#### Vamos a filtrar sacando los datos que no están los limites inf y sup
df_clean <- dplyr::filter( # Cree un NUEVO DF llamado DF_CLEAN!!!!!!!
df,
distance >= lims_dist["inf"], distance <= lims_dist["sup"], # Cuando la distancia se mayor o igual al inferior y menor o igual al superior
air_time >= lims_air["inf"], air_time <= lims_air["sup"]
)
knitr::kable(head(df_clean,5)) # En mark Down no funciona el VIEW()
distance | air_time | dep_delay | arr_delay |
---|---|---|---|
1400 | 227 | 2 | 11 |
1416 | 227 | 4 | 20 |
1089 | 160 | 2 | 33 |
1576 | 183 | -1 | -18 |
762 | 116 | -6 | -25 |
knitr::kable(tail(df_clean,5)) #Uso este comando con Head y tail para ver 5 y 5
distance | air_time | dep_delay | arr_delay |
---|---|---|---|
209 | 41 | -5 | -17 |
301 | 52 | -10 | -20 |
264 | 47 | -5 | -16 |
187 | 33 | 12 | 1 |
1617 | 196 | -10 | -25 |
cat("Filas finales:", nrow(df_clean), "\n")# Muestro las filas finales de DF clean
## Filas finales: 321898
Paso 5. Construyo la función analizar()
que genera una tabla con estadísticas de cada variable. Incluye medidas
de localización (mean()
, median()
, moda con
table()
), dispersión (var()
,
sd()
, rango, IQR()
, coeficiente de variación)
y forma (skewness()
, kurtosis()
). Agrupo
resultados para todas las variables con rbind()
en un
objeto llamado estadisticas
y lo visualizo con
knitr::kable()
.
#===================. PASO 5 ========================
#Creare una función dentro de la función creo un DF nuevo donde están los todos los estadisticos Localización, Dispersión , Forma
analizar <- function(x, nom) {
data.frame(
Variable = nom,
# Centralidad
Media = mean(x, na.rm = TRUE),
Mediana = median(x, na.rm = TRUE),
Moda = as.numeric(names(which.max(table(x)))),
Q1 = quantile(x, 0.25, na.rm = TRUE),
Q2 = quantile(x, 0.50, na.rm = TRUE),
Q3 = quantile(x, 0.75, na.rm = TRUE),
#DISPERSIÓN
Varianza = var(x, na.rm = TRUE),
Desv_Est = sd(x, na.rm = TRUE),
Rango = max(x, na.rm = TRUE) - min(x, na.rm = TRUE),
RIQ = IQR(x, na.rm = TRUE),
CV = sd(x, na.rm = TRUE) / mean(x, na.rm = TRUE) * 100,
#FORMA
Asimetria = e1071::skewness(x, type=2, na.rm = TRUE),
Curtosis = e1071::kurtosis(x, type=2, na.rm = TRUE),
row.names = NULL
)
}
###### VOY A CREAR un objeto llamdo esttadisticas que va a construir el datta frame final
estadisticas <- rbind( # RBIND me crea las filas por variable y las guara para graficar
analizar(df_clean$distance, "DISTANCE"),
analizar(df_clean$air_time, "AIR_TIME"),
analizar(df_clean$dep_delay, "DEP_DELAY"),
analizar(df_clean$arr_delay, "ARR_DELAY")
)
#View(estadisticas) # Acá ya veo la tabla con los datos guardados de la función
knitr::kable(estadisticas)
Variable | Media | Mediana | Moda | Q1 | Q2 | Q3 | Varianza | Desv_Est | Rango | RIQ | CV | Asimetria | Curtosis |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
DISTANCE | 1017.794 | 872 | 2475 | 502 | 872 | 1389 | 483267 | 695.17 | 2506 | 887 | 68.30 | 0.9361 | -0.0790 |
AIR_TIME | 146.464 | 128 | 42 | 81 | 128 | 186 | 7735 | 87.95 | 337 | 105 | 60.05 | 0.9087 | -0.0879 |
DEP_DELAY | 12.596 | -2 | -5 | -5 | -2 | 11 | 1609 | 40.11 | 1180 | 16 | 318.42 | 4.7381 | 41.4081 |
ARR_DELAY | 6.688 | -5 | -13 | -17 | -5 | 13 | 1988 | 44.59 | 1213 | 30 | 666.76 | 3.6786 | 27.6714 |
Paso 6. Para distance y air_time utilizo geom_histogram() con intervalos definidos por binwidth. Resalto la media de cada distribución con geom_vline(linetype=“dashed”, color=“red”). Ajusto escalas con scale_x_continuous() y scale_y_continuous(), y aplico theme_minimal() para un diseño limpio.
En el caso de los retrasos de salida (dep_delay) y llegada (arr_delay), empleo geom_histogram() combinado con case_when() para clasificar los vuelos en categorías: Adelantado, A Tiempo, Retraso Leve y Retraso Fuerte. Personalizo colores con scale_fill_manual() y limito el foco de los datos con coord_cartesian(xlim=…) para concentrarme en los valores más frecuentes. También agrego convenciones con leyendas claras.
Para un análisis más avanzado de los retrasos en salida, combino geom_histogram(aes(y=..density..)) con geom_density() para representar la forma de la distribución y resaltar la media con geom_vline(). Calculo asimetría y curtosis usando skewness() y kurtosis() de la librería moments, defino la forma de la curva con condicionales ifelse(), y muestro el resultado dentro del gráfico con annotate(“text”, …).
Finalmente, para explorar la relación entre retraso en despegue y retraso en aterrizaje, utilizo geom_hex() con scale_fill_viridis_c(), generando un gráfico tipo panal de abeja que permite visualizar zonas de alta concentración sin sobrecargar la visualización.
#===================. PASO 6 ========================
# Grafico: distancia y air time (Histograma y box plot)
# Graficos : Retraso (Histograma)
#gradicos: Simetria y Curtosis (Graficos avanzados)
#######======= 1. Histograma Distance================
ggplot(df_clean, aes(x = distance)) + ### SELECCIONO la variable
geom_histogram(binwidth = 50 , fill = "steelblue", color = "black") + # SELECCIONO el tipo de grafico
geom_vline(aes(xintercept = mean(distance, na.rm = TRUE)), # CREO la LINEA Vertical con la media.
color = "red", linetype = "dashed", linewidth = 1) +
labs(title = "Distribución de distancias de vuelos (Distance)",
x = "Distancia (millas)",
y = "Número de vuelos") +
####### Eje y
scale_y_continuous(breaks = seq(0, 50000, by = 5000)) +
######## EJE X
scale_x_continuous(breaks = seq(0, 5000, by = 500))+
theme_minimal()
#####======= 2. Histograma Air time ====================
ggplot(df_clean, aes(x = air_time)) + # Le digo que vamos a graficar air_time
geom_histogram(binwidth = 10, fill = "steelblue", color = "black") + # agrupo lo vuelos en tiempoos de 10 min / relleno y color de línea
geom_vline(aes(xintercept = mean(air_time, na.rm = TRUE)), # geom_vline(...): linea roja es la media del tiempo de vuelo.
color = "red" , linetype = "dashed", linewidth = 1) +
labs(title = "Distribución del tiempo de vuelo (air_time)", # Etiquetas
x = "Tiempo de vuelo (minutos)",
y = "Número de vuelos") +
####### Eje y
scale_y_continuous(breaks = seq(0, 50000, by = 5000)) +
######## EJE X
scale_x_continuous(breaks = seq(0, 500, by = 50))+
theme_minimal() # Fondo blanco lineas
#####===== Retrasos / despegar
#para este histograma se deben realizar un grafico mas elaborado
#1. se debe usar un Case_When_ es un condicional de datos que permite etiquetar
#2. se hace un zoom sobre el X -
#3. Creamos convenciones que salen al lado derecho
############## HISTOGRAMAS CONDICIONAL COLOR Y CATEGORIA=======
ggplot(df_clean, aes(x = dep_delay)) +
# Histograma con las categorías de color para poder visualizar el histograma
geom_histogram(
aes(fill = case_when(
dep_delay < 0 ~ "Adelantado",
dep_delay == 0 ~ "A Tiempo",
dep_delay <=120 ~ "Retraso Leve",
TRUE ~ "Retraso Fuerte" # TRUE captura todos los casos restantes
)),
binwidth = 5,
color = "white",
na.rm = TRUE # Omite los valores NA para evitar errores
) +
######## Importante ZOOM
coord_cartesian(xlim = c(-43, 100)) +
######## Convensiones
scale_fill_manual(
name = "Tipo de Puntualidad",
values = c(
"Adelantado" = "seagreen",
"A Tiempo" = "steelblue",
"Retraso Leve" = "orange",
"Retraso Fuerte" = "firebrick"
)
) +
########
labs(
title = "Retrasos vuelos Vuelos ",
subtitle = " Rango: -43 a 100 minutos",
x = "Retraso en la Salida (Minutos)",
y = "Cantidad de Vuelos"
) +
theme_minimal()
##############====================================== RETRASOS ATERRIZAR
#para este histograma se deben realizar un grafico mas elaborado
#1. se debe usar un Case_When_ es un condicional de datos que permite etiquetar
#2. se hace un zoom sobre el X -
#3. Creamos convenciones que salen al lado derecho
#4. Creamos un Scale en X / Y para ver numeros mas pequeños en los labels
ggplot(df_clean, aes(x = arr_delay)) +
# Histograma con las categorías de color para poder visualizar el histograma
geom_histogram(
aes(fill = case_when(
arr_delay < 0 ~ "Adelantado",
arr_delay == 0 ~ "A Tiempo",
arr_delay <= 60 ~ "Retraso Leve",
TRUE ~ "Retraso Fuerte" # TRUE captura todos los casos restantes
)),
binwidth = 10,
color = "white",
na.rm = TRUE # Omite los valores NA para evitar errores
) +
######## Importante ZOOM delimito el foco de los datos
coord_cartesian(xlim = c(-90, 200)) +
####### Eje y
scale_y_continuous(breaks = seq(0, 70000, by = 10000)) +
######## EJE X
scale_x_continuous(breaks = seq(-100, 200, by = 50))+
######## Convensiones
scale_fill_manual(
name = "Tipo de Puntualidad",
values = c(
"Adelantado" = "seagreen",
"A Tiempo" = "steelblue",
"Retraso Leve" = "orange",
"Retraso Fuerte" = "firebrick"
)
) +
########
labs(
title = "Retrasos llegadas vuelos ",
subtitle = " Rango: -90 a 200 minutos",
x = "Retraso en la llegada (Minutos)",
y = "Cantidad de Vuelos"
) +
theme_minimal()
#####================================
#####================================ AVANZADOS PRO ==============
###### Densidad, Asimetría y curtois
##########=============================RETRASOS SALIDAS=====================================
# Calcular curtosis y asimetría
kurt_val <- kurtosis(df_clean$dep_delay, na.rm = TRUE) # Creo un objeto donde guardo la operacion Kurtosis
skew_val <- skewness(df_clean$dep_delay, na.rm = TRUE) # Creo un objeto donde guardo la asimetría
# Definir el tipo de distribución según la curtosis creo ubn condicional con IF
tipo_curtosis <- ifelse(kurt_val > 3, "Leptocúrtica (colas pesadas)",
ifelse(kurt_val < 3, "Platicúrtica (aplanada)",
"Mesocúrtica (normal)"))
# Definir el tipo de asimetría , condicional
tipo_asimetria <- ifelse(skew_val > 0, "Positiva (cola a la derecha)",
ifelse(skew_val < 0, "Negativa (cola a la izquierda)",
"Simétrica"))
# Texto que se va a mostrar en la anotación
texto <- paste0("Asimetría: ", tipo_asimetria,
"\nCurtosis: ", tipo_curtosis,
"\n(skew = ", round(skew_val,2), #llamo el objeto guardado y el digo que muestre 2 decimales
", kurt = ", round(kurt_val,2), ")")
# --- Gráfico ---
ggplot(df_clean, aes(x = dep_delay)) +
geom_histogram(aes(y = ..density..), bins = 100, fill = "orange", color = "black") + #histograma
geom_density(color = "magenta", linewidth = 1) + #liena de densidad
geom_vline(aes(xintercept = mean(dep_delay, na.rm = TRUE)), # Linea de la Media
color = "red", linetype = "dashed", linewidth = 1) +
######## Importante ZOOM delimito el foco de los datos
coord_cartesian(xlim = c(-50, 100)) + # Zoom en el eje X lo ajusto de acuerdo a los valores de los datos
######## EJE X
scale_x_continuous(breaks = seq(-50, 200, by = 10))+ # como se ve el eje X en el grafico
labs(title = "Distribución de retraso en despegue (dep_delay)",
x = "Retraso en despegue (min)", y = "Densidad") +
annotate("text", x = 60, y = 0.06, # El texto en el gráifco
label = texto, color = "black", size = 3, fontface = "bold") +
theme_minimal()
#########==========
###### Panal Exaginal
library(ggplot2)
ggplot(df_clean, aes(x = dep_delay, y = arr_delay)) +
geom_hex(bins = 100) +
scale_fill_viridis_c() +
labs(title = "Relación entre retraso en despegue y aterrizaje",
x = "Retraso en despegue (min)",
y = "Retraso en aterrizaje (min)",
fill = "Cantidad") +
theme_minimal()