[1] TRUE
[1] FALSE
[1] TRUE
H. Sherry Zhang
Department of Statistics and Data Sciences
University of Texas at Austin
library(usethis) create_from_github("SDS322E-26FALL/0202-dplyr", fork = FALSE)
We will learn the five most basic dplyr verbs to wrangle data, including:
filter(): filter rows by a predicatemutate(): create or modify variablesgroup_by(): group data by one or more variablessummarize(): summarize data by groupsarrange(): sort data by one or more variablesThese are the fundamentals for building up more complex data wrangling…
By the end of the class, you are expected to write code to answer question like this:
Artwork by @allison_horst
==, !=a == b checks whether a is equal to ba != b checks whether a is NOT equal to bIn the flights data:
# A tibble: 27,004 × 19
year month day dep_time sched_dep_time dep_delay arr_time
<int> <int> <int> <int> <int> <dbl> <int>
1 2013 1 1 517 515 2 830
2 2013 1 1 533 529 4 850
3 2013 1 1 542 540 2 923
4 2013 1 1 544 545 -1 1004
5 2013 1 1 554 600 -6 812
# ℹ 26,999 more rows
# ℹ 12 more variables: sched_arr_time <int>, arr_delay <dbl>,
# carrier <chr>, flight <int>, tailnum <chr>, origin <chr>,
# dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
# minute <dbl>, time_hour <dttm>
%in%For multiple values, you need%in%:
a %in% c(x1, x2, ...) checks
a is one of the values in the vector c(x1, x2, ...)!a %in% c(x1, x2, ...) checks
a is NOT one of the values in the vector c(x1, x2, ...)In the flights data:
# A tibble: 55,838 × 19
year month day dep_time sched_dep_time dep_delay arr_time
<int> <int> <int> <int> <int> <dbl> <int>
1 2013 1 1 517 515 2 830
2 2013 1 1 533 529 4 850
3 2013 1 1 542 540 2 923
4 2013 1 1 544 545 -1 1004
5 2013 1 1 554 600 -6 812
# ℹ 55,833 more rows
# ℹ 12 more variables: sched_arr_time <int>, arr_delay <dbl>,
# carrier <chr>, flight <int>, tailnum <chr>, origin <chr>,
# dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
# minute <dbl>, time_hour <dttm>
&, |You can also combine multiple predicate functions together with & (and) and | (or).
[1] FALSE
[1] TRUE
In the flights data:
# A tibble: 593 × 19
year month day dep_time sched_dep_time dep_delay arr_time
<int> <int> <int> <int> <int> <dbl> <int>
1 2013 1 1 848 1835 853 1001
2 2013 1 1 957 733 144 1056
3 2013 1 1 1114 900 134 1447
4 2013 1 1 1540 1338 122 2020
5 2013 1 1 1815 1325 290 2120
# ℹ 588 more rows
# ℹ 12 more variables: sched_arr_time <int>, arr_delay <dbl>,
# carrier <chr>, flight <int>, tailnum <chr>, origin <chr>,
# dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
# minute <dbl>, time_hour <dttm>
You can also write it as:
# A tibble: 593 × 19
year month day dep_time sched_dep_time dep_delay arr_time
<int> <int> <int> <int> <int> <dbl> <int>
1 2013 1 1 848 1835 853 1001
2 2013 1 1 957 733 144 1056
3 2013 1 1 1114 900 134 1447
4 2013 1 1 1540 1338 122 2020
5 2013 1 1 1815 1325 290 2120
# ℹ 588 more rows
# ℹ 12 more variables: sched_arr_time <int>, arr_delay <dbl>,
# carrier <chr>, flight <int>, tailnum <chr>, origin <chr>,
# dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
# minute <dbl>, time_hour <dttm>
dplyr syntaxDATA |> filter(PREDICATE)
# basic
flights |> filter(dep_delay > 120)
# by a single value
flights |> filter(month == 1)
# by multiple value
flights |> filter(month %in% c(1, 3))
# by negation
flights |> filter(month != 1)
flights |> filter(!month %in% c(1, 3))
# by multiple condition
flights |> filter(month == 1 & dep_delay > 120)
flights |> filter(month == 1, dep_delay > 120)
flights |> filter(month == 1 | dep_delay > 120)# A tibble: 27,004 × 19
year month day dep_time sched_dep_time dep_delay arr_time
<int> <int> <int> <int> <int> <dbl> <int>
1 2013 1 1 517 515 2 830
2 2013 1 1 533 529 4 850
3 2013 1 1 542 540 2 923
4 2013 1 1 544 545 -1 1004
5 2013 1 1 554 600 -6 812
# ℹ 26,999 more rows
# ℹ 12 more variables: sched_arr_time <int>, arr_delay <dbl>,
# carrier <chr>, flight <int>, tailnum <chr>, origin <chr>,
# dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
# minute <dbl>, time_hour <dttm>
Apply the predicate functions to answer the following questions:
JFKJFK in JanuaryEWR and LGA and not in JanuaryYou may start from:
JFKJFK and LGA in JanuaryArtwork by @allison_horst
mutate() syntaxDATA |> mutate(VARIABLE = EXPRESSION)
If VARIABLE already exists, it modifies the column; otherwise, it will create a new one.
# A tibble: 336,776 × 20
year month day dep_time sched_dep_time dep_delay arr_time
<int> <int> <int> <int> <int> <dbl> <int>
1 2013 1 1 517 515 2 830
2 2013 1 1 533 529 4 850
3 2013 1 1 542 540 2 923
4 2013 1 1 544 545 -1 1004
5 2013 1 1 554 600 -6 812
# ℹ 336,771 more rows
# ℹ 13 more variables: sched_arr_time <int>, arr_delay <dbl>,
# carrier <chr>, flight <int>, tailnum <chr>, origin <chr>,
# dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
# minute <dbl>, time_hour <dttm>, gain <dbl>
These two are identical:
# A tibble: 336,776 × 21
year month day dep_time sched_dep_time
<int> <int> <int> <int> <int>
1 2013 1 1 517 515
2 2013 1 1 533 529
3 2013 1 1 542 540
4 2013 1 1 544 545
5 2013 1 1 554 600
# ℹ 336,771 more rows
# ℹ 16 more variables: dep_delay <dbl>,
# arr_time <int>, sched_arr_time <int>,
# arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>,
# air_time <dbl>, distance <dbl>, hour <dbl>,
# minute <dbl>, time_hour <dttm>, gain <dbl>, …
# A tibble: 336,776 × 21
year month day dep_time sched_dep_time
<int> <int> <int> <int> <int>
1 2013 1 1 517 515
2 2013 1 1 533 529
3 2013 1 1 542 540
4 2013 1 1 544 545
5 2013 1 1 554 600
# ℹ 336,771 more rows
# ℹ 16 more variables: dep_delay <dbl>,
# arr_time <int>, sched_arr_time <int>,
# arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>,
# air_time <dbl>, distance <dbl>, hour <dbl>,
# minute <dbl>, time_hour <dttm>, gain <dbl>, …
Read the documentation of mutate() and modify the following code to put the gain column:
day variable, andgain columnWhy these arguments have “.” in front of everything?
after for the number of mins after the scheduled timeafter is also an argument name inside mutate(), it will then be confusing whether you are referring to the column, after, or the argument.. avoids this problem – it’s a good practice.Illustration by Andrew Heiss
Illustration by Andrew Heiss
Illustration by Andrew Heiss
flights dataDATA |> group_by(VARIABLEs) |> summarize(EXPRESSION)
Example:
# A tibble: 336,776 × 19
# Groups: month [12]
year month day dep_time sched_dep_time
<int> <int> <int> <int> <int>
1 2013 1 1 517 515
2 2013 1 1 533 529
3 2013 1 1 542 540
4 2013 1 1 544 545
5 2013 1 1 554 600
# ℹ 336,771 more rows
# ℹ 14 more variables: dep_delay <dbl>,
# arr_time <int>, sched_arr_time <int>,
# arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>,
# air_time <dbl>, distance <dbl>, hour <dbl>,
# minute <dbl>, time_hour <dttm>
The header tells you that the data is grouped by month and there are 12 groups (12 months).
Why we get all the NAs here?
summarize(), summarise(), and summary()summarize()/ summarise() are dplyr verbs to summarize groups in a way you specifiedsummary() is a base R function to provide the 5 number summary (min, quantile, median, mean, max) for each variable in a data frameflights |>
group_by(month, origin) |>
summarize(avg_dep_delay = mean(dep_delay, na.rm = TRUE),
avg_arr_delay = mean(arr_delay, na.rm = TRUE))# A tibble: 36 × 4
# Groups: month [12]
month origin avg_dep_delay avg_arr_delay
<int> <chr> <dbl> <dbl>
1 1 EWR 14.9 12.8
2 1 JFK 8.62 1.37
3 1 LGA 5.64 3.38
4 2 EWR 13.1 8.78
5 2 JFK 11.8 4.39
# ℹ 31 more rows
Separate summarize() into two commands means summarizing avg_dep_delay first, then take the result of the first summary, summarize avg_arr_delay:
Error in `summarize()`:
ℹ In argument: `avg_arr_delay = mean(arr_delay, na.rm = TRUE)`.
ℹ In group 1: `month = 1`.
Caused by error:
! object 'arr_delay' not found
Apply the group_by() + summarize() syntax to calculate the average flight distance for each of the three origins. Your results should look like this:
# A tibble: 3 × 2
origin distance
<chr> <dbl>
1 EWR 1057.
2 JFK 1266.
3 LGA 780.
Hint:
arrange()Sometimes, we may wish to have the result sorted by a variable, this can be done with arrange():
Sort by decreasing order can be done with either - or desc():
flights |>
group_by(carrier) |>
summarize(avg_dep_delay =
mean(arr_delay, na.rm = TRUE)) |>
arrange(-avg_dep_delay)# A tibble: 16 × 2
carrier avg_dep_delay
<chr> <dbl>
1 F9 21.9
2 FL 20.1
3 EV 15.8
4 YV 15.6
5 OO 11.9
6 MQ 10.8
7 WN 9.65
8 B6 9.46
9 9E 7.38
10 UA 3.56
11 US 2.13
12 VX 1.76
13 DL 1.64
14 AA 0.364
15 HA -6.92
16 AS -9.93
flights |>
group_by(carrier) |>
summarize(avg_dep_delay =
mean(arr_delay, na.rm = TRUE)) |>
arrange(desc(avg_dep_delay))# A tibble: 16 × 2
carrier avg_dep_delay
<chr> <dbl>
1 F9 21.9
2 FL 20.1
3 EV 15.8
4 YV 15.6
5 OO 11.9
6 MQ 10.8
7 WN 9.65
8 B6 9.46
9 9E 7.38
10 UA 3.56
11 US 2.13
12 VX 1.76
13 DL 1.64
14 AA 0.364
15 HA -6.92
16 AS -9.93
Can you improve the previous group_by() and summarize() code to show the distance sorted from small to large as this:
# A tibble: 3 × 2
origin distance
<chr> <dbl>
1 LGA 780.
2 EWR 1057.
3 JFK 1266.
?
Hint
dplyrDo you know that US Department of Transportation (DoT) says you’re entitled to a refund if the consumer is scheduled to arrive at the destination airport 3 hours more for more domestic itineraries?
dplyrAirline: How many of our flights are 3 hrs+ late?
Task: We want to g the proportion of flights with arrival delay larger than 3 hours.
Thought process:
This sounds like a mutate() and we learn the “larger than 3 hrs” part in filter()
# A tibble: 336,776 × 2
arr_delay over_3h_delay
<dbl> <lgl>
1 11 FALSE
2 20 FALSE
3 33 FALSE
4 -18 FALSE
5 -25 FALSE
6 12 FALSE
7 19 FALSE
8 -14 FALSE
9 -8 FALSE
10 8 FALSE
11 -2 FALSE
12 -3 FALSE
13 7 FALSE
14 -14 FALSE
15 31 FALSE
16 -4 FALSE
17 -8 FALSE
18 -7 FALSE
19 12 FALSE
20 -6 FALSE
# ℹ 336,756 more rows
Task: We want to summarize the proportion of flights with departure delay larger than 3 hours.
Thought process:
This sounds like group_by() and summarize(), but I want what’s inside summarise() to be the count
Task: We want to summarize the proportion of flights with departure delay larger than 3 hours.
Thought process:
n.This sounds like mutate() again
What do these NA rows look like?
Can we look at those NAs? Yes!
# A tibble: 9,430 × 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 1 1525 1530 -5 1934 1805
2 2013 1 1 1528 1459 29 2002 1647
3 2013 1 1 1740 1745 -5 2158 2020
4 2013 1 1 1807 1738 29 2251 2103
5 2013 1 1 1939 1840 59 29 2151
# ℹ 9,425 more rows
# ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
Do you wonder why the following happens?
# A tibble: 0 × 19
# ℹ 19 variables: year <int>, month <int>, day <int>, dep_time <int>,
# sched_dep_time <int>, dep_delay <dbl>, arr_time <int>,
# sched_arr_time <int>, arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
This is not legit because comparing anything with NA gives an NA (rather than giving FALSE):
You should always use is.na(VAR) or !is.na(VAR) to check whether a variable contains NA values.
group_by(over_2h_delay) |> summarise(n = length(over_3h_delay)) can be simplified with a single command dplyr::count(over_2h_delay).
Data analysis problem rarely tell you exactly what steps to use: you need to understand the context and solve it using the appropriate dplyr verbs. You may also want to ask
It is neither practical nor necessary to cover all the dplyr and related syntax upfront, so we will learn more as we go. In our example, we pick up the following:
n() and count()NAsCan you reproduce the code we just walked through?
Here is the step breakdown if you need:
n.Are the delays coming from all three origins, or are they concentrated at a particular origin?
# A tibble: 3 × 2
# Groups: origin [3]
origin n
<chr> <int>
1 EWR 1515
2 JFK 1158
3 LGA 1170
For flights delayed by 3+ hours, how many flights fall into each hourly delay category?
What are the records for flights with delays of more than 10 hours
# A tibble: 39 × 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 1 848 1835 853 1001 1950
2 2013 1 9 641 900 1301 1242 1530
3 2013 1 10 1121 1635 1126 1239 1810
4 2013 1 13 1809 810 599 2054 1042
5 2013 10 14 2042 900 702 2255 1127
# ℹ 34 more rows
# ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
With the mtcars data, try the following:
mpg variable into kpl (1 mpg = 0.425144 km/l)kpl and disp for each number of cylindersdisp in descending order| Item | Available | Due | Mode |
|---|---|---|---|
| Lab 1 | Week 3 Tue Sep 8 12am |
Week 3 Tue Sep 8 11:59pm |
Complete during the lab session in your lab group |
| HW 1 | Week 3 Thur Sep 10 12am |
Week 4 Thur Sep 17 11:59pm |
Complete individually |
| Lab 2 | Week 4 Tue Sep 15 12am |
Week 4 Tue Sep 15 11:59pm |
Complete during the lab session in your lab group |
| HW 2 | Week 4 Thur Sep 17 12am |
Week 5 Thur Sep 24 11:59pm |
Complete individually |
| Lab 3 | Week 5 Tue Sep 22 12am |
Week 5 Tue Sep 22 11:59pm |
Complete during the lab session in your lab group |
| HW 3 | Week 5 Thur Sep 24 12am |
Week 6 Thur Oct 01 11:59pm |
Complete individually |