教程:使用 R 预测航班延误

本教程介绍了 Microsoft Fabric 中 Synapse 数据科学工作流的端到端示例。 在本教程中,使用了 nycflights13 数据和 R 来预测飞机是否晚于 30 分钟到达。 然后使用预测结果生成交互式 Power BI 仪表板。

本教程介绍如何执行下列操作:

  • 使用 tidymodels 包(方案parsniprsample工作流)处理数据和训练机器学习模型
  • 将输出数据以增量表形式写入湖屋
  • 生成 Power BI 视觉对象报表,以直接在该湖屋中访问数据

先决条件

  • 打开或创建笔记本。 请参阅如何使用 Microsoft Fabric 笔记本,了解如何操作。

  • 通过将语言选项设置为 Spark (R) 来更改主要语言。

  • 将笔记本附加到湖屋。 选择左侧的“添加”以添加现有湖屋或创建湖屋。

安装包

若要使用本教程中的代码,请安装 nycflights13 包。

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

浏览数据

nycflights13 数据包含 2013 年到达纽约市附近的 325,819 个航班的信息。 首先,查看航班延误的分布情况。 此图显示了到达延迟的情况为右偏分布。 在高值中具有长尾。

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

Screenshot that shows a graph of flight delays.

加载数据,对变量进行一些更改:

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)

请先了解一些对预处理和建模都很重要的特定变量,然后再开始构建模型。

变量 arr_delay 属于因子变量。 重要的是,用于训练逻辑回归模型的结果变量是因子变量。

glimpse(flight_data)

此数据集中大约 16% 的航班晚到 30 分钟以上。

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

dest 特征中包含 104 个航班目的地。

unique(flight_data$dest)

有 16 家不同的航空公司。

unique(flight_data$carrier)

拆分数据

请将此单个数据集拆分为两个数据集:一个训练集和一个测试集。 将原始数据集(随机选择的子集)中的大部分行保留在训练数据集中。 训练数据集用于拟合模型,测试数据集用于测量模型性能。

使用 rsample 包创建一个对象,该对象包含有关如何拆分数据的信息。 然后使用另外两个 rsample 函数为训练和测试集创建 DataFrame:

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)

创建方案和角色

为简单的逻辑回归模型创建方案。 在训练模型之前,请使用方案创建新预测器,并执行模型所需的预处理。

使用 update_role() 函数让方案知道 flighttime_hour 是具有名为 ID 的自定义角色的变量。 角色可以具有任何字符值。 公式包括训练集中除作为预测器的 arr_delay 之外的所有变量。 方案保留这两个 ID 变量,但不将它们用作结果或预测器。

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

若要查看当前变量和角色集,请使用 summary() 函数:

summary(flights_rec)

创建特征

执行一些特征工程来改进模型。 航班日期可能对迟到的可能性产生合理影响。

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

最好添加派生自日期的模型术语,这些模型术语对模型具有潜在重要意义。 从单个日期变量派生以下有意义的特征:

  • 一周中的一天
  • 日期是否对应于假日

将三个步骤添加到方案中:

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

将模型与方案拟合

使用逻辑回归为飞行数据建模。 首先,使用 parsnip 包生成模型规范:

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

使用 workflows 包将模型 parsnip(lr_mod) 与方案 (flights_rec) 捆绑在一起:

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

flights_wflow

训练模型

此函数可用于准备方案并从生成的预测器中训练模型:

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

使用帮助程序函数 xtract_fit_parsnip()extract_recipe() 从工作流中提取模型或方案对象。 在此示例中,拉取拟合的模型对象,然后使用 broom::tidy() 函数获取整齐的模型系数:

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

预测结果

使用训练的工作流 (flights_fit) 通过看不见的测试数据进行预测,只需调用 predict() 即可完成。 方法 predict() 将方案应用于新数据,然后将结果传递到拟合模型。

predict(flights_fit, test_data)

predict() 获取输出以返回预测类:lateon_time。 然而,如果使用每个航班的预测类概率,请使用 augment() 模型和测试数据将它们一起保存:

flights_aug <- 
  augment(flights_fit, test_data)

查看数据:

glimpse(flights_aug)

评估模型

现在我们已经准备好预测的类概率。 从前几行中,模型正确预测了 5 个准时航班(.pred_on_time 的值为 p > 0.50)。 但是,我们总共有 81,455 行要预测。

我们需要一个指标,用于查看与结果变量 arr_delay 的真实状态相比,模型对延迟到达的预测情况。

使用“接收者操作特性曲线下面积”(AUC-ROC) 作为指标。 使用 roc_curve()roc_auc()yardstick 包中进行计算:

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

生成 Power BI 报表

模型结果看起来不错。 使用航班延误预测结果构建交互式 Power BI 仪表板。 仪表板分别按航空公司和目的地显示航班数。 仪表板还可以按延迟预测结果进行筛选。

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

将航空公司名称和机场名称包含在预测结果数据集中:

  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)

查看数据:

glimpse(flights_clean)

将数据转换为 Spark 数据帧:

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

将数据写入湖屋中的增量表:

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

使用此增量表创建语义模型:

  1. 选择左侧的“OneLake 数据中心”

  2. 选择附加到笔记本的湖屋

  3. 选择“打开”

    Screenshot that shows the button to open a lakehouse.

  4. 选择“新建语义模型”

  5. 为新的语义模型选择“nycflight13”,然后选择“确认”

  6. 你已创建语义模型。 选择“新建报表”

  7. 从“数据”和“可视化效果”窗格中选择字段或将其拖到报表画布上,以生成报表

    Screenshot that shows data and visualization details for a report.

若要创建本部分开头所示的报表,请使用以下可视化效果和数据:

  1. 堆积条形图,包含:
    1. Y 轴:carrier_name
    2. X 轴:航班。 为“聚合”选择“计数”
    3. 图例:origin_name
  2. 堆积条形图,包含:
    1. Y 轴:dest_name
    2. X 轴:航班。 为“聚合”选择“计数”
    3. 图例:origin_name
  3. 切片器具有:
    1. 字段:_pred_class
  4. 切片器具有:
    1. 字段:_pred_late