Course objectives, schedule, assignments · Introduction to R · Live coding
Scope
We will:
We will NOT:
Approach
Part I — Learn the Basics
Part II — Apply your learnings
Basics
Week 1
29.10.2025
Course objectives, schedule, assignments · Introduction to R · Live coding
Data Handling & Visualization
Week 2
05.11.2025
API access, merging, cleansing, transforming and visualising financial data in R · Introduction to Overleaf
Statistical Analysis
Week 3
12.11.2025
Descriptive · inferential · modelling — applied in R
Academic Publishing & Refereeing
Week 4
19.11.2025
What makes a great empirical paper · publication process · how to write a referee report
Brown Bag Seminar
Week 13
20.01.2026
Engage with doctoral research and prepare your referee report
Assignment I — Problem Set 50% of your grade
Documented .R script + PDF write-up (Overleaf)
Group of up to 5.
Submit by emailing oliver.padmaperuma@uni-ulm.de, CC andre.guettler@uni-ulm.de. Subject pattern: Research in Finance_assignment-1-problem-set_surname1_surname2_…
19 January 2026
Assignment II — Referee Report 50% of your grade
2.5–3 page referee report on a Brown-Bag presentation
Group of up to 5.
Submit by emailing oliver.padmaperuma@uni-ulm.de, CC andre.guettler@uni-ulm.de. Subject pattern: Research in Finance_assignment-2-referee-report_surname1_surname2_…
3 February 2026
Open the Mentimeter link shared in class.

In order to use RStudio, you need to have R installed. RStudio is just the interface. R does the actual computing.
.exe. Accept defaults.Three main panes when you open RStudio:

.R scripts.Write and run code through the Script Editor. Use the Console only for quick exploration.
wd) is where R looks for and saves files.setwd().getwd() to avoid confusion about where your files are being read from or written to.The blinking cursor in the Script Editor prompts you to write. The Console shows > when R is ready.
Four ways to run code:
Short exercise
Type 1 + 2*8 and log(10). Result appears in the Console with a leading [1] (the index of the first element on that line).

Or click Install in the Packages tab.
Or tick the package’s checkbox in the Packages tab.
Short exercise
Install and load the tidyverse, tidyquant, and Quandl packages.
_ or .x and X are different)= for function arguments, but “<-” for assignment to avoid confusion= for assignment in scripts, as it can lead to bugs and readability issuesL)." ".TRUE / FALSE).
class(objectname)returns the higher-level label R uses to decide which functions and behaviors apply ("data.frame","factor","matrix","numeric").
subset(myData, myData$sector == "Tech"))# Create
myVector <- c(3, 4, -1.1, pi)
# Inspect / aggregate
myVector[3] # third element: -1.1
length(myVector) # 4
sum(myVector) # ~9.04
mean(myVector) # ~2.26
var(myVector) # ~5.21
sort(myVector) # ascending: -1.1, 3.0, 3.14, 4.0
quantile(myVector, c(0.1, 0.25, 0.95))
# Vectorized arithmetic — no loops needed
myVector + 2
myVector * myVector
# Coercion: mixed types collapse to character
mixed <- c(1, "two", TRUE) # "1" "two" "TRUE"
# Named vectors
namedVec <- c(apple = 5, banana = 3)
namedVec["banana"] # 3c() combines values into a vector; indexing with [] retrieves elementsmyMatrix <- matrix(c(2, 1, 0, -9, 5, 0), nrow = 2, byrow = TRUE)
dim(myMatrix) # [1] 2 3
myMatrix[1, 1] <- 2.1415 # modify cell
myMatrix[, 2] # second column
# Linear algebra
anotherMatrix <- matrix(c(5, -1, 7, 0, 2, -1), nrow = 2, byrow = TRUE)
transposedMatrix <- t(anotherMatrix)
matrixProduct <- myMatrix %*% transposedMatrix # 2x2 product
matrixInverse <- solve(matrixProduct) # inverse
# Aggregations
rowSums(myMatrix)
colMeans(myMatrix)
# Bind: combine rows / cols
cbind(myMatrix, c(6, 7))matrix() creates a matrix from a vector of values; specify nrow and ncol to set dimensions; byrow = TRUE fills by rows instead of columnsrowSums(), colMeans(), and cbind() allow you to perform common matrix manipulations without writing loopsstudent_name <- c("Student A", "Student B", "Student C")
grade <- c(1.7, 2.3, 5.0)
students <- data.frame(student_name, grade)
students$grade # column access
colnames(students)[2] <- "exam2021"
students[2:3, ] # rows 2-3
# Add columns
students$degree <- c("Bachelor", "Master", "Bachelor")
students$pass_fail <- c("Pass", "Pass", "Fail")
table(students$degree, students$pass_fail)
# Summary
summary(students)
# Subset by condition
subset(students, exam2021 > 2)
# Add row
newStudent <- data.frame(student_name = "Student D", exam2021 = 3.5,
degree = "PhD", pass_fail = "Pass")
students <- rbind(students, newStudent)
# Merge with another frame
ages <- data.frame(student_name = c("Student A", "Student B", "Student C"),
age = c(20, 22, 21))
merged <- merge(students, ages, by = "student_name")data.frame() creates a data frame from vectors; columns can have different types; access with $ or []scoresList <- list(
scores = c(95, 85, 92),
names = c("Alice", "Bob", "Carol"),
passed = c(TRUE, TRUE, FALSE)
)
str(scoresList)
scoresList$scores[3] <- 90 # update Carol's score
scoresList$comments <- "All passed" # add element
# Nested list
nestedList <- list(course = "Math 101", details = scoresList)
nestedList$details$names[1] # "Alice"
# Convert to data frame (elements need equal length)
scoresDF <- as.data.frame(scoresList)list() creates a list; access with $ or []; lists can contain any type of object, including other lists# Define
bmiCalc <- function(height, weight) {
bmi <- weight / (height ^ 2)
return(round(bmi, 1))
}
# Call
myBmi <- bmiCalc(1.75, 70) # 22.9
# Default arguments
bmiCalcDefault <- function(height, weight = 70) {
round(weight / (height ^ 2), 1)
}
bmiCalcDefault(1.75) # 22.9
# Multiple returns via list
bmiAdvanced <- function(height, weight) {
bmi <- weight / (height ^ 2)
category <- ifelse(bmi < 18.5, "Underweight",
ifelse(bmi < 25, "Normal", "Overweight"))
list(bmi = round(bmi, 1), category = category)
}
result <- bmiAdvanced(1.75, 70)
result$bmi # 22.9
result$category # "Normal"function(arg1, arg2) { ... } defines a function; use return() to specify output; functions can have default arguments and return multiple values via listsfor (var in sequence) { ... } iterates over elements; while (condition) { ... } continues until condition is falsedplyr that abstract away the need for explicit loops when working with data framesYou will rarely build matrices/data frames by hand. Common ways to read data:
.TXT (readLines()).CSV, .TSV (read.table(), readr::read_csv()).XLSX (xlsx, readxl)googlesheets4haven)RMySQL)# CSV
write.csv(objectname, file = "output_file.csv", row.names = FALSE)
# Tab-delimited
write.table(objectname, file = "output_file.txt",
sep = "\t", row.names = FALSE, col.names = TRUE)
# Excel
library(writexl)
write_xlsx(objectname, "output_file.xlsx")
# RDS
saveRDS(objectname, file = "output_file.rds")The argument
sep =may not be necessary — R recognises,in.csvand whitespace in.txt. But sometimes R won’t read correctly unless you specify it
.R script. Comment lines start with # and are ignored at run time.Three ways to close RStudio:
q() in the Console.Don’t save the workspace image (.RData)
Unless (a) you ran something very expensive, or (b) you’re nearly done with the project. Starting clean each session avoids hidden state from previous runs.
Basics
Week 1
29.10.2025
Course objectives, schedule, assignments · Introduction to R · Live coding
Data Handling & Visualization
Week 2
05.11.2025
API access, merging, cleansing, transforming and visualising financial data in R · Introduction to Overleaf
Statistical Analysis
Week 3
12.11.2025
Descriptive · inferential · modelling — applied in R
Academic Publishing & Refereeing
Week 4
19.11.2025
What makes a great empirical paper · publication process · how to write a referee report
Brown Bag Seminar
Week 13
20.01.2026
Engage with doctoral research and prepare your referee report
.Rmd.Quandl library, set your key with Quandl.api_key("your_key_here"), and test loading data. We’ll walk through this in Lecture 2.Reminder
campusonline by 30 November 2025.tidyverse, tidyquant, Quandl packages already loaded.dplyr, ggplot2.Institute of Strategic Management and Finance · Ulm University