We are tasked with recreating a .csv file provided for us in the assignment. We are free to use any software, including SQL of our choosing, and read it into R for analysis and data manipulation in order to determine which airline has better on-time performance. Is there one carrier who is more reliable than the other and does their location matter?
My plan is to recreate the table in Excel, save it as a .csv file and load it in my Github repository. From there, I will import the file into R using the read_csv function into r. Next I will tidy the data, including pivoting from wide to long format and other exploratory data analysis (EDA) to generate sufficient data that support my final answer.
Create the data
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.2.1 ✔ readr 2.2.0
✔ forcats 1.0.1 ✔ stringr 1.6.0
✔ ggplot2 4.0.3 ✔ tibble 3.3.1
✔ lubridate 1.9.5 ✔ tidyr 1.3.2
✔ purrr 1.2.2
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(ggplot2)library(kableExtra)
Attaching package: 'kableExtra'
The following object is masked from 'package:dplyr':
group_rows
Read file from Github
Using “read_csv” I imported the raw file from my github repository.
Rows: 5 Columns: 7
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (2): airline, status
dbl (5): Los Angeles, Phoenix, San Diego, San Francisco, Seattle
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
airline_delay
# A tibble: 5 × 7
airline status `Los Angeles` Phoenix `San Diego` `San Francisco` Seattle
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Alaska on time 497 221 212 503 1841
2 <NA> delayed 62 12 20 102 305
3 <NA> <NA> NA NA NA NA NA
4 AM WEST on time 694 4840 383 320 201
5 <NA> delayed 117 415 65 129 61
str(airline_delay)
spc_tbl_ [5 × 7] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
$ airline : chr [1:5] "Alaska" NA NA "AM WEST" ...
$ status : chr [1:5] "on time" "delayed" NA "on time" ...
$ Los Angeles : num [1:5] 497 62 NA 694 117
$ Phoenix : num [1:5] 221 12 NA 4840 415
$ San Diego : num [1:5] 212 20 NA 383 65
$ San Francisco: num [1:5] 503 102 NA 320 129
$ Seattle : num [1:5] 1841 305 NA 201 61
- attr(*, "spec")=
.. cols(
.. airline = col_character(),
.. status = col_character(),
.. `Los Angeles` = col_double(),
.. Phoenix = col_double(),
.. `San Diego` = col_double(),
.. `San Francisco` = col_double(),
.. Seattle = col_double()
.. )
- attr(*, "problems")=<pointer: 0x000001cef1afc1e0>
Remove empty rows; fill empty cells
After importing the file, I see that row three is entirely empty, so I will remove it. Afterwards I will use the fill function to carry the airline names downward to fill the empty N/A cells with the same data.
#install.packages("janitor")library(janitor)
Attaching package: 'janitor'
The following objects are masked from 'package:stats':
chisq.test, fisher.test
airline_delay_mod <-remove_empty(airline_delay, "rows")airline_delay_mod <- airline_delay_mod|>fill(airline, .direction ="down")#Capitalize the first letter of the first two columnsairline_delay_mod <- airline_delay_mod |>rename_with(str_to_title, .cols =1:2)kable(airline_delay_mod, caption ="Tidy Airline Delay")
Tidy Airline Delay
Airline
Status
Los Angeles
Phoenix
San Diego
San Francisco
Seattle
Alaska
on time
497
221
212
503
1841
Alaska
delayed
62
12
20
102
305
AM WEST
on time
694
4840
383
320
201
AM WEST
delayed
117
415
65
129
61
Pivot to long data frame
Now that my data is “tidy” with missing values replaced, I will now pivot it to a long format to convert the city columns into two variables, Destinations and Flights. Transforming the data into this manner facilitates grouping and analying the dataset.
# A tibble: 20 × 4
Airline Status Destination Flights
<chr> <chr> <chr> <dbl>
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
Compare count and percentage of on-time flights for the two airlines.
Here we see that AM WEST has the lowest overall delay rate at 10.9% compared to Alaska’s 13.3%. Whereas the two airlines are pretty close in their respective on-time rates with AM West leading at 89.1% compared to Alaska’s 86.7%
##Let’s focus on on-time arrival rates between two by using the filter function
overall_performance %>%filter(Status =="on time") %>%ggplot(aes(x = Airline, y = Percentage, fill = Airline)) +geom_col(width =0.6, show.legend =FALSE) +geom_text(aes(label =paste0(round(Percentage, 1), "%")),vjust =-0.4 ) +labs(title ="Overall Percentage of On-Time Flights",x =NULL,y ="On Time (%)" ) +theme_classic()
Overall AM West had a slightly better on-time arrival rate than Alaska, however this comparison may be somewhat skewed. Other factors such as destination may tell a different story.
Compare count and percentage of on-time flights for the two airlines across five cities.
Key takeaways on City specific On-time performance
1.This graph indicates that Alaska outperforms AM West across the board For each city—Los Angeles, Phoenix, San Diego, San Francisco, and Seattle—Alaska’s bar is higher. Even without exact numbers, the visual gap is obvious.
2.The performance gap varies by destination Largest gap: Likely San Francisco or Seattle, where Alaska’s bar is much higher.
Smallest gap: Possibly Phoenix, where the difference looks narrower.
This suggests that AM West struggles more in certain markets than others.
Both airlines show destination‑specific variability Some cities have noticeably higher on‑time percentages for both airlines (e.g., Seattle), while others show lower performance (e.g., San Francisco).
Alaska’s operational consistency stands out The red bars (Alaska) stay relatively high and stable across destinations. AM West’s teal bars fluctuate more and generally sit lower.