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)
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.
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
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
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
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
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
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
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.
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.
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.
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.
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.
The following resources were used as references for creating, cleaning, transforming, analyzing, and presenting the airline delay data:
pivot_longer() and pivot_wider()..Rmd file with
Markdown text and executable R code chunks.