SPOLIER ALERT!
All code is provided in this document. It would be best if you tried to write the code without this document and then used it for reference as necessary.
This week you practiced tracing a dataset's origin. This week you get your
hands dirty inside the data: wrangling it with dplyr verbs and turning
it into plots with ggplot2. In this 45-minute activity you will rotate
through three short stations built around two classic, built-in R datasets:
penguins (from the palmerpenguins package) and flights (from the
nycflights13 package). At each station you will copy and paste ready-made R
code into RStudio, run it, and read the console output and plots. Then you
will record what trend or pattern you noticed in writing/reflection.md.
By the end of this activity, you should be comfortable using filter(),
select(), mutate(), arrange(), group_by()/summarize(), basic missing
value handling, and ggplot2 to explore a real dataset - and you will have an
optional Shiny app to keep exploring on your own.
By the end of this activity, you will be able to:
- Wrangle data with
dplyr- usefilter(),select(),mutate(),arrange(), andgroup_by()/summarize()to answer questions about a dataset - Handle missing values - detect (
is.na(),sum(),colSums()) and remove (na.omit(),drop_na()) missing values before summarizing - Join related tables - combine two datasets that share a common column with
left_join() - Visualize trends with
ggplot2- build scatter plots, boxplots, bar charts, and histograms, and use color/faceting to compare groups - Read plots critically - describe, in writing, what a plot does and does not show
Note: You do not need to finish every reflection question during class. Anything unfinished should be completed as homework and submitted before the deadline in the main README.
In the given code in src/ the below code has been added to make sure the required packages are installed. If a dependency is not already installed, then the code will automatically make the installation for you. How convenient, right?!
if (!require('tidyverse')) install.packages('tidyverse')
if (!require('palmerpenguins')) install.packages('palmerpenguins')
if (!require('nycflights13')) install.packages('nycflights13')Note: You only need to install a dependency once on your computer. However you must load the code when execute it.
The added code to each of your scrips will also clear out the variables and left-overs variables from previous code executions.
File: src/station_01_penguins_wrangling/explore_penguins_wrangling.R
Data: penguins (built into the palmerpenguins package)
The penguins dataset comes from a real research project at Palmer Station,
Antarctica: researchers measured bill length, bill depth, flipper length, and
body mass for three penguin species (Adelie, Chinstrap, Gentoo) across three
islands. A few measurements are missing because not every penguin could be
fully measured in the field.
Replace # TODO: Load the tidyverse and palmerpenguins libraries with:
library(tidyverse)
library(palmerpenguins)Replace # TODO: Preview the structure and first few rows of the penguins data with:
str(penguins)
head(penguins)Replace # TODO: Count total missing values, and missing values per column with:
sum(is.na(penguins))
colSums(is.na(penguins))Replace # TODO: Remove rows with any missing values and save as penguins_clean with:
penguins_clean <- na.omit(penguins)
nrow(penguins)
nrow(penguins_clean)Replace # TODO: Filter penguins_clean to only Gentoo penguins, save as gentoo with:
gentoo <- penguins_clean %>%
filter(species == "Gentoo")Replace # TODO: Add a new column body_mass_kg (body_mass_g / 1000) using mutate() with:
penguins_clean <- penguins_clean %>%
mutate(body_mass_kg = round(body_mass_g / 1000, 2))Replace # TODO: Group by species and summarize average bill length, average body mass (kg), and count of penguins per species with:
penguins_summary <- penguins_clean %>%
group_by(species) %>%
summarize(
avg_bill_length = round(mean(bill_length_mm), 1),
avg_body_mass_kg = round(mean(body_mass_kg), 2),
n = n()
)
penguins_summaryReplace # TODO: Arrange the summary table in descending order of average body mass with:
penguins_summary %>%
arrange(desc(avg_body_mass_kg))- What trend did you notice among the three species in average bill length or body mass?
- How many rows were dropped when you removed missing values, and why does that matter for the summary numbers you calculated?
File: src/station_02_penguins_visualization/explore_penguins_visualization.R
Data: penguins (built into the palmerpenguins package)
Replace # TODO: Load the tidyverse and palmerpenguins libraries with:
library(tidyverse)
library(palmerpenguins)Replace # TODO: Remove rows with any missing values and save as penguins_clean with:
penguins_clean <- na.omit(penguins)Replace # TODO: Scatter plot of bill_length_mm vs. bill_depth_mm, colored by species with:
ggplot(penguins_clean, aes(x = bill_length_mm, y = bill_depth_mm, color = species)) +
geom_point(size = 2, alpha = 0.7) +
labs(
title = "Bill Length vs. Bill Depth by Species",
x = "Bill Length (mm)", y = "Bill Depth (mm)", color = "Species"
)Replace # TODO: Boxplot of body_mass_g by species with:
ggplot(penguins_clean, aes(x = species, y = body_mass_g, fill = species)) +
geom_boxplot(alpha = 0.7) +
labs(title = "Body Mass by Species", x = "Species", y = "Body Mass (g)") +
theme(legend.position = "none")Replace # TODO: Bar chart of the number of penguins observed on each island with:
ggplot(penguins_clean, aes(x = island, fill = species)) +
geom_bar() +
labs(title = "Penguins Observed per Island", x = "Island", y = "Count", fill = "Species")Replace # TODO: Facet the bill_length_mm vs. bill_depth_mm scatter plot by island with:
ggplot(penguins_clean, aes(x = bill_length_mm, y = bill_depth_mm, color = species)) +
geom_point(size = 2, alpha = 0.7) +
facet_wrap(~ island) +
labs(
title = "Bill Length vs. Bill Depth by Species, Faceted by Island",
x = "Bill Length (mm)", y = "Bill Depth (mm)", color = "Species"
)Please respond in writing/reflection.md.
- Describe one visual pattern from your scatterplot or boxplot that surprised you or confirmed what you expected.
- Why might faceting or coloring by species reveal a pattern that the overall summary table from Station 1 hides?
File: src/station_03_nycflights_wrangling_viz/explore_flights.R
Data: flights and airlines (built into the nycflights13 package)
The flights dataset is every flight that departed New York City airports
(JFK, LGA, EWR) in 2013 - over 336,000 rows. The airlines dataset is a
small lookup table that maps each two-letter carrier code (e.g. "UA") to
its full airline name (e.g. "United Air Lines Inc.").
Replace # TODO: Load the tidyverse and nycflights13 libraries with:
library(tidyverse)
library(nycflights13)Replace # TODO: Preview the structure and first few rows of flights and airlines with:
str(flights)
head(flights)
airlinesReplace # TODO: Count total missing values in dep_delay and arr_delay with:
sum(is.na(flights$dep_delay))
sum(is.na(flights$arr_delay))Replace # TODO: Remove rows with missing dep_delay or arr_delay, save as flights_clean with:
flights_clean <- flights %>%
filter(!is.na(dep_delay), !is.na(arr_delay))
nrow(flights)
nrow(flights_clean)Replace # TODO: Join flights_clean with airlines by "carrier" to add the full airline name, save as flights_named with:
flights_named <- flights_clean %>%
left_join(airlines, by = "carrier")Replace # TODO: Group by airline name and summarize average departure delay and number of flights, then arrange from highest to lowest average delay with:
delay_by_airline <- flights_named %>%
group_by(name) %>%
summarize(
avg_dep_delay = round(mean(dep_delay), 1),
n_flights = n()
) %>%
arrange(desc(avg_dep_delay))
delay_by_airlineReplace # TODO: Bar chart of average departure delay by airline name with:
ggplot(delay_by_airline, aes(x = reorder(name, avg_dep_delay), y = avg_dep_delay)) +
geom_col(fill = "steelblue") +
coord_flip() +
labs(
title = "Average Departure Delay by Airline (2013)",
x = "Airline", y = "Average Departure Delay (minutes)"
)Replace # TODO: Histogram of arrival delay (arr_delay) across all flights with:
ggplot(flights_clean, aes(x = arr_delay)) +
geom_histogram(binwidth = 15, fill = "darkorange", color = "white") +
coord_cartesian(xlim = c(-60, 180)) +
labs(
title = "Distribution of Arrival Delays (2013)",
x = "Arrival Delay (minutes)", y = "Number of Flights"
)Please respond in writing/reflection.md.
- Which airline had the highest average departure delay in your table? Was that what you expected?
- The
flightsdata has missingdep_delay/arr_delayvalues (these are usually cancelled flights). How did removing them change what your summary and plots can tell you?
Once you finish all three stations, open shiny_app/app.R in RStudio and
click Run App. Pick a dataset, choose variables and a plot type, and use
the Show Code button to see the exact dplyr/ggplot2 code behind
whatever you built. See the main README for details.
Finish the General Reflection question in writing/reflection.md,
thinking back across all three stations and (if you tried it) the Shiny app.
