Resources
Setup

Open your R project. Create a new script called day5.R.

R
gap <- read.csv("rawdata/gapminder.csv")
dim(gap)     # dimensions: rows × columns
nrow(gap)    # number of rows
Object Types

R stores data in different types. Look at the Environment panel to see what type each column is.

  • int — integer (whole number)
  • num — numeric (floating point / decimal)
  • chr — character (text)
  • logi — logical (TRUE / FALSE)
R
# Add a logical column
gap$big_countries <- gap$pop >= 100000000
Data Structure Types
  • Data frame — tabular data; columns must be the same length
  • Vector — one-dimensional, all elements the same type
  • List — like a data frame but elements can have different lengths and types
  • Factor — categorical data with defined levels

Vectorization Is Faster Than Loops

R
# Vectorized — fast
system.time(gap$pop - 1000)

# Loop — slow
system.time(
  for(i in 1:nrow(gap)) {
    print(gap[i,]$pop - 1000)
  }
)

Working with Vectors and Data Frames

R
# Create a data frame
cats <- data.frame(coat = c("calico", "black", "tabby"),
                   weight = c(2.1, 5.0, 3.2),
                   likes_catnip = c(1, 0, 1))

write.csv(x = cats, file = "rawdata/feline-data.csv", row.names = FALSE)

# Vectorization on character vectors
paste("My cat is", cats$coat)

Type Coercion — Watch Out

R will silently convert types when you mix them. The hierarchy: logical → integer → double → complex → character

R
coercion_vector <- c(0, TRUE)    # what do you predict?
coercion_vector

# Explicit type conversion
coercion_vector <- c('0', '2', '4')
str(coercion_vector)
coercion_vector <- as.numeric(coercion_vector)
str(coercion_vector)

Lists

R
list_example <- list(nums = c(1,2,3,4,5), chars = "a", logis = c(TRUE,TRUE,FALSE))
list_example[[1]]        # access by position
list_example$nums[1]    # access by name + index
Subsetting Data
R
# Index by position [row, column]
gap[1,1]
gap[1:5, 1:2]
gap[1:5, ]                         # all columns
gap[1:5, c("country", "continent")] # select by name

# Logical subsetting
gap[gap$year == 1957, ]
gap[gap$year %in% c(1957, 1958, 1959), ]
gap[gap$year == 1957, c("country", "continent", "pop")]
Practice problem

Make a new data frame containing life expectancies for all countries, but only for "big" countries between 1970 and 1990. Hint: use & to combine conditions.

Answer: LifeExpBigs <- gap[gap$year >= 1970 & gap$year <= 1990 & gap$big_countries == TRUE, c("country", "lifeExp")]

dplyr — the Tidyverse Way
R
install.packages("tidyverse")  # run once
library(tidyverse)              # run each session (put at top of script)

The key dplyr verbs:

  • select() — choose columns
  • filter() — choose rows
  • mutate() — add or edit columns
  • group_by() — group data
  • summarize() — compute summaries

Pipelines with %>%

R
# Select columns
gap_smaller <- gap %>%
  select(country, continent, pop)

# Filter rows
tidyGap <- gap %>%
  select(year, country, pop, gdpPercap) %>%
  filter(between(year, 1970, 1990)) %>%
  rename(population = pop)

# Summarize by group
gdp_bycontinents <- gap %>%
  group_by(continent) %>%
  summarize(mean_gdpPercap = mean(gdpPercap))

# Multi-variable summary
gdp_pop_bycontinents_byyear <- gap %>%
  group_by(continent, year) %>%
  summarize(mean_gdpPercap = mean(gdpPercap),
            sd_gdpPercap = sd(gdpPercap),
            mean_pop = mean(pop),
            sd_pop = sd(pop),
            countriesInContinent = n())

# Mutate — add a new column
gap %>%
  mutate(gdp_billion = pop * gdpPercap / 10^9)
Practice problem

Calculate the mean life expectancy per country. Which country has the longest average life expectancy? The shortest?

Ask AI to Write a dplyr Pipeline AI

dplyr is where AI really shines — describe what you want in plain English and let AI write the pipeline. Then run it and make sure the output makes sense.

Try this prompt in Claude or ChatGPT
I'm working with the gapminder dataset in R. It has columns: country, continent, year, lifeExp, pop, gdpPercap. I have it loaded as a data frame called "gap". Please write a dplyr pipeline that: 1. Filters to only include data from 1990 onwards 2. Groups by continent and year 3. Calculates the mean life expectancy and total population for each group 4. Arranges the results by continent and year Please use the tidyverse %>% pipe and explain what each step does.

After running it, follow up: "Can you modify this to also calculate the standard deviation of life expectancy for each group?"