Tutorial: uso de R para predecir el retraso del vuelo

En este tutorial se muestra un ejemplo completo de un flujo de trabajo de ciencia de datos de Synapse en Microsoft Fabric. Usa los datos de nycflights13 y R para predecir si un avión llega o no con más de 30 minutos de retraso. A continuación, usa los resultados de predicción para crear un panel interactivo de Power BI.

En este tutorial, aprenderá a:

  • Usar paquetes tidymodels (como recipes, parsnip, rsample o workflows) para procesar datos y entrenar un modelo de Machine Learning
  • Escribir los datos de salida en un almacén de lago como tabla delta
  • Crear un informe visual de Power BI para acceder directamente a los datos de ese almacén de lago

Requisitos previos

  • Abra o cree un cuaderno. Para obtener información sobre cómo hacerlo, consulte Uso de cuadernos de Microsoft Fabric.

  • Establezca la opción de lenguaje en SparkR (R) para cambiar el lenguaje principal.

  • Adjunte el cuaderno a un almacén de lago. En el lado izquierdo, seleccione Añadir para añadir un almacén de lago existente o crear uno.

Instalar paquetes

Instale el paquete nycflights13 para usar el código en este artículo.

install.packages("nycflights13")
# Load the packages
library(tidymodels)      # For tidymodels packages
library(nycflights13)    # For flight data

Exploración de los datos

Los datos de nycflights13 tienen información sobre 325 819 vuelos que llegaron cerca de la ciudad de Nueva York en 2013. En primer lugar, vea la distribución de retrasos de vuelos. En este gráfico se muestra que la distribución de los retrasos de llegada está sesgada a la derecha. Tiene una cola larga en los valores altos.

ggplot(flights, aes(arr_delay)) + geom_histogram(color="blue", bins = 300)

Screenshot that shows a graph of flight delays.

Cargue los datos y realice algunos cambios en las variables:

set.seed(123)

flight_data <- 
  flights %>% 
  mutate(
    # Convert the arrival delay to a factor
    arr_delay = ifelse(arr_delay >= 30, "late", "on_time"),
    arr_delay = factor(arr_delay),
    # You'll use the date (not date-time) for the recipe that you'll create
    date = lubridate::as_date(time_hour)
  ) %>% 
  # Include weather data
  inner_join(weather, by = c("origin", "time_hour")) %>% 
  # Retain only the specific columns that you'll use
  select(dep_time, flight, origin, dest, air_time, distance, 
         carrier, date, arr_delay, time_hour) %>% 
  # Exclude missing data
  na.omit() %>% 
  # For creating models, it's better to have qualitative columns
  # encoded as factors (instead of character strings)
  mutate_if(is.character, as.factor)

Antes de crear el modelo, considere algunas variables específicas que son importantes para el preprocesamiento y el modelado.

La variable arr_delay es una variable de factor. Para el entrenamiento de modelos con regresión logística, es importante que la variable de resultados sea una variable de factor.

glimpse(flight_data)

Aproximadamente el 16 % de los vuelos de este conjunto de datos llegaron más de 30 minutos tarde.

flight_data %>% 
  count(arr_delay) %>% 
  mutate(prop = n/sum(n))

La característica dest tiene 104 destinos de vuelos.

unique(flight_data$dest)

Hay 16 operadores distintos.

unique(flight_data$carrier)

División de los datos

Divida el único conjunto de datos en dos conjuntos: un conjunto de entrenamiento y un conjunto de pruebas. Mantenga la mayoría de las filas del conjunto de datos original (como un subconjunto elegido aleatoriamente) en el conjunto de datos de entrenamiento. Use el conjunto de datos de entrenamiento para ajustar el modelo, y use el conjunto de datos de prueba para medir el rendimiento del modelo.

Use el paquete rsample para crear un objeto que contenga información sobre cómo dividir los datos. A continuación, use dos funciones rsample más para crear DataFrames para los conjuntos de entrenamiento y pruebas:

set.seed(123)
# Keep most of the data in the training set 
data_split <- initial_split(flight_data, prop = 0.75)

# Create DataFrames for the two sets:
train_data <- training(data_split)
test_data  <- testing(data_split)

Creación de una receta y roles

Cree una receta para un modelo de regresión logística simple. Antes de entrenar el modelo, use una receta para crear predictores nuevos y realizar el preprocesamiento requerido por el modelo.

Use la función update_role() para que las recetas sepan que flight y time_hour son variables, con un rol personalizado denominado ID. Un rol puede tener cualquier valor de carácter. La fórmula incluye todas las variables del conjunto de entrenamiento como predictores, salvo arr_delay. La receta mantiene estas dos variables de identificador, pero no las usa como resultados o predictores.

flights_rec <- 
  recipe(arr_delay ~ ., data = train_data) %>% 
  update_role(flight, time_hour, new_role = "ID") 

Para ver el conjunto actual de variables y roles, use la función summary():

summary(flights_rec)

Creación de características

Realice alguna ingeniería de características para mejorar el modelo. Es posible que la fecha del vuelo tenga un efecto razonable sobre la probabilidad de una llegada tardía.

flight_data %>% 
  distinct(date) %>% 
  mutate(numeric_date = as.numeric(date)) 

Puede ser recomendable agregar términos de modelo derivados de la fecha que posiblemente son importantes para el modelo. Derive las siguientes características significativas de la variable de fecha única:

  • Día de la semana
  • Mes
  • Si la fecha corresponde o no a un día festivo

Agregue los tres pasos a la receta:

flights_rec <- 
  recipe(arr_delay ~ ., data = train_data) %>% 
  update_role(flight, time_hour, new_role = "ID") %>% 
  step_date(date, features = c("dow", "month")) %>%               
  step_holiday(date, 
               holidays = timeDate::listHolidays("US"), 
               keep_original_cols = FALSE) %>% 
  step_dummy(all_nominal_predictors()) %>% 
  step_zv(all_predictors())

Ajustar un modelo con una receta

Use la regresión logística para modelar los datos de vuelo. En primer lugar, cree una especificación de modelo con el paquete parsnip:

lr_mod <- 
  logistic_reg() %>% 
  set_engine("glm")

Use el paquete workflows para agrupar el modelo parsnip (lr_mod) con la receta (flights_rec):

flights_wflow <- 
  workflow() %>% 
  add_model(lr_mod) %>% 
  add_recipe(flights_rec)

flights_wflow

Entrenamiento del modelo

Esta función puede preparar la receta y entrenar el modelo a partir de los predictores resultantes:

flights_fit <- 
  flights_wflow %>% 
  fit(data = train_data)

Use las funciones auxiliares xtract_fit_parsnip() y extract_recipe() para extraer el modelo o los objetos de receta del flujo de trabajo. En este ejemplo, se extrae el objeto de modelo ajustado y, a continuación, se usa la función broom::tidy() para obtener un tibble ordenado de coeficientes del modelo:

flights_fit %>% 
  extract_fit_parsnip() %>% 
  tidy()

Predicción de resultados

Una única llamada a predict() usa el flujo de trabajo entrenado (flights_fit) para realizar predicciones con los datos de prueba no vistos. El método predict() aplica la receta a los nuevos datos y, a continuación, pasa los resultados al modelo ajustado.

predict(flights_fit, test_data)

Obtenga la salida de predict() para que devuelva la clase predicha: late frente a on_time. Sin embargo, para las probabilidades de clase predichas para cada vuelo, use augment() con el modelo junto con los datos de prueba para guardarlos juntos:

flights_aug <- 
  augment(flights_fit, test_data)

Revise los datos:

glimpse(flights_aug)

Evaluación del modelo

Ahora tenemos un tibble con las probabilidades de clase predichas. A partir de estas primeras filas, el modelo predijo correctamente cinco vuelos puntuales (los valores de .pred_on_time son p > 0.50). Sin embargo, tenemos un total de 81 455 filas para predecir.

Necesitamos una métrica que indique la calidad del modelo para predecir las llegadas tardías, en comparación con el verdadero estado de la variable de resultado: arr_delay.

Use la métrica del área bajo la curva de característica operativa del receptor (AUC-ROC). Realice el cálculo con roc_curve() y roc_auc(), desde el paquete yardstick:

flights_aug %>% 
  roc_curve(truth = arr_delay, .pred_late) %>% 
  autoplot()

Creación de un informe de Power BI

El resultado del modelo parece correcto. Use los resultados de predicción de los retrasos de los vuelos para crear un panel interactivo de Power BI. En el panel se muestra el número de vuelos por operador y el número de vuelos por destino. El panel también puede filtrar por los resultados de predicción de retraso.

Screenshot that shows bar charts for number of flights by carrier and number of flights by destination in a Power BI report.

En Incluya el nombre del operador y el nombre del aeropuerto en el conjunto de datos del resultado de predicción:

  flights_clean <- flights_aug %>% 
  # Include the airline data
  left_join(airlines, c("carrier"="carrier"))%>% 
  rename("carrier_name"="name") %>%
  # Include the airport data for origin
  left_join(airports, c("origin"="faa")) %>%
  rename("origin_name"="name") %>%
  # Include the airport data for destination
  left_join(airports, c("dest"="faa")) %>%
  rename("dest_name"="name") %>%
  # Retain only the specific columns you'll use
  select(flight, origin, origin_name, dest,dest_name, air_time,distance, carrier, carrier_name, date, arr_delay, time_hour, .pred_class, .pred_late, .pred_on_time)

Revise los datos:

glimpse(flights_clean)

Convierta los datos en un DataFrame de Spark:

sparkdf <- as.DataFrame(flights_clean)
display(sparkdf)

Escriba los datos en una tabla delta en el almacén de lago:

# Write data into a delta table
temp_delta<-"Tables/nycflight13"
write.df(sparkdf, temp_delta ,source="delta", mode = "overwrite", header = "true")

Use la tabla delta para crear un modelo semántico.

  1. A la izquierda, seleccione Centro de datos de OneLake

  2. Seleccione el almacén de lago que adjuntó al cuaderno.

  3. Seleccione Abrir.

    Screenshot that shows the button to open a lakehouse.

  4. Seleccione Nuevos modelos semánticos.

  5. Seleccione nycflight13 como nuevo modelo semántico y, a continuación, seleccione Confirmar.

  6. Se crea el modelo semántico. Seleccione Nuevo informe.

  7. Seleccione o arrastre campos desde los paneles Datos y Visualizaciones al lienzo del informe para compilarlo

    Screenshot that shows data and visualization details for a report.

Para crear el informe que se muestra al principio de esta sección, use estas visualizaciones y datos:

  1. Gráfico de barras apiladas con:
    1. Eje Y: carrier_name.
    2. Eje X: vuelo. Seleccione Recuento para la agregación.
    3. Leyenda: origin_name
  2. Gráfico de barras apiladas con:
    1. Eje Y: dest_name.
    2. Eje X: vuelo. Seleccione Recuento para la agregación.
    3. Leyenda: origin_name
  3. Segmentación con:
    1. Campo: _pred_class
  4. Segmentación con:
    1. Campo: _pred_late