## Warning in file(filename, "r", encoding = encoding): URL
## 'https://metrics.rstudioprimers.com/learnr/installClient': status was 'SSL
## connect error'
[1] “Warning: An error occurred with the client code.”
Welcome
Boxplots display the relationship between a continuous variable and a categorical variable. Count plots display the relationship between two categorical variables. In this tutorial, you will learn how to use both. You will learn how to:
- Make and interpret boxplots
- Rotate boxplots by flipping the coordinate system of your plot
- Use violin plots and dotplots, two geoms that are similar to boxplots
- Make and interpret count plots
The tutorial is adapted from R for Data Science by Hadley Wickham and Garrett Grolemund, published by O’Reilly Media, Inc., 2016, ISBN: 9781491910399. You can purchase the book at shop.oreilly.com.
The tutorial uses the ggplot2 and dplyr packages, which have been pre-loaded for your convenience.
Boxplots
Introduction
Exercise 1 - Boxplots
How to make a boxplot
To make a boxplot with ggplot2, add geom_boxplot()
to the ggplot2 template. For example, the code below uses boxplots to display the relationship between the class
and hwy
variables in the mpg
dataset, which comes with ggplot2.
ggplot(data = mpg) +
geom_boxplot(mapping = aes(x = class, y = hwy))
Categorical and continuous
geom_boxplot()
expects the \(y\) axis to be continuous, but accepts categorical variables on the \(x\) axis. For example, here class
is categorical. geom_boxplot()
will automatically plot a separate boxplot for each value of \(x\). This makes it easy to compare the distributions of points with different values of \(x\).
Exercise 2 - Interpretation
Exercise 3 - Make a Boxplot
Recreate the boxplot below with the diamonds data set.
ggplot(data = diamonds) +
geom_boxplot(mapping = aes(x = cut, y = price))
Outliers
You can change how outliers look in your boxplot with the parameters outlier.color
, outlier.fill
, outlier.shape
, outlier.size
, outlier.stroke
, and outlier.alpha
(outlier.shape
takes a number from 1 to 25).
Unfortunately, you can’t tell geom_boxplot()
to ignore outliers completely, but you can make outliers disappear by setting outlier.alpha = 0
. Try it in the plot below.
ggplot(data = diamonds) +
geom_boxplot(mapping = aes(x = cut, y = price), outlier.shape = 24,
outlier.fill = "white", outlier.stroke = 0.25)
ggplot(data = diamonds) +
geom_boxplot(mapping = aes(x = cut, y = price), outlier.alpha = 0)
Aesthetics
Boxplots recognize the following aesthetics: alpha, color, fill, group, linetype, shape, size, and weight.
Of these group can be the most useful. Consider the plot below. It uses a continuous variable on the \(x\) axis. As a result, geom_boxplot()
is not sure how to split the data into categories: it lumps all of the data into a single boxplot. The result reveals little about the relationship between carat and price.
In the next sections, we’ll use group to make a more informative plot.
How to “cut” a continuous variable
ggplot2 provides three helper functions that you can use to split a continuous variable into categories. Each takes a continuous vector and returns a categorical vector that assigns each value to a group. For example, cut_interval()
bins a vector into n
equal length bins.
continuous_vector <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
continuous_vector
## [1] 1 2 3 4 5 6 7 8 9 10
cut_interval(continuous_vector, n = 3)
## [1] [1,4] [1,4] [1,4] [1,4] (4,7] (4,7] (4,7] (7,10] (7,10] (7,10]
## Levels: [1,4] (4,7] (7,10]
The cut functions
The three cut functions are
cut_interval()
which makesn
groups with equal rangecut_number()
which makesn
groups with (approximately) equal numbers of observationscut_width()
which makes groups with widthwidth
Use one of three functions below to bin continuous_vector
into groups of width = 2
.
## [1] 1 2 3 4 5 6 7 8 9 10
continuous_vector
[1] 1 2 3 4 5 6 7 8 9 10
cut_width(continuous_vector, width = 2)
Exercise 4 - Apply a cut function
When you set the \(group\) aesthetic of a boxplot, geom_boxplot()
will draw a separate boxplot for each collection of observations that have the same value of whichever vector you map to \(group\).
This means we can split our carat
plot by mapping \(group\) to the output of a cut function, as in the code below. Study the code, then modify it to create a separate boxplot for each 0.25 wide interval of carat
.
ggplot(data = diamonds) +
geom_boxplot(mapping = aes(x = carat, y = price, group = cut_interval(carat, n = 2)))
ggplot(data = diamonds) +
geom_boxplot(mapping = aes(x = carat, y = price, group = cut_width(carat, width = 0.25)))
coord_flip()
geom_boxplot()
always expects the categorical variable to appear on the \(x\) axis, which create horizontal boxplots. But what if you’d like to make horizontal boxplots, like in the plot below?
You can do this by adding + coord_flip()
to your plot call.
Exercise 5 - Horizontal boxplots
Extend the code below to orient the boxplots horizontally.
ggplot(data = mpg) +
geom_boxplot(mapping = aes(x = class, y = hwy))
ggplot(data = mpg) +
geom_boxplot(mapping = aes(x = class, y = hwy)) +
coord_flip()
Similar Geoms
geom_dotplot()
Boxplots provide a quick way to represent a distribution, but they leave behind a lot of information. ggplot2 supplements boxplots with two geoms that show more information.
The first is geom_dotplot()
. If you set the binaxis
parameter of geom_dotplot()
to "y"
, geom_dotplot()
behaves like geom_boxplot()
, display a separate distribution for each group of data.
Here each group functions like a vertical histogram. Add the parameter stackdir = "center"
then re-run the code. Can you interpret the results?
ggplot(data = mpg) +
geom_dotplot(mapping = aes(x = class, y = hwy), binaxis = "y",
dotsize = 0.5, binwidth = 1)
ggplot(data = mpg) +
geom_dotplot(mapping = aes(x = class, y = hwy), binaxis = "y",
dotsize = 0.5, binwidth = 1, stackdir = "center")
geom_violin()
geom_violin()
provides a second alternative to geom_boxplot()
. A violin plot uses densities to draw a smoothed version of the centered dotplot you just made.
You can think of a violin plot as an outline drawn around the edges of a centered dotplot. Each “violin” spans the range of the data. The violin is thick where there are many values, and thin where there are few.
Convert the plot below from a boxplot to a violin plot. Note that violin plots do not use the parameters you saw for dotplots.
ggplot(data = mpg) +
geom_boxplot(mapping = aes(x = class, y = hwy))
ggplot(data = mpg) +
geom_violin(mapping = aes(x = class, y = hwy))
Exercise 7 - Violin plots
You can further enhance violin plots by adding the parameter draw_quantiles = c(0.25, 0.5, 0.75)
. This will cause ggplot2 to draw horizontal lines across the violins at the 25th, 50th, and 75th percentiles. These are the same three horizontal lines that are displayed in a boxplot (the 25th and 75th percentiles are the bounds of the box, the 50th percentile is the median).
Add these lines to the violin plot below.
ggplot(data = mpg) +
geom_violin(mapping = aes(x = class, y = hwy))
ggplot(data = mpg) +
geom_violin(mapping = aes(x = class, y = hwy), draw_quantiles = c(0.25, 0.5, 0.75))
Counts
geom_count()
Boxplots provide an efficient way to explore the interaction of a continuous variable and a categorical variable. But what if you have two categorical variables?
You can see how observations are distributed across two categorical variables with geom_count()
. geom_count()
draws a point at each combination of values from the two variables. The size of the point is mapped to the number of observations with this combination of values. Rare combinations will have small points, frequent combinations will have large points.
Exercise 8 - Count plots
Use geom_count()
to plot the interaction of the cut
and clarity
variables in the diamonds
data set.
ggplot(data = diamonds) +
geom_count(mapping = aes(x = cut, y = clarity))
count
You can use the count()
function in the dplyr package to compute the count values displayed by geom_count()
. To use count()
, pass it a data frame and then the names of zero or more variables in the data frame. count()
will return a new table that lists how many observations occur with each possible combination of the listed variables.
So for example, the code below returns the counts that you visualized in Exercise 8.
diamonds %>%
count(cut, clarity)
Heat maps
Heat maps provide a second way to visualize the relationship between two categorical variables. They work like count plots, but use a fill color instead of a point size, to display the number of observations in each combination.
How to make a heat map
ggplot2 does not provide a geom function for heat maps, but you can construct a heat map by plotting the results of count()
with geom_tile()
.
To do this, set the x and y aesthetics of geom_tile()
to the variables that you pass to count()
. Then map the fill aesthetic to the n
variable computed by count()
. The plot below displays the same counts as the plot in Exercise 8.
diamonds %>%
count(cut, clarity) %>%
ggplot() +
geom_tile(mapping = aes(x = cut, y = clarity, fill = n))
Exercise 9 - Make a heat map
Practice the method above by re-creating the heat map below.
diamonds %>%
count(color, cut) %>%
ggplot(mapping = aes(x = color, y = cut)) +
geom_tile(mapping = aes(fill = n))
Recap
Boxplots, dotplots and violin plots provide an easy way to look for relationships between a continuous variable and a categorical variable. Violin plots convey a lot of information quickly, but boxplots have a head start in popularity — they were easy to use when statisticians had to draw graphs by hand.
In any of these graphs, look for distributions, ranges, medians, skewness or anything else that catches your eye to change in an unusual way from distribution to distribution. Often, you can make patterns even more revealing with the fct_reorder()
function from the forcats package (we’ll wait to learn about forcats until after you study factors).
Count plots and heat maps help you see how observations are distributed across the interactions of two categorical variables.