Lesson 14 of 17 · Week 07 · Thu Nov 5
dplyr II: groups and joins
Questions
- How do I compute a summary for every group at once?
- How do I combine information from two tables?
Objectives
- Use
group_by()withsummarize(),n(),mutate()andslice_sample(). - Group by more than one column.
- Combine tables with
left_join()andinner_join(), and find gaps withanti_join().
Split, apply, combine
Many questions are about groups: the mean life expectancy per continent, the richest country in each
year. dplyr answers them in two steps: group_by() splits the rows into groups, and the next verb works
within each group. Then the results are combined into one table.
library(dplyr)
gm |>
group_by(continent) |>
summarize(mean_lifeExp = mean(lifeExp),
n_rows = n())
summarize() (or summarise()) collapses each group to one row. n() counts rows in the
group; n_distinct(country) counts different countries. Group by several columns for one row per combination:
group_by(continent, year). count(continent) is a shortcut for grouping and counting.
Adapted from Software Carpentry's “Data Frame Manipulation with dplyr” episode (CC BY 4.0, The Carpentries). Text, examples and exercises have been rewritten for this course.
Groups with the other verbs
gm |>
group_by(year) |>
mutate(rank_in_year = min_rank(desc(lifeExp))) |> # ranked within each year
filter(rank_in_year <= 3) |>
arrange(year, rank_in_year)
gm |>
filter(year == 2007) |>
group_by(continent) |>
slice_sample(n = 2) # 2 random rows from each continent
After a grouped summarize(), dplyr drops the last grouping level. Use ungroup() when you're done
with groups, to avoid surprises later in the pipe.
Joining tables
Information often lives in separate tables that share a key column. A join matches rows by that key:
capitals <- data.frame(country = c("Chile", "Kenya", "Japan", "Peru"),
capital = c("Santiago", "Nairobi", "Tokyo", "Lima"))
gm07 <- filter(gm, year == 2007)
left_join(gm07, capitals, by = "country") # all gm07 rows; capital is NA where there's no match
inner_join(gm07, capitals, by = "country") # only rows that match in both
anti_join(gm07, capitals, by = "country") # gm07 rows with NO match - great for spotting gaps
After a join, always check the number of rows. If it grew, some keys appear more than once in the second table.
Exercises
Each exercise gives you up to 10 checked attempts. Use Run as many times as you like to experiment first, then click Check answer when you're ready. Your exercises use numbers/subsets unique to you, so answers won't match a classmate's exactly.
Exercise 1 — Longest and shortest lives
0 / 10 attempts usedUsing only the years from from_year on (click Run), compute each country's average
life expectancy in by_country, a data frame with columns country and mean_lifeExp.
Then store the names of the countries with the longest and shortest average in longest and
shortest (as text).
Exercise 2 — Per continent, per year
0 / 10 attempts usedMake cont_year with one row per continent and year and columns continent,
year, n_countries (how many countries) and median_gdp (median GDP per capita).
Exercise 3 — A random pair from each continent
0 / 10 attempts usedFor year yr (click Run), pick 2 random countries from each continent
with slice_sample(), compute the mean life expectancy of each pair, and arrange the result with the continent
names in reverse alphabetical order. Store it in pairs, with columns continent
and mean_lifeExp. (Your numbers will change each run. That's expected.)
Exercise 4 — Join a lookup table
0 / 10 attempts usedClick Run to see langs, a small table of countries and an official language. Some of its
countries aren't in gm, and some of gm's aren't in it. For year yr:
with_lang: every country ingmthat year, plus alanguagecolumn (NAwhere unknown);n_matched: how many of those rows have a known language.
Exercise 5 — What's missing?
0 / 10 attempts usedUsing langs again: store in no_lang the names (text) of the gm countries that have
no entry in langs, and in not_in_gm the countries in langs that
aren't in gm. Use anti_join() for both. Order matters: which table goes first?
Key Points
group_by()+summarize(): one row per group.- Verbs after
group_by()work within each group;ungroup()when done. left_join()keeps every row of the first table;anti_join()shows what didn't match.- Check the row count after every join.
Proof of completion
Once you've attempted every exercise above, download a PDF summary of your work on this lesson — your name, the exercises you passed, attempt counts, timing, and your final code for each.