Assignment 5A - Airline Delays

This analysis compares the arrival performance of Alaska Airlines and America West across five destinations. The data will first be imported in wide format, cleaned and transformed into tidy long format, and then used to compare on-time and delayed flight percentages.

library(tidyverse)
library(dplyr)
library(tidyr)
library(ggplot2)
library(knitr)

3. Create and Upload the CSV File

The airline delay data was recreated in a CSV file named airline_delays.csv and uploaded to my public GitHub repository. The file contains the original wide-format data for Alaska Airlines and America West across five destinations.

4. Read the CSV from GitHub

url <- "https://raw.githubusercontent.com/LBoodram26/Data607_-Week-5/refs/heads/main/airline_delays.csv"

airline_wide <- read.csv(url)

airline_wide
##   airline  status Los.Angeles Phoenix San.Diego San.Francisco Seattle
## 1  ALASKA on time         497     221       212           503    1841
## 2  ALASKA delayed          62      12        20           102     305
## 3 AM WEST on time         694    4840       383           320     201
## 4 AM WEST delayed         117     415        65           129      61

5. Inspect the Data

str(airline_wide)
## 'data.frame':    4 obs. of  7 variables:
##  $ airline      : chr  "ALASKA" "ALASKA" "AM WEST" "AM WEST"
##  $ status       : chr  "on time" "delayed" "on time" "delayed"
##  $ Los.Angeles  : int  497 62 694 117
##  $ Phoenix      : int  221 12 4840 415
##  $ San.Diego    : int  212 20 383 65
##  $ San.Francisco: int  503 102 320 129
##  $ Seattle      : int  1841 305 201 61
summary(airline_wide)
##       airline        status   Los.Angeles       Phoenix         San.Diego     
##  Length   :4   Length   :4   Min.   : 62.0   Min.   :  12.0   Min.   : 20.00  
##  N.unique :2   N.unique :2   1st Qu.:103.2   1st Qu.: 168.8   1st Qu.: 53.75  
##  N.blank  :0   N.blank  :0   Median :307.0   Median : 318.0   Median :138.50  
##  Min.nchar:6   Min.nchar:7   Mean   :342.5   Mean   :1372.0   Mean   :170.00  
##  Max.nchar:7   Max.nchar:7   3rd Qu.:546.2   3rd Qu.:1521.2   3rd Qu.:254.75  
##                              Max.   :694.0   Max.   :4840.0   Max.   :383.00  
##  San.Francisco      Seattle    
##  Min.   :102.0   Min.   :  61  
##  1st Qu.:122.2   1st Qu.: 166  
##  Median :224.5   Median : 253  
##  Mean   :263.5   Mean   : 602  
##  3rd Qu.:365.8   3rd Qu.: 689  
##  Max.   :503.0   Max.   :1841
colSums(is.na(airline_wide))
##       airline        status   Los.Angeles       Phoenix     San.Diego 
##             0             0             0             0             0 
## San.Francisco       Seattle 
##             0             0

6. Transform the Data from Wide to Long Format

The original dataset is in wide format, with each destination stored in a separate column. I will use pivot_longer() from the tidyr package to transform the data into a tidy long format.

airline_long <- airline_wide %>%
  pivot_longer(
    cols = c(Los.Angeles, Phoenix, San.Diego, San.Francisco, Seattle),
    names_to = "city",
    values_to = "flights"
  )

airline_long
## # A tibble: 20 × 4
##    airline status  city          flights
##    <chr>   <chr>   <chr>           <int>
##  1 ALASKA  on time Los.Angeles       497
##  2 ALASKA  on time Phoenix           221
##  3 ALASKA  on time San.Diego         212
##  4 ALASKA  on time San.Francisco     503
##  5 ALASKA  on time Seattle          1841
##  6 ALASKA  delayed Los.Angeles        62
##  7 ALASKA  delayed Phoenix            12
##  8 ALASKA  delayed San.Diego          20
##  9 ALASKA  delayed San.Francisco     102
## 10 ALASKA  delayed Seattle           305
## 11 AM WEST on time Los.Angeles       694
## 12 AM WEST on time Phoenix          4840
## 13 AM WEST on time San.Diego         383
## 14 AM WEST on time San.Francisco     320
## 15 AM WEST on time Seattle           201
## 16 AM WEST delayed Los.Angeles       117
## 17 AM WEST delayed Phoenix           415
## 18 AM WEST delayed San.Diego          65
## 19 AM WEST delayed San.Francisco     129
## 20 AM WEST delayed Seattle            61

7. Count Analysis

Before comparing percentages, I will summarize the total number of on-time and delayed flights for each airline.

count_analysis <- airline_long %>%
  group_by(airline, status) %>%
  summarise(
    total_flights = sum(flights),
    .groups = "drop"
  )

count_analysis
## # A tibble: 4 × 3
##   airline status  total_flights
##   <chr>   <chr>           <int>
## 1 ALASKA  delayed           501
## 2 ALASKA  on time          3274
## 3 AM WEST delayed           787
## 4 AM WEST on time          6438

8. Overall Airline Performance

To compare the airlines fairly, I will calculate percentages rather than relying only on raw flight counts.

overall_performance <- airline_long %>%
  group_by(airline, status) %>%
  summarise(
    flights = sum(flights),
    .groups = "drop"
  ) %>%
  group_by(airline) %>%
  mutate(
    total_flights = sum(flights),
    percentage = round((flights / total_flights) * 100, 2)
  )

overall_performance
## # A tibble: 4 × 5
## # Groups:   airline [2]
##   airline status  flights total_flights percentage
##   <chr>   <chr>     <int>         <int>      <dbl>
## 1 ALASKA  delayed     501          3775       13.3
## 2 ALASKA  on time    3274          3775       86.7
## 3 AM WEST delayed     787          7225       10.9
## 4 AM WEST on time    6438          7225       89.1

9. Compare Airline Performance by City

Next, I will compare the percentage of on-time and delayed flights for each airline within each destination.

city_performance <- airline_long %>%
  group_by(airline, city, status) %>%
  summarise(
    flights = sum(flights),
    .groups = "drop"
  ) %>%
  group_by(airline, city) %>%
  mutate(
    total_flights = sum(flights),
    percentage = round((flights / total_flights) * 100, 2)
  )

city_performance
## # A tibble: 20 × 6
## # Groups:   airline, city [10]
##    airline city          status  flights total_flights percentage
##    <chr>   <chr>         <chr>     <int>         <int>      <dbl>
##  1 ALASKA  Los.Angeles   delayed      62           559      11.1 
##  2 ALASKA  Los.Angeles   on time     497           559      88.9 
##  3 ALASKA  Phoenix       delayed      12           233       5.15
##  4 ALASKA  Phoenix       on time     221           233      94.8 
##  5 ALASKA  San.Diego     delayed      20           232       8.62
##  6 ALASKA  San.Diego     on time     212           232      91.4 
##  7 ALASKA  San.Francisco delayed     102           605      16.9 
##  8 ALASKA  San.Francisco on time     503           605      83.1 
##  9 ALASKA  Seattle       delayed     305          2146      14.2 
## 10 ALASKA  Seattle       on time    1841          2146      85.8 
## 11 AM WEST Los.Angeles   delayed     117           811      14.4 
## 12 AM WEST Los.Angeles   on time     694           811      85.6 
## 13 AM WEST Phoenix       delayed     415          5255       7.9 
## 14 AM WEST Phoenix       on time    4840          5255      92.1 
## 15 AM WEST San.Diego     delayed      65           448      14.5 
## 16 AM WEST San.Diego     on time     383           448      85.5 
## 17 AM WEST San.Francisco delayed     129           449      28.7 
## 18 AM WEST San.Francisco on time     320           449      71.3 
## 19 AM WEST Seattle       delayed      61           262      23.3 
## 20 AM WEST Seattle       on time     201           262      76.7

10. Create a Clean On-Time Percentage Table

To make the city-by-city comparison easier to interpret, I will display only the on-time percentage for each airline.

on_time_table <- city_performance %>%
  filter(status == "on time") %>%
  select(airline, city, percentage) %>%
  pivot_wider(
    names_from = airline,
    values_from = percentage
  )

on_time_table
## # A tibble: 5 × 3
## # Groups:   city [5]
##   city          ALASKA `AM WEST`
##   <chr>          <dbl>     <dbl>
## 1 Los.Angeles     88.9      85.6
## 2 Phoenix         94.8      92.1
## 3 San.Diego       91.4      85.5
## 4 San.Francisco   83.1      71.3
## 5 Seattle         85.8      76.7

The city-by-city results show that Alaska Airlines had a higher on-time percentage than America West in every destination. However, the overall results showed America West with a higher on-time percentage. This difference occurs because the airlines did not have the same number of flights in each city. America West had a very large number of flights in Phoenix, where its on-time performance was relatively strong, which heavily influenced its overall percentage.

11. Visualize On-Time Performance by City

To make the differences between the two airlines easier to compare, I will create a bar chart of the on-time percentages for each destination.

on_time_chart <- city_performance %>%
  filter(status == "on time") %>%
  ggplot(aes(x = city, y = percentage, fill = airline)) +
  geom_col(position = "dodge") +
  labs(
    title = "On-Time Flight Percentage by City",
    x = "City",
    y = "On-Time Percentage",
    fill = "Airline"
  ) +
  theme_minimal()

on_time_chart

The chart shows that Alaska Airlines had a higher on-time percentage than America West in each of the five cities. The largest differences appear in San Francisco and Seattle, while the percentages are closer in Phoenix.

12. Explain the Difference Between Overall and City-by-City Results

Although America West had a higher overall on-time percentage, Alaska Airlines performed better in every individual city. This happens because the two airlines had very different numbers of flights across the five destinations.

America West had a very large number of flights in Phoenix, where its on-time percentage was relatively high. Because Phoenix made up such a large share of America West’s total flights, it had a strong influence on the airline’s overall percentage.

Alaska Airlines had fewer flights in Phoenix and a larger share of flights in other cities, including Seattle and San Francisco, where the overall on-time percentages were lower. As a result, Alaska’s overall percentage was lower even though it performed better than America West within each individual city.

This is an example of Simpson’s paradox, where a trend that appears within separate groups can reverse when the groups are combined.

13. Overall On-Time Percentage Comparison

overall_on_time <- overall_performance %>%
  filter(status == "on time") %>%
  select(airline, percentage)

overall_on_time
## # A tibble: 2 × 2
## # Groups:   airline [2]
##   airline percentage
##   <chr>        <dbl>
## 1 ALASKA        86.7
## 2 AM WEST       89.1

Overall, America West had an on-time percentage of 89.11%, compared with 86.73% for Alaska Airlines. However, the city-level analysis shows that Alaska had the higher on-time percentage in all five destinations. This confirms that the difference in overall performance is caused by the distribution of flights across cities rather than better performance by America West within each destination.

14. Conclusion

The analysis shows that the way airline performance is summarized can affect the conclusion. When the data is combined across all five cities, America West appears to perform better, with an overall on-time percentage of 89.11% compared with 86.73% for Alaska Airlines.

However, when each destination is examined separately, Alaska Airlines has a higher on-time percentage in all five cities. This difference is caused by the unequal distribution of flights across destinations, especially the large number of America West flights in Phoenix.

This analysis demonstrates why percentages should be examined both overall and within individual groups. Looking only at the overall percentage could lead to a misleading conclusion about which airline actually performs better within each destination. The results provide an example of Simpson’s paradox.

15. References and Resources

The following resources were used as references for creating, cleaning, transforming, analyzing, and presenting the airline delay data:

  1. Course Assignment Data
  • Numbersense, Kaiser Fung, McGraw Hill, 2013. -Provided in Week 5 assignment
  1. tidyr – pivot_longer()
  1. tidyr – Pivoting Data
  1. dplyr – group_by()
  1. dplyr – summarise()
  1. dplyr – mutate()
  1. ggplot2 – Bar Charts
  1. R Markdown Documentation
  • Posit/RStudio. “Dynamic Documents for R.”
  • https://rmarkdown.rstudio.com/docs/
  • Used as a reference for structuring the .Rmd file with Markdown text and executable R code chunks.
  1. R Markdown HTML Output
  1. GitHub Raw CSV File