Compartilhar via


Tutorial: Usar o R para prever o atraso do voo

Este tutorial apresenta um exemplo de ponta a ponta de um fluxo de trabalho de Ciência de Dados do Synapse no Microsoft Fabric. Ele usa os dados nycflights13 e R para prever se um avião chega ou não com mais de 30 minutos de atraso. Em seguida, ele usa os resultados da previsão para criar um painel interativo do Power BI.

Neste tutorial, você aprenderá a:

  • Use pacotes tidymodels (recipes, parsnip, rsample, fluxos de trabalho) para processar dados e treinar um modelo de machine learning
  • Gravar os dados de saída em um lakehouse no formato de uma tabela delta
  • Criar um relatório visual do Power BI para acessar diretamente os dados naquele lakehouse

Pré-requisitos

  • Abra ou crie um bloco de anotações. Para saber como, confira Como usar notebooks do Microsoft Fabric.

  • Defina a opção de idioma para SparkR (R) para alterar o idioma primário.

  • Anexe seu notebook a um lakehouse. No lado esquerdo, selecione Adicionar para adicionar um lakehouse existente ou para criar um.

Instalar pacotes

Instale o pacote nycflights13 para usar o código neste tutorial.

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

Explorar os dados

Os dados nycflights13 têm informações sobre 325.819 voos que chegaram perto de Nova York em 2013. Primeiro, exiba a distribuição de atrasos de voo. Este grafo mostra que a distribuição dos atrasos de chegada está distorcida para a direita. Ele tem uma cauda longa nos valores altos.

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

captura de tela que mostra um grafo de atrasos de voo.

Carregue os dados e faça algumas alterações nas variáveis:

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 criarmos o modelo, considere algumas variáveis específicas importantes para pré-processamento e modelagem.

A variável arr_delay é uma variável de fator. Para o treinamento do modelo de regressão logística, é importante que a variável de resultado seja uma variável de fator.

glimpse(flight_data)

Cerca de 16% dos voos neste conjunto de dados chegaram com mais de 30 minutos de atraso.

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

O recurso dest tem 104 destinos de voo.

unique(flight_data$dest)

Há 16 transportadoras distintas.

unique(flight_data$carrier)

Dividir os dados

Divida o conjunto de dados em dois conjuntos: um conjunto de treinamento e um conjunto de teste. Mantenha a maioria das linhas no conjunto de dados original (como um subconjunto escolhido aleatoriamente) no conjunto de dados de treinamento. Use o conjunto de dados de treinamento para ajustar o modelo e use o conjunto de dados de teste para medir o desempenho do modelo.

Use o pacote rsample para criar um objeto que contenha informações sobre como dividir os dados. Em seguida, use mais duas funções rsample para criar DataFrames para os conjuntos de treinamento e teste:

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)

Criar uma receita e funções

Crie uma receita para um modelo de regressão logística simples. Antes de treinar o modelo, use uma receita para criar novos preditores e realize o pré-processamento necessário para o modelo.

Use a função update_role() para que as receitas saibam que flight e time_hour são variáveis, com uma função personalizada chamada ID. Um papel pode ter qualquer valor de caractere. A fórmula inclui todas as variáveis no conjunto de treinamento, exceto arr_delay, como preditores. A receita mantém essas duas variáveis de ID, mas não as usa como resultados ou preditores.

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

Para exibir o conjunto atual de variáveis e funções, use a função summary():

summary(flights_rec)

Criar funcionalidades

Faça alguma engenharia de recursos para melhorar seu modelo. A data do voo pode ter um efeito razoável sobre a probabilidade de uma chegada tardia.

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

Pode ajudar a adicionar termos de modelo derivados da data que potencialmente têm importância para o modelo. Derivar os seguintes recursos significativos da variável de data única:

  • Dia da semana
  • Mês
  • Se a data corresponde ou não a um feriado

Adicione as três etapas à sua receita:

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())

Ajuste um modelo com uma receita

Use a regressão logística para modelar os dados de voo. Primeiro, crie uma especificação de modelo com o pacote parsnip:

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

Use o pacote workflows para agrupar seu modelo de parsnip (lr_mod) com sua receita (flights_rec):

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

flights_wflow

Treinar o modelo

Essa função pode preparar a receita e treinar o modelo dos preditores resultantes:

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

Use as funções auxiliares xtract_fit_parsnip() e extract_recipe() para extrair os objetos de modelo ou receita do fluxo de trabalho. Neste exemplo, extraia o objeto de modelo ajustado e, em seguida, use a função broom::tidy() para obter um tibble organizado de coeficientes de modelo:

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

Prever resultados

Uma única chamada para predict() usa o fluxo de trabalho treinado (flights_fit) para fazer previsões com os dados de teste não vistos. O método predict() aplica a receita aos novos dados e, em seguida, passa os resultados para o modelo ajustado.

predict(flights_fit, test_data)

Obtenha a saída de predict() para retornar a classe prevista: late versus on_time. No entanto, para as probabilidades de classe previstas para cada voo, use augment() com o modelo, combinado com os dados de teste, para salvá-los juntos:

flights_aug <- 
  augment(flights_fit, test_data)

Examine os dados:

glimpse(flights_aug)

Avaliar o modelo

Agora temos um tibble com as probabilidades de classe previstas. Nas primeiras linhas, o modelo previu corretamente cinco voos no horário (os valores de .pred_on_time são p > 0.50). No entanto, temos 81.455 linhas no total para prever.

Precisamos de uma métrica que informe o quão bem o modelo previu chegadas tardias, em comparação com o status verdadeiro da variável de resultado, arr_delay.

Utilize a Área Sob a Curva da Característica de Operação do Receptor (AUC-ROC) como métrica. Compute-o com roc_curve() e roc_auc(), do pacote yardstick:

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

Criar um relatório do Power BI

O resultado do modelo parece bom. Use os resultados da previsão de atraso de voo para criar um painel interativo do Power BI. O painel mostra o número de voos por companhia aérea e o número de voos por destino. O painel pode filtrar os resultados da previsão de atraso.

Captura de tela que mostra gráficos de barras para o número de voos por companhia aérea e número de voos por destino em um relatório do Power BI.

Inclua o nome da transportadora e o nome do aeroporto no conjunto de dados do resultado da previsão:

  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)

Examine os dados:

glimpse(flights_clean)

Converta os dados em um DataFrame do Spark:

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

Escreva os dados em uma tabela delta em seu lakehouse:

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

Use a tabela delta para criar um modelo semântico.

  1. À esquerda, selecione OneLake

  2. Selecione o lakehouse que você anexou ao notebook

  3. Selecione Abrir

    Captura de tela que mostra o botão para abrir um lakehouse.

  4. Selecione Novo modelo semântico

  5. Selecione nycflight13 para seu novo modelo semântico e selecione Confirmar

  6. Seu modelo semântico é criado. Selecione Novo relatório

  7. Selecione ou arraste campos dos painéis de Dados e Visualizações para a tela do relatório e crie seu relatório

    Captura de tela que mostra dados e detalhes de visualização de um relatório.

Para criar o relatório mostrado no início desta seção, use estas visualizações e dados:

  1. Gráfico de barras empilhadas com:
    1. Eixo Y: carrier_name
    2. Eixo X: voo. Selecione Count para a agregação
    3. Legenda: origin_name
  2. Gráfico de barras empilhadas com:
    1. Eixo Y: dest_name
    2. Eixo X: voo. Selecione Count para a agregação
    3. Legenda: origin_name
  3. Segmentação com:
    1. Campo: _pred_class
  4. Segmentação com:
    1. Campo: _pred_late