Data Science with R - Comprehensive Guide
Welcome to R Data Science! This comprehensive 12-week course will take you from complete beginner to proficient data scientist using R. Unlike Python, R was specifically designed for statistical computing and data analysis, making it incredibly powerful for data science work. KEY DIFFERENCES FROM PYTHON:
COURSE STRUCTURE: This course spans 12 weeks with Tuesday/Thursday/Saturday sessions, each lasting 2 hours:
WHAT YOU'LL LEARN THIS WEEK:
BY END OF WEEK 1: ✓ R and RStudio installed and configured ✓ Understand R data types and structures ✓ Write basic R scripts ✓ Comfortable with variables and vectors ✓ Know how to use help() system ✓ Understand vectorization ✓ Write your first functions ✓ Install and load packages This week is CRITICAL - establish good habits from the start!
WHAT IS R? R is a free, open-source programming language specifically designed for:
WHAT IS RSTUDIO? RStudio is an Integrated Development Environment (IDE) for R. It makes R much more user-friendly. Think of it as: R = engine, RStudio = car dashboard
WHY RStudio?
INSTALLATION STEPS:
Step 1: Install R
Step 2: Install RStudio Desktop (Free Version)
Step 3: Verify Installation
RSTUDIO INTERFACE TOUR:
When you open RStudio, you'll see 4 panes:
LEFT PANE - CONSOLE:
TOP LEFT - SCRIPT EDITOR:
RIGHT TOP - ENVIRONMENT/HISTORY:
RIGHT BOTTOM - FILES/PLOTS/PACKAGES/HELP:
CUSTOMIZING RSTUDIO: Tools → Global Options → Appearance
PRO TIP: Set to save and restore workspace = OFF Tools → Global Options → General This prevents loading old objects, keeps workspace clean
FIRST R COMMAND:
Open Console and type:
print("Hello R World!")Press Enter. You should see: [1] "Hello R World!"
Congratulations! You just ran R code!
KEYBOARD SHORTCUTS (Make life easier):
Windows/Linux:
Mac:
SET UP YOUR FIRST PROJECT:
File → New Project → New Directory → New Project
WHY PROJECTS?
# CREATING VARIABLES (ASSIGNMENT)
In R, we assign values using <- (not =, though = works)
Syntax: variable_name <- value
Examples:
# Numeric values age <- 25 height <- 5.9 income <- 50000 # Character (text) values name <- "Alice" city <- "New York" # Logical (TRUE/FALSE) values is_student <- TRUE has_car <- FALSE # Check what's in a variable age # Type in console, R prints it print(age) # Explicit printing
OUTPUT: [1] 25
NAMING CONVENTIONS:
✗ Don't start with number: 1variable ✗ Don't use spaces: my variable ✗ Avoid special characters: my-variable
UNDERSTANDING VECTORIZATION:
This is THE MOST IMPORTANT R concept!
In R, everything is a VECTOR (a sequence of values)
# Single value is actually a vector of length 1 x <- 5 length(x) # [1] 1 # Create vectors with c() (combine) numbers <- c(1, 2, 3, 4, 5) numbers # [1] 1 2 3 4 5 names <- c("Alice", "Bob", "Charlie") names # [1] "Alice" "Bob" "Charlie" logical_values <- c(TRUE, FALSE, TRUE) logical_values # [1] TRUE FALSE TRUE # Sequence creation 1:10 # [1] 1 2 3 4 5 6 7 8 9 10 seq(1, 10, by=2) # [1] 1 3 5 7 9 rep(5, times=3) # [1] 5 5 5
DATA TYPES - THE FUNDAMENTALS:
price <- 19.99
weight <- 72.5
class(price) # [1] "numeric"count <- 42L # L makes it integer age <- as.integer(25) class(count) # [1] "integer"
city <- "Paris" sentence <- "R is amazing!" class(city) # [1] "character"
is_adult <- TRUE is_valid <- FALSE class(is_adult) # [1] "logical"
z <- 3 + 4i
class(z) # [1] "complex"DATA STRUCTURES - Containers for data:
# All elements must be SAME type numbers <- c(1, 2, 3, 4, 5) words <- c("apple", "banana", "cherry") flags <- c(TRUE, TRUE, FALSE) # If mix types, R coerces to most general mixed <- c(1, "two", 3) # All become character! mixed # [1] "1" "two" "3"
# Create matrix my_matrix <- matrix(1:12, nrow=3, ncol=4) my_matrix # [,1] [,2] [,3] [,4] # [1,] 1 4 7 10 # [2,] 2 5 8 11 # [3,] 3 6 9 12 # Dimensions nrow(my_matrix) # [1] 3 ncol(my_matrix) # [1] 4 dim(my_matrix) # [1] 3 4
# Create data frame (like Excel spreadsheet) students <- data.frame( name = c("Alice", "Bob", "Charlie"), age = c(20, 21, 19), grade = c("A", "B", "A") ) students # name age grade # 1 Alice 20 A # 2 Bob 21 B # 3 Charlie 19 A # Access columns students$name # [1] "Alice" "Bob" "Charlie" students$age # [1] 20 21 19 # Number of rows and columns nrow(students) # [1] 3 ncol(students) # [1] 3 dim(students) # [1] 3 3
# List can contain anything my_list <- list( name = "Alice", age = 25, scores = c(85, 90, 88), is_student = TRUE ) my_list # $name # [1] "Alice" # $age # [1] 25 # $scores # [1] 85 90 88 # $is_student # [1] TRUE # Access elements my_list$name # [1] "Alice" my_list[[1]] # [1] "Alice" my_list[["age"]] # [1] 25
INDEXING AND SUBSETTING:
Accessing elements (CRITICAL SKILL!)
# Vector indexing (starts at 1, NOT 0!) v <- c(10, 20, 30, 40, 50) v[1] # [1] 10 (first element) v[3] # [1] 30 (third element) v[1:3] # [1] 10 20 30 (first three) v[-1] # [1] 20 30 40 50 (all except first) v[v > 25] # [1] 30 40 50 (conditional) # Matrix indexing [row, column] m <- matrix(1:12, nrow=3) m[1, ] # First row m[, 2] # Second column m[2, 3] # Element at row 2, column 3 = 8 # Data frame indexing df <- data.frame(name=c("A", "B", "C"), age=c(20, 21, 22)) df[1, ] # First row df[, "age"] # Age column df$name # Name column (most common) df[df$age > 20, ] # Rows where age > 20 # List indexing my_list <- list(a=1, b=2, c=3) my_list$a # [1] 1 my_list[["a"]] # [1] 1 my_list[1] # $a [1] 1 (returns list)
CHECKING DATA TYPES:
# typeof() - low level type typeof(5) # [1] "double" typeof("text") # [1] "character" # class() - practical class class(5) # [1] "numeric" class(data.frame()) # [1] "data.frame" # str() - structure of object (VERY USEFUL!) str(my_data_frame) # Shows columns, types, first few values # BEST WAY to understand data quickly # is.* functions - test type is.numeric(5) # [1] TRUE is.character("x") # [1] TRUE is.data.frame(df) # [1] TRUE # as.* functions - convert types as.numeric("5") # [1] 5 as.character(5) # [1] "5" as.integer(5.9) # [1] 5 (truncates)
KEY DIFFERENCES FROM PYTHON:
Python vs R:
Python:
R:
ARITHMETIC OPERATIONS:
Basic operations work on vectors (vectorized!)
# Single values 5 + 3 # [1] 8 10 - 4 # [1] 6 3 * 7 # [1] 21 20 / 4 # [1] 5 7 %% 3 # [1] 1 (modulo - remainder) 2 ** 3 # [1] 8 (exponentiation) 2 ^ 3 # [1] 8 (alternative exponentiation) # With variables x <- 10 y <- 3 x + y # [1] 13 x / y # [1] 3.333333 # VECTORIZATION - THE POWER OF R v1 <- c(1, 2, 3) v2 <- c(10, 20, 30) v1 + v2 # [1] 11 22 33 (element-wise!) v1 * 2 # [1] 2 4 6 (broadcast!) # More complex operations c(1, 2, 3) ^ 2 # [1] 1 4 9 sqrt(c(1, 4, 9, 16)) # [1] 1 2 3 4 abs(c(-5, 3, -1)) # [1] 5 3 1 log(c(1, 2.718, 10)) # [1] 0.0000000 1.0000000 2.3025851 exp(c(0, 1, 2)) # [1] 1.000000 2.718282 7.389056
LOGICAL OPERATIONS:
Testing and combining conditions
# Comparison operators (return TRUE/FALSE) 5 > 3 # [1] TRUE 5 < 3 # [1] FALSE 5 == 5 # [1] TRUE (equality, note: ==) 5 != 3 # [1] TRUE (not equal) 5 >= 5 # [1] TRUE (greater or equal) 5 <= 3 # [1] FALSE (less or equal) # With vectors (vectorized!) v <- c(1, 2, 3, 4, 5) v > 3 # [1] FALSE FALSE FALSE TRUE TRUE v == 3 # [1] FALSE FALSE TRUE FALSE FALSE v != 3 # [1] TRUE TRUE FALSE TRUE TRUE # Logical operators (combine conditions) TRUE & FALSE # [1] FALSE (AND - both must be true) TRUE | FALSE # [1] TRUE (OR - at least one true) !TRUE # [1] FALSE (NOT - negation) # With conditions (5 > 3) & (2 < 4) # [1] TRUE (both true) (5 > 10) | (2 < 4) # [1] TRUE (one true) !(5 > 3) # [1] FALSE # Useful functions all(c(TRUE, TRUE, TRUE)) # [1] TRUE (all elements true?) any(c(TRUE, FALSE, FALSE)) # [1] TRUE (any element true?) which(v > 3) # [1] 4 5 (indices where TRUE) # PRACTICAL EXAMPLE: Filtering data ages <- c(20, 21, 19, 22, 18) adults <- ages >= 18 adults # [1] TRUE TRUE TRUE TRUE TRUE ages[adults] # [1] 20 21 19 22 18 # Complex filtering ages[(ages >= 21) & (ages <= 25)] # [1] 21 22
OPERATOR PRECEDENCE (Order of operations):
# ^ (exponentiation) - highest # *, / # +, - # >, <, ==, != # & # | - lowest # Example 2 + 3 * 4 # [1] 14 (multiply first) (2 + 3) * 4 # [1] 20 (parentheses first) # With logical x <- 5 x > 3 & x < 10 # [1] TRUE (comparison before &)
SPECIAL VALUES:
# NULL - nothing/empty x <- NULL is.null(x) # [1] TRUE # NA - Missing value x <- NA is.na(x) # [1] TRUE # NaN - Not a Number x <- 0/0 is.nan(x) # [1] TRUE # Inf - Infinity x <- 1/0 is.infinite(x) # [1] TRUE # VERY IMPORTANT for data cleaning! v <- c(1, NA, 3, NaN, 5) is.na(v) # [1] FALSE TRUE FALSE TRUE FALSE sum(v) # [1] NA (NA propagates!) sum(v, na.rm=TRUE) # [1] 9 (ignore NAs)
WHAT ARE FUNCTIONS?
Functions are reusable blocks of code that perform specific tasks.
Syntax:
function_name <- function(argument1, argument2) { # Code to execute return(result) }
EXAMPLE: Simple function
# Define function greet <- function(name) { message <- paste("Hello,", name, "!") return(message) } # Use function greet("Alice") # [1] "Hello, Alice !" greet("Bob") # [1] "Hello, Bob !"
MORE DETAILED EXAMPLE:
# Function to calculate rectangle area calculate_area <- function(length, width) { area <- length * width return(area) } # Use it calculate_area(5, 3) # [1] 15 calculate_area(10, 4) # [1] 40 # Function with default arguments greet <- function(name = "Friend") { paste("Hello,", name) } greet() # [1] "Hello, Friend" greet("Alice") # [1] "Hello, Alice" # Function that returns multiple values stats <- function(v) { list( mean = mean(v), median = median(v), sd = sd(v) ) } result <- stats(c(1, 2, 3, 4, 5)) result # $mean # [1] 3 # $median # [1] 3 # $sd # [1] 1.581139
BUILT-IN FUNCTIONS (You don't need to write these):
# Math functions abs(-5) # [1] 5 (absolute value) sqrt(16) # [1] 4 (square root) round(3.7) # [1] 4 (round to nearest integer) ceiling(3.2) # [1] 4 (round up) floor(3.8) # [1] 3 (round down) log(10) # [1] 2.302585 (natural log) exp(1) # [1] 2.718282 (e^x) # Vector functions sum(c(1, 2, 3, 4, 5)) # [1] 15 prod(c(2, 3, 4)) # [1] 24 (product) mean(c(1, 2, 3, 4, 5)) # [1] 3 (average) median(c(1, 2, 3, 4, 5)) # [1] 3 (middle value) sd(c(1, 2, 3, 4, 5)) # Standard deviation var(c(1, 2, 3, 4, 5)) # Variance min(c(1, 2, 3, 4, 5)) # [1] 1 max(c(1, 2, 3, 4, 5)) # [1] 5 range(c(1, 2, 3, 4, 5)) # [1] 1 5 length(c(1, 2, 3, 4, 5)) # [1] 5 (count elements) unique(c(1, 1, 2, 2, 3)) # [1] 1 2 3 (remove duplicates) sort(c(3, 1, 4, 1, 5)) # [1] 1 1 3 4 5 (sort) rev(c(1, 2, 3, 4)) # [1] 4 3 2 1 (reverse) # String functions paste("Hello", "World") # Combine strings paste0("Hello", "World") # Without space nchar("Hello") # [1] 5 (length) substr("Hello", 1, 3) # [1] "Hel" (substring) toupper("hello") # [1] "HELLO" tolower("HELLO") # [1] "hello" grep("a", c("apple", "banana", "cherry")) # [1] 1 2 (find matches) gsub("a", "o", "banana") # Replace: "bonono" strsplit("apple,banana", ",") # Split string # Sequence functions (VERY USEFUL!) seq(1, 10) # [1] 1 2 3 4 5 6 7 8 9 10 seq(1, 10, by=2) # [1] 1 3 5 7 9 (every 2nd) seq(1, 10, length.out=5) # [1] 1.00 3.25 5.50 7.75 10.00 rep(5, times=3) # [1] 5 5 5 (repeat) 1:10 # [1] 1 2 3 4 5 6 7 8 9 10 (shortcut)
CONTROL FLOW: IF/ELSE:
Making decisions in code
# Simple if age <- 20 if (age >= 18) { print("You are an adult") } # [1] "You are an adult" # If/else age <- 16 if (age >= 18) { print("Adult") } else { print("Minor") } # [1] "Minor" # If/else if/else (multiple conditions) score <- 78 if (score >= 90) { grade <- "A" } else if (score >= 80) { grade <- "B" } else if (score >= 70) { grade <- "C" } else { grade <- "F" } print(grade) # [1] "C" # Nested if age <- 25 income <- 30000 if (age >= 18) { if (income > 25000) { status <- "Adult with good income" } else { status <- "Adult with low income" } } else { status <- "Minor" } print(status)
CONTROL FLOW: LOOPS:
Repeating code multiple times
# FOR LOOP - repeat specific number of times for (i in 1:5) { print(i) } # [1] 1 # [1] 2 # [1] 3 # [1] 4 # [1] 5 # FOR LOOP - iterate over vector fruits <- c("apple", "banana", "cherry") for (fruit in fruits) { print(fruit) } # [1] "apple" # [1] "banana" # [1] "cherry" # FOR LOOP - calculate something results <- vector("numeric", 5) for (i in 1:5) { results[i] <- i ^ 2 } results # [1] 1 4 9 16 25 # WHILE LOOP - repeat while condition is true count <- 1 while (count <= 3) { print(count) count <- count + 1 } # [1] 1 # [1] 2 # [1] 3 # PRACTICAL EXAMPLE: Process each row of data students <- data.frame( name = c("Alice", "Bob", "Charlie"), score = c(85, 92, 78) ) for (i in 1:nrow(students)) { print(paste( students$name[i], "scored", students$score[i] )) } # [1] "Alice scored 85" # [1] "Bob scored 92" # [1] "Charlie scored 78" # VECTORIZATION - The R Way (avoid loops!) # Instead of loop: # for (i in 1:length(v)) v[i] <- v[i] ^ 2 # Do this: v <- c(1, 2, 3, 4, 5) v_squared <- v ^ 2 # Vectorized! v_squared # [1] 1 4 9 16 25 # WHY? Vectorization is MUCH faster in R!
APPLY FAMILY - R's "Loop Alternative":
# apply() - apply function to rows/columns of matrix m <- matrix(1:12, nrow=3) apply(m, 1, sum) # Sum each row: [1] 22 26 30 apply(m, 2, mean) # Mean of each column: [1] 2 5 8 11 # lapply() - apply to list, return list lapply(list(1:3, 4:6), sum) # [[1]] [1] 6 # [[2]] [1] 15 # sapply() - apply to list, simplify to vector sapply(list(1:3, 4:6), sum) # [1] 6 15 # mapply() - apply function to multiple vectors v1 <- c(1, 2, 3) v2 <- c(10, 20, 30) mapply(function(x, y) x + y, v1, v2) # [1] 11 22 33
WHAT ARE R PACKAGES?
R packages are collections of functions, data, and documentation. Base R has basic functions, but packages extend capabilities.
Think: R = car engine, Packages = specialized tools
INSTALLING PACKAGES:
Two methods:
Method 1 - Console:
install.packages("ggplot2") install.packages(c("ggplot2", "dplyr", "tidyr")) # Multiple
Method 2 - RStudio GUI:
IMPORTANT: Install once per computer!
LOADING PACKAGES:
After installing, load before use:
library(ggplot2) library(dplyr) # Alternative require(ggplot2)
DIFFERENCE:
ESSENTIAL PACKAGES FOR THIS COURSE:
# Install all at once install.packages(c( "tidyverse", # Everything data analysis "ggplot2", # Beautiful graphics "dplyr", # Data manipulation "tidyr", # Data reshaping "readr", # Reading data "caret", # Machine learning "rpart", # Decision trees "randomForest", # Random forests "rpart.plot", # Tree visualization "forecast", # Time series "gridExtra", # Arrange plots "RColorBrewer", # Color palettes "corrplot" # Correlation heatmaps )) # Load main ones library(tidyverse) library(ggplot2) library(dplyr) library(caret) library(forecast)
WHAT EACH PACKAGE DOES:
tidyverse - THE most important package
ggplot2 - Create professional graphics
dplyr - Manipulate data like a pro
tidyr - Reshape data
caret - Machine learning made easy
forecast - Time series analysis
CHECKING INSTALLED PACKAGES:
# What packages are loaded? .packages() # What packages are installed? library() # Opens list # Is package available? require("ggplot2") # TRUE if installed # Get package info packageVersion("ggplot2") # [1] '3.4.2' help(package = "ggplot2") # Documentation
UPDATING PACKAGES:
# Update specific package install.packages("ggplot2") # Update all packages update.packages() # Check version conflicts old.packages()
LOADING PACKAGES IN SCRIPTS:
Best practice at top of script:
# ============================================ # R Script: Customer Analysis # Created: 2024-01-15 # Updated: 2024-01-20 # ============================================ # Load required packages library(tidyverse) library(ggplot2) library(dplyr) library(caret) # Set seed for reproducibility set.seed(42) # Code follows...
READING DATA FROM FILES:
CSV (Comma-Separated Values) - Most common
# Base R method data <- read.csv("data.csv") # Tidyverse method (more options) library(readr) data <- read_csv("data.csv") # With options data <- read_csv( "data.csv", col_types = cols( age = col_integer(), score = col_double() ), na = c("NA", "N/A", "-") # What counts as missing ) # Excel files library(readxl) data <- read_excel("data.xlsx", sheet = 1) # JSON files library(jsonlite) data <- fromJSON("data.json") # Database connection library(DBI) conn <- dbConnect(RSQLite::SQLite(), "database.db") data <- dbReadTable(conn, "table_name")
EXPLORING YOUR DATA:
After loading, ALWAYS explore first!
# Load data data <- read_csv("customers.csv") # Quick look head(data) # First 6 rows tail(data) # Last 6 rows head(data, 10) # First 10 rows # Structure str(data) # MOST IMPORTANT! # Shows: # - Column names # - Data types # - First few values # Example output: # 'data.frame': 150 obs. of 5 variables: # $ id : int 1 2 3 4 5... # $ name : chr "Alice" "Bob" "Charlie"... # $ age : int 25 30 28... # $ score : num 85 90 78... # $ date : Date, format: "2023-01-15" "2023-01-16"... # Dimensions dim(data) # [1] 150 5 (150 rows, 5 columns) nrow(data) # [1] 150 ncol(data) # [1] 5 # Column names names(data) # Shows all column names colnames(data) # Alternative # Summary statistics summary(data) # Shows min, Q1, median, mean, Q3, max for each column # Data info info(data) # From skimr package (optional) glimpse(data) # From dplyr package (nice!) # Missing values sum(is.na(data)) # Total missing colSums(is.na(data)) # Missing per column sum(is.na(data)) / nrow(data) # % missing
SAMPLE OUTPUT:
glimpse(mtcars) # Rows: 32 # Columns: 11 # $ mpg <dbl> 21.0, 21.0, 22.8, 21.4, 18.7, 18.1, 14.3, 24.4, 22.8, 19.2, ... # $ cyl <dbl> 6, 6, 4, 6, 8, 6, 8, 4, 4, 6, ... # $ hp <dbl> 110, 110, 93, 110, 175, 105, 245, 62, 95, 123, ...
ACCESSING DATA:
Different ways to get columns/rows
# Load sample data data <- tibble( name = c("Alice", "Bob", "Charlie"), age = c(25, 30, 28), score = c(85, 90, 78) ) # Access columns - three ways data$name # Simplest data[["name"]] # More robust data["name"] # Returns data frame # Get specific rows data[1, ] # First row data[c(1, 3), ] # Rows 1 and 3 data[data$age > 28, ] # Rows where age > 28 # Get specific cell data[1, 2] # Row 1, Column 2 = 25 data[1, "age"] # Row 1, "age" column = 25 data$age[1] # First age value = 25
WORKING WITH DIFFERENT DATA TYPES:
# Creating example data with different types people <- tibble( name = c("Alice", "Bob", "Charlie"), # character age = c(25, 30, 28), # numeric hired_date = as.Date(c("2020-01-15", "2021-03-20", "2019-07-10")), # date is_manager = c(TRUE, FALSE, TRUE) # logical ) # Check types typeof(people$age) # [1] "double" class(people$hired_date) # [1] "Date" # Convert types if needed people$age_int <- as.integer(people$age) people$name_upper <- toupper(people$name)
WRITING DATA:
Saving your processed data
# Write CSV write.csv(data, "output.csv", row.names = FALSE) # Tidyverse version write_csv(data, "output.csv") # Write Excel writexl::write_xlsx(data, "output.xlsx") # Write multiple sheets list_of_sheets <- list( "Sheet1" = data1, "Sheet2" = data2 ) writexl::write_xlsx(list_of_sheets, "multi_sheet.xlsx")
By completing Week 1, you have learned: