Agenda

Packages

## ── Attaching packages ──────────────────────────────────────────────────────────── tidyverse 1.2.1 ──
## ✔ ggplot2 3.2.1     ✔ purrr   0.3.3
## ✔ tibble  2.1.3     ✔ dplyr   0.8.3
## ✔ tidyr   1.0.0     ✔ stringr 1.4.0
## ✔ readr   1.3.1     ✔ forcats 0.4.0
## ── Conflicts ─────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()

Getting started: birthwt dataset

tibbles

## # A tibble: 189 x 10
##      low   age   lwt  race smoke   ptl    ht    ui   ftv   bwt
##    <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
##  1     0    19   182     2     0     0     0     1     0  2523
##  2     0    33   155     3     0     0     0     0     3  2551
##  3     0    20   105     1     1     0     0     0     1  2557
##  4     0    21   108     1     1     0     0     1     2  2594
##  5     0    18   107     1     1     0     0     1     0  2600
##  6     0    21   124     3     0     0     0     0     0  2622
##  7     0    22   118     1     0     0     0     0     1  2637
##  8     0    17   103     3     0     0     0     0     1  2637
##  9     0    29   123     1     1     0     0     0     1  2663
## 10     0    26   113     1     1     0     0     0     0  2665
## # … with 179 more rows
##   [1] 19 33 20 21 18 21 22 17 29 26 19 19 22 30 18 18 15 25 20 28 32 31 36
##  [24] 28 25 28 17 29 26 17 17 24 35 25 25 29 19 27 31 33 21 19 23 21 18 18
##  [47] 32 19 24 22 22 23 22 30 19 16 21 30 20 17 17 23 24 28 26 20 24 28 20
##  [70] 22 22 31 23 16 16 18 25 32 20 23 22 32 30 20 23 17 19 23 36 22 24 21
##  [93] 19 25 16 29 29 19 19 30 24 19 24 23 20 25 30 22 18 16 32 18 29 33 20
## [116] 28 14 28 25 16 20 26 21 22 25 31 35 19 24 45 28 29 34 25 25 27 23 24
## [139] 24 21 32 19 25 16 25 20 21 24 21 20 25 19 19 26 24 17 20 22 27 20 17
## [162] 25 20 18 18 20 21 26 31 15 23 20 24 15 23 30 22 17 23 17 26 20 26 14
## [185] 28 14 23 17 21
##   [1] 19 33 20 21 18 21 22 17 29 26 19 19 22 30 18 18 15 25 20 28 32 31 36
##  [24] 28 25 28 17 29 26 17 17 24 35 25 25 29 19 27 31 33 21 19 23 21 18 18
##  [47] 32 19 24 22 22 23 22 30 19 16 21 30 20 17 17 23 24 28 26 20 24 28 20
##  [70] 22 22 31 23 16 16 18 25 32 20 23 22 32 30 20 23 17 19 23 36 22 24 21
##  [93] 19 25 16 29 29 19 19 30 24 19 24 23 20 25 30 22 18 16 32 18 29 33 20
## [116] 28 14 28 25 16 20 26 21 22 25 31 35 19 24 45 28 29 34 25 25 27 23 24
## [139] 24 21 32 19 25 16 25 20 21 24 21 20 25 19 19 26 24 17 20 22 27 20 17
## [162] 25 20 18 18 20 21 26 31 15 23 20 24 15 23 30 22 17 23 17 26 20 26 14
## [185] 28 14 23 17 21
## [1] 19
## # A tibble: 1 x 1
##     age
##   <int>
## 1    19
## [1] 19

Note: If you want to import data directly into tibble format, you may use read_delim() and read_csv() instead of their base-R alternatives. Even though we started with the base alternatives, I recommend using these improved import commands going forward.

Renaming the variables

##  [1] "low"   "age"   "lwt"   "race"  "smoke" "ptl"   "ht"    "ui"   
##  [9] "ftv"   "bwt"
## # A tibble: 189 x 10
##    birthwt.below.2… mother.age mother.weight  race mother.smokes
##               <int>      <int>         <int> <int>         <int>
##  1                0         19           182     2             0
##  2                0         33           155     3             0
##  3                0         20           105     1             1
##  4                0         21           108     1             1
##  5                0         18           107     1             1
##  6                0         21           124     3             0
##  7                0         22           118     1             0
##  8                0         17           103     3             0
##  9                0         29           123     1             1
## 10                0         26           113     1             1
## # … with 179 more rows, and 5 more variables: previous.prem.labor <int>,
## #   hypertension <int>, uterine.irr <int>, physician.visits <int>,
## #   birthwt.grams <int>

An alternative renaming approach: the rename() command

rename operates by allowing you to specify a new variable name for whichever old variable name you want to change.

##  [1] "birthwt.below.2500"  "mother.age"          "mother.weight"      
##  [4] "race"                "mother.smokes"       "previous.prem.labor"
##  [7] "hypertension"        "uterine.irr"         "physician.visits"   
## [10] "birthwt.grams"
## # A tibble: 189 x 10
##    birthwt.below.2… mother.age mother.weight  race mother.smokes
##               <int>      <int>         <int> <int>         <int>
##  1                0         19           182     2             0
##  2                0         33           155     3             0
##  3                0         20           105     1             1
##  4                0         21           108     1             1
##  5                0         18           107     1             1
##  6                0         21           124     3             0
##  7                0         22           118     1             0
##  8                0         17           103     3             0
##  9                0         29           123     1             1
## 10                0         26           113     1             1
## # … with 179 more rows, and 5 more variables: previous.prem.labor <int>,
## #   hypertension <int>, uterine.irr <int>, physician.visits <int>,
## #   birthwt.grams <int>

Note that in this command we didn’t rename the race variable because it already had a good name.

Renaming the factors

## # A tibble: 189 x 10
##    birthwt.below.2… mother.age mother.weight  race mother.smokes
##               <int>      <int>         <int> <int>         <int>
##  1                0         19           182     2             0
##  2                0         33           155     3             0
##  3                0         20           105     1             1
##  4                0         21           108     1             1
##  5                0         18           107     1             1
##  6                0         21           124     3             0
##  7                0         22           118     1             0
##  8                0         17           103     3             0
##  9                0         29           123     1             1
## 10                0         26           113     1             1
## # … with 179 more rows, and 5 more variables: previous.prem.labor <int>,
## #   hypertension <int>, uterine.irr <int>, physician.visits <int>,
## #   birthwt.grams <int>
## # A tibble: 189 x 10
##    birthwt.below.2… mother.age mother.weight race  mother.smokes
##    <fct>                 <int>         <int> <fct> <fct>        
##  1 no                       19           182 black no           
##  2 no                       33           155 other no           
##  3 no                       20           105 white yes          
##  4 no                       21           108 white yes          
##  5 no                       18           107 white yes          
##  6 no                       21           124 other no           
##  7 no                       22           118 white no           
##  8 no                       17           103 other no           
##  9 no                       29           123 white yes          
## 10 no                       26           113 white yes          
## # … with 179 more rows, and 5 more variables: previous.prem.labor <int>,
## #   hypertension <fct>, uterine.irr <fct>, physician.visits <int>,
## #   birthwt.grams <int>

Recall that the syntax ~ recode_factor(.x, ...) defines an anonymous function that will be applied to every column specfied in the first part of the mutate_at() call. In this case, all of the specified variables are binary 0/1 coded, and are being recoded to no/yes.

Summary of the data

##  birthwt.below.2500   mother.age    mother.weight      race   
##  no :130            Min.   :14.00   Min.   : 80.0   white:96  
##  yes: 59            1st Qu.:19.00   1st Qu.:110.0   black:26  
##                     Median :23.00   Median :121.0   other:67  
##                     Mean   :23.24   Mean   :129.8             
##                     3rd Qu.:26.00   3rd Qu.:140.0             
##                     Max.   :45.00   Max.   :250.0             
##  mother.smokes previous.prem.labor hypertension uterine.irr
##  no :115       Min.   :0.0000      no :177      no :161    
##  yes: 74       1st Qu.:0.0000      yes: 12      yes: 28    
##                Median :0.0000                              
##                Mean   :0.1958                              
##                3rd Qu.:0.0000                              
##                Max.   :3.0000                              
##  physician.visits birthwt.grams 
##  Min.   :0.0000   Min.   : 709  
##  1st Qu.:0.0000   1st Qu.:2414  
##  Median :0.0000   Median :2977  
##  Mean   :0.7937   Mean   :2945  
##  3rd Qu.:1.0000   3rd Qu.:3487  
##  Max.   :6.0000   Max.   :4990

A simple table

## # A tibble: 6 x 3
## # Groups:   race [3]
##   race  mother.smokes mean.birthwt
##   <fct> <fct>                <dbl>
## 1 white no                    3429
## 2 white yes                   2827
## 3 black no                    2854
## 4 black yes                   2504
## 5 other no                    2816
## 6 other yes                   2757

A simple reshape

## # A tibble: 3 x 3
## # Groups:   race [3]
##   race     no   yes
##   <fct> <dbl> <dbl>
## 1 white  3429  2827
## 2 black  2854  2504
## 3 other  2816  2757

What if we wanted nicer looking output?

race no yes
white 3429 2827
black 2854 2504
other 2816 2757

Example: Association between mother’s age and birth weight?

## [1] 0.09031781
## # A tibble: 2 x 2
##   mother.smokes cor_bwt_age
##   <fct>               <dbl>
## 1 no                  0.201
## 2 yes                -0.144

Does the association between birthweight and mother’s age vary by race?

## # A tibble: 3 x 2
##   race  cor_bwt_age
##   <fct>       <dbl>
## 1 white      0.166 
## 2 black     -0.329 
## 3 other     -0.0293

There does look to be variation, but we don’t know if it’s statistically significant without further investigation.

Graphics in R

Standard graphics in R

Single-variable plots

Let’s continue with the birthwt data from the MASS library.

Here are some basic single-variable plots.

Note that the result of calling plot(x, ...) varies depending on what x is.
- When x is numeric, you get a plot showing the value of x at every index.
- When x is a factor, you get a bar plot of counts for every level

Let’s add more information to the smoking bar plot, and also change the color by setting the col option.

(much) better graphics with ggplot2

Introduction to ggplot2

ggplot2 has a slightly steeper learning curve than the base graphics functions, but it also generally produces far better and more easily customizable graphics.

There are two basic calls in ggplot:

  • qplot(x, y, ..., data): a “quick-plot” routine, which essentially replaces the base plot()
  • ggplot(data, aes(x, y, ...), ...): defines a graphics object from which plots can be generated, along with aesthetic mappings that specify how variables are mapped to visual properties.

plot vs qplot

Here’s how the default scatterplots look in ggplot compared to the base graphics. We’ll illustrate things by continuing to use the birthwt data from the MASS library.

I’ve snuck the with() command into this example. with() allows you to use the variables in a data frame directly in evaluating the expression in the second argument.

Remember how it took us some effort last time to add color coding, use different plotting characters, and add a legend? Here’s the qplot call that does it all in one simple line.

This way you won’t run into problems of accidentally producing the wrong legend. The legend is produced based on the colour and shape argument that you pass in. (Note: color and colour have the same effect. )

ggplot function

The ggplot2 library comes with a dataset called diamonds. Let’s look at it

## [1] 53940    10
## # A tibble: 6 x 10
##   carat cut       color clarity depth table price     x     y     z
##   <dbl> <ord>     <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl>
## 1 0.23  Ideal     E     SI2      61.5    55   326  3.95  3.98  2.43
## 2 0.21  Premium   E     SI1      59.8    61   326  3.89  3.84  2.31
## 3 0.23  Good      E     VS1      56.9    65   327  4.05  4.07  2.31
## 4 0.290 Premium   I     VS2      62.4    58   334  4.2   4.23  2.63
## 5 0.31  Good      J     SI2      63.3    58   335  4.34  4.35  2.75
## 6 0.24  Very Good J     VVS2     62.8    57   336  3.94  3.96  2.48

It is a data frame of 53,940 diamonds, recording their attributes such as carat, cut, color, clarity, and price.

We will make a scatterplot showing the price as a function of the carat (size). (The data set is large so the plot may take a few moments to generate.)

The data set looks a little weird because a lot of diamonds are concentrated on the 1, 1.5 and 2 carat mark.

Let’s take a step back and try to understand the ggplot syntax.

  1. The first thing we did was to define a graphics object, diamond.plot. This definition told R that we’re using the diamonds data, and that we want to display carat on the x-axis, and price on the y-axis.

  2. We then called diamond.plot + geom_point() to get a scatterplot.

The arguments passed to aes() are called mappings. Mappings specify what variables are used for what purpose. When you use geom_point() in the second line, it pulls x, y, colour, size, etc., from the mappings specified in the ggplot() command.

You can also specify some arguments to geom_point directly if you want to specify them for each plot separately instead of pre-specifying a default.

Here we shrink the points to a smaller size, and use the alpha argument to make the points transparent.

If we wanted to let point color depend on the color indicator of the diamond, we could do so in the following way.

If we didn’t know anything about diamonds going in, this plot would indicate to us that D is likely the highest diamond grade, while J is the lowest grade.

We can change colors by specifying a different color palette. Here’s how we can switch to the cbPalette we saw last class.

To make the scatterplot look more typical, we can switch to logarithmic coordinate axis spacing.

Conditional plots

We can create plots showing the relationship between variables across different values of a factor. For instance, here’s a scatterplot showing how diamond price varies with carat size, conditioned on color. It’s created using the facet_wrap(~ factor1 + factor2 + ... + factorn) command.

You can also use facet_grid() to produce this type of output.

ggplot can create a lot of different kinds of plots, just like lattice. Here are some examples.

Function Description
geom_point(...) Points, i.e., scatterplot
geom_bar(...) Bar chart
geom_line(...) Line chart
geom_boxplot(...) Boxplot
geom_violin(...) Violin plot
geom_density(...) Density plot with one variable
geom_density2d(...) Density plot with two variables
geom_histogram(...) Histogram

Histograms and density plots

## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Does the association between birthweight and mother’s age depend on smoking status?

We previously ran the following command to calculate the correlation between mother’s ages and baby birthweights broken down by the mother’s smoking status.

## # A tibble: 2 x 2
##   mother.smokes cor_bwt_age
##   <fct>               <dbl>
## 1 no                  0.201
## 2 yes                -0.144

Here’s a visualization of our data that allows us to see what’s going on.