Lecture 2: Positron, Data Science Workflow and ggplot2

Chapters 2.1 - 2.2

Published

September 2, 2026

Data Science Workflow

What are the main tools of data science? One answer to this question is the following diagram.

Figure: The data science flow

Positron

Cheatsheet

Make a script (or Quarto Document) for each class

New > New File > R File or Quarto Document

  • Use comments to organize your work!
  • Insert R-chunk with: ctrl + shift + i or cmd + shift + i (Mac)
  • Use ctrl + enter or cmd + enter to run the code in the current chunk.
  • Use ctrl + shift + enter or cmd + shift + enter to run all code in the current document.

Useful tips

The dollar sign notation

The dollar sign ($) is used to access variables within a data frame in R.

# Access variables directly 
us_rent_income$NAME # the variable NAME in the dataset us_rent_income
  [1] "Alabama"              "Alabama"              "Alaska"              
  [4] "Alaska"               "Arizona"              "Arizona"             
  [7] "Arkansas"             "Arkansas"             "California"          
 [10] "California"           "Colorado"             "Colorado"            
 [13] "Connecticut"          "Connecticut"          "Delaware"            
 [16] "Delaware"             "District of Columbia" "District of Columbia"
 [19] "Florida"              "Florida"              "Georgia"             
 [22] "Georgia"              "Hawaii"               "Hawaii"              
 [25] "Idaho"                "Idaho"                "Illinois"            
 [28] "Illinois"             "Indiana"              "Indiana"             
 [31] "Iowa"                 "Iowa"                 "Kansas"              
 [34] "Kansas"               "Kentucky"             "Kentucky"            
 [37] "Louisiana"            "Louisiana"            "Maine"               
 [40] "Maine"                "Maryland"             "Maryland"            
 [43] "Massachusetts"        "Massachusetts"        "Michigan"            
 [46] "Michigan"             "Minnesota"            "Minnesota"           
 [49] "Mississippi"          "Mississippi"          "Missouri"            
 [52] "Missouri"             "Montana"              "Montana"             
 [55] "Nebraska"             "Nebraska"             "Nevada"              
 [58] "Nevada"               "New Hampshire"        "New Hampshire"       
 [61] "New Jersey"           "New Jersey"           "New Mexico"          
 [64] "New Mexico"           "New York"             "New York"            
 [67] "North Carolina"       "North Carolina"       "North Dakota"        
 [70] "North Dakota"         "Ohio"                 "Ohio"                
 [73] "Oklahoma"             "Oklahoma"             "Oregon"              
 [76] "Oregon"               "Pennsylvania"         "Pennsylvania"        
 [79] "Rhode Island"         "Rhode Island"         "South Carolina"      
 [82] "South Carolina"       "South Dakota"         "South Dakota"        
 [85] "Tennessee"            "Tennessee"            "Texas"               
 [88] "Texas"                "Utah"                 "Utah"                
 [91] "Vermont"              "Vermont"              "Virginia"            
 [94] "Virginia"             "Washington"           "Washington"          
 [97] "West Virginia"        "West Virginia"        "Wisconsin"           
[100] "Wisconsin"            "Wyoming"              "Wyoming"             
[103] "Puerto Rico"          "Puerto Rico"         
us_rent_income$estimate # the variable estimate in the dataset us_rent_income
  [1] 24476   747 32940  1200 27517   972 23789   709 29454  1358 32401  1125
 [13] 35326  1123 31560  1076 43198  1424 25952  1077 27024   927 32453  1507
 [25] 25298   792 30684   952 27247   782 30002   740 29126   801 24702   713
 [37] 25086   825 26841   808 37147  1311 34498  1173 26987   824 32734   906
 [49] 22766   740 26999   784 26249   751 30020   773 29019  1017 33172  1052
 [61] 35075  1249 24457   809 31057  1194 26482   844 32336   775 27435   764
 [73] 26207   766 27389   988 28923   885 30210   957 25454   836 28821   696
 [85] 25453   808 28063   952 27928   948 29351   945 32545  1166 32318  1120
 [97] 23707   681 29868   813 30854   828    NA   464

We note the NAME variable is a character vector, while the estimate variable is a numeric vector. We can use the class() function to check this. It is contains redundancies. To see only the unique values of a variable, we can use the unique() function.

class(us_rent_income$NAME) # check the class of the variable NAME
[1] "character"
class(us_rent_income$estimate) # check the class of the variable estimate
[1] "numeric"
unique(us_rent_income$NAME) # see the unique values of the variable NAME
 [1] "Alabama"              "Alaska"               "Arizona"             
 [4] "Arkansas"             "California"           "Colorado"            
 [7] "Connecticut"          "Delaware"             "District of Columbia"
[10] "Florida"              "Georgia"              "Hawaii"              
[13] "Idaho"                "Illinois"             "Indiana"             
[16] "Iowa"                 "Kansas"               "Kentucky"            
[19] "Louisiana"            "Maine"                "Maryland"            
[22] "Massachusetts"        "Michigan"             "Minnesota"           
[25] "Mississippi"          "Missouri"             "Montana"             
[28] "Nebraska"             "Nevada"               "New Hampshire"       
[31] "New Jersey"           "New Mexico"           "New York"            
[34] "North Carolina"       "North Dakota"         "Ohio"                
[37] "Oklahoma"             "Oregon"               "Pennsylvania"        
[40] "Rhode Island"         "South Carolina"       "South Dakota"        
[43] "Tennessee"            "Texas"                "Utah"                
[46] "Vermont"              "Virginia"             "Washington"          
[49] "West Virginia"        "Wisconsin"            "Wyoming"             
[52] "Puerto Rico"         

Dataset: Gapminder

The gapminder dataset is a collection of data about countries around the world, including information about life expectancy, GDP per capita, and population. Learn more about the dataset: (https://www.gapminder.org/)

Gapminder: Fight devastating ignorance with a fact-based worldview everyone can understand.

Install the dataset. This step is like downloading a file to your computer. You only need to do this once.

pak::pkg_install("gapminder") 
# note the code below also works and is commonly found on the web
# install.packages("gapminder")

To get files from your computer into R, we load the libraries as below. This step is like opening a file on your computer. You need to do this every time you start a new R session.

library(gapminder)

Below we look at a transposed version of the data with glimpse, which lives in the dplyr package, included in the tidyverse. Or View(), or or just type gapminder.

glimpse(gapminder)
Rows: 1,704
Columns: 6
$ country   <fct> "Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan", …
$ continent <fct> Asia, Asia, Asia, Asia, Asia, Asia, Asia, Asia, Asia, Asia, …
$ year      <int> 1952, 1957, 1962, 1967, 1972, 1977, 1982, 1987, 1992, 1997, …
$ lifeExp   <dbl> 28.801, 30.332, 31.997, 34.020, 36.088, 38.438, 39.854, 40.8…
$ pop       <int> 8425333, 9240934, 10267083, 11537966, 13079460, 14880372, 12…
$ gdpPercap <dbl> 779.4453, 820.8530, 853.1007, 836.1971, 739.9811, 786.1134, …

We see that this dataset has variables: countries, continents, year, life expectancy, population and GDP per capita.

Find out more about a variable, dataset or function

?gapminder # you should see a description of the dataset and its variables on the right of Positron

List all the variable names of a dataset

names(gapminder)
[1] "country"   "continent" "year"      "lifeExp"   "pop"       "gdpPercap"

Grammar of Graphics / ggplot syntax

One of the main ways to visualize data in R is ggplot2, which utilizes the conceptual framework of the grammar of graphics. In English, grammar dictates that each sentence must have a subject and verb. In the grammar of graphics, each plotting element must have data, aesthetics and a geometry. Good sentences often have prepositions, adverbs, etc., and good graphics have more layers as well.

Figure: ggplot2 layers

This example shows some layers of a ggplot2 graphic. We include the line numbers in the code so you can see which lines of code corresponds to which layer in the graphic.

  • Line 1 creates a plot
  • Line 2 adds the data layer
  • Line 3 adds the aesthetics layer
  • Line 4 adds the geometry layer
  • Line 5 adds a layer modifying the theme
ggplot(
  data = gapminder, # data
  aes(x = gdpPercap, y = lifeExp)) + 
  geom_point(aes(color = year)) + 
  labs(title = "GDP vs. Life Expectancy", 
       y = "GDP per capita", 
       subtitle = "From 1960 to 2000")

The first input to ggplot is always a data table. Notice below, there is nothing to see, but also no error. It’s just a blank plot.

ggplot(data = gapminder)

The second input is a mapping argument called aes() or aesthetic. (Another blank plot.)

ggplot(
  data = gapminder,
  aes(x = year)
)

Only with the third layer do we get something interesting.

ggplot(
  data = gapminder,
  aes(x = year, y = lifeExp)) + 
  geom_point() 

This is a pretty bad plot. We learn something, but we could learn the same with less. Scatterplots are best used to compare numerical data, not categorical. The variable GDP (gross domestic product) is numerical, so let’s see if life expectancy is possibly related to GDP per capita.

ggplot(
  data = gapminder,
  aes(x = gdpPercap, y = lifeExp)) + 
  geom_point() 

In the above plot, can you determine a relationship between GDP and Life Expectancy? Let’s see if time plays a role.

ggplot(
  data = gapminder,
  aes(x = gdpPercap, y = lifeExp, color = year)) + 
  geom_point() 

In the above, we included a 3rd variable as color. Now apply a fourth layer, a statistic. In this case a curve of best fit.

ggplot(
  data = gapminder,
  aes(x = gdpPercap, y = lifeExp)) + 
  geom_point(aes(color = year)) +
  geom_smooth()
`geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

We improve the graphic by adding labels such as a title, subtitle and more with labs(). Do ?labs() to explore possibilities. How could the plot below be improved even further?

ggplot(
  data = gapminder,
  aes(x = gdpPercap, y = lifeExp)) + 
  geom_point(aes(color = year)) +
  labs(title = "GDP vs. Life Expectancy", 
       y = "GDP per capita", 
       subtitle = "From 1960 to 2000")

Assignment 2

Due: Midnight, Friday, 9/4/2026

  1. Create a .qmd file to contain responses to the following: (note you need to “render” the .qmd file into an .html file)

  2. Recreate the final plot above but with a different mapping, such as GDP as a function of year and color by continent.

  3. What happens when you try to color by country?

  4. What makes some mappings more useful than others?