22.06.2026, 18:33 HBA12H Exam Study Guide
HBA12H Data & Programming Skills — FULL Study Guide
Based on lecture scripts + June 2025 Exam Set A (seed = 1000)
EXAM DAY SETUP (do this first, every time!)
# 1. Open examfunction.R
# 2. Line 17: replace XXXX with your seed value, e.g.:
value_seed <- 1000
# 3. Select ALL lines → Run
# 4. Close examfunction.R → Open a NEW empty R script
# 5. Save it as exam_YOURSTUDENTNUMBER.R and save often!
# You now have df_regular + tidyverse + readxl loaded
PART 1 — DATA FRAME QUESTIONS (seed = 1000)
Q1: Count auctions — paintings in London
df_regular |>
filter(item == "paintings", auction_location == "London") |>
summarise(n = n())
# Answer: C — 501
Q2: Min final_bid — maps, Europe buyers
df_regular |>
filter(item == "maps", final_bidder_location == "Europe") |>
summarise(min(final_bid))
# Answer: B — 445.7761 (RStudio may show 446 due to rounding)
# TIP: to see full decimals, run options(digits = 10) at the top of your script
# or wrap result in print(digits = 10)
Q3: Avg gap (final_bid - estimated_bid) — wines, num_bids >= 5
df_regular |>
filter(item == "wines", num_bids >= 5) |>
mutate(gap_fin_est_bid = final_bid - estimated_bid) |>
summarise(mean(gap_fin_est_bid))
# Answer: C — 30.3228913
Q4: Second busiest day for London auctions
df_regular |>
filter(auction_location == "London") |>
mutate(day = wday(date, label = TRUE, abbr = FALSE,
week_start = getOption("lubridate.week.start", 1),
locale = Sys.setlocale("LC_TIME", "en"))) |>
group_by(day) |>
summarise(n = n()) |>
arrange(desc(n))
# Row 2 = Answer: C — Tuesday
Q5: Avg offered_quantity — paintings, weeks 26-52
# NOTE: typo in data — "offered_quantity" (one t!)
df_regular |>
mutate(week = isoweek(date)) |>
filter(item == "paintings", week >= 26) |>
summarise(mean(offered_quantity))
# Answer: C — 4.3181818
Q6: Item with highest share of accepted bids
df_regular |>
mutate(accepted = final_bid >= min_bid) |>
file:///C:/Users/weron/AppData/Local/Temp/2a05e0b2-fb8b-4b49-95eb-914357cd3efd_dAp.zip.efd/exam_study_guide_PRINT (4).html 1/16
,22.06.2026, 18:33 HBA12H Exam Study Guide
group_by(item) |>
summarise(share = mean(accepted)) |>
arrange(desc(share))
# Answer: A — manuscripts
Q7: Combine regular + specials, count manuscripts
df_specials <- read.csv(here::here("data", "raw", "specials_bid_data.csv"))
df_full <- bind_rows(
df_regular |> mutate(type = "regular"),
df_specials |> mutate(type = "special")
)
df_full |> filter(item == "manuscripts") |> summarise(n = n())
# Answer: B — 825
Q8: Avg final_bid difference (regular - special) for paintings
avg_reg <- df_full |> filter(item=="paintings", type=="regular") |> pull(final_bid) |> mean()
avg_spe <- df_full |> filter(item=="paintings", type=="special") |> pull(final_bid) |> mean()
avg_reg - avg_spe
# Answer: C — -45360.08
Q9: Fee for antiques, not accepted, special auction
df_auction_fee <- read.csv(here::here("data", "raw", "auction_fee_data.csv"))
df_auction_fee |>
mutate(accepted_false = as.numeric(str_remove(accepted_false, "%")) / 100) |>
filter(item == "antiques", type == "special") |>
select(accepted_false)
# Answer: A — 0.03
Q10: Tidy fee data → join → fee_revenue → top item in Paris
# Step 1: tidy fee data
df_fee_tidy <- df_auction_fee |>
mutate(
accepted_true = as.numeric(str_remove(accepted_true, "%")) / 100,
accepted_false = as.numeric(str_remove(accepted_false, "%")) / 100
) |>
pivot_longer(cols = c(accepted_true, accepted_false),
names_to = "accepted", values_to = "fee") |>
mutate(accepted = accepted == "accepted_true") # → logical TRUE/FALSE
# Step 2: create accepted in df_regular
df_regular_acc <- df_regular |> mutate(accepted = final_bid >= min_bid)
# Step 3: join on item + accepted, only regular fees
df_joined <- df_regular_acc |>
left_join(df_fee_tidy |> filter(type == "regular"), by = c("item", "accepted"))
# Step 4: fee_revenue, filter Paris, top item
df_joined |>
filter(auction_location == "Paris") |>
mutate(fee_revenue = final_bid * offered_quantity * fee) |>
group_by(item) |>
summarise(total = sum(fee_revenue)) |>
arrange(desc(total))
# Answer: C — paintings
Q11: Import exchange rates → tidy → avg HKD rate
df_currency <- read_xlsx(here::here("data", "raw", "exchange_rates_2024.xlsx"))
# Rename the long ECB column names
df_currency <- df_currency |>
rename(
date = DATE,
gbp = `UK pound sterling/Euro (EXR.M.GBP.EUR.SP00.A)`,
hkd = `Hong Kong dollar/Euro (EXR.M.HKD.EUR.SP00.A)`,
usd = `US dollar/Euro (EXR.M.USD.EUR.SP00.A)`
) |>
mutate(
date = as.POSIXct(date),
month = month(date, label = TRUE, abbr = FALSE,
file:///C:/Users/weron/AppData/Local/Temp/2a05e0b2-fb8b-4b49-95eb-914357cd3efd_dAp.zip.efd/exam_study_guide_PRINT (4).html 2/16
, 22.06.2026, 18:33 HBA12H Exam Study Guide
locale = Sys.setlocale("LC_TIME", "en")),
eur = 1
) |>
pivot_longer(cols = c(gbp, hkd, usd, eur),
names_to = "currency", values_to = "rate")
df_currency |> filter(currency == "hkd") |> summarise(mean(rate, na.rm = TRUE))
# Answer: C — 8.442975
Q12: Add currency to df_regular → join → avg local bid for sculptures in HK
df_regular2 <- df_regular |>
mutate(
date = as.POSIXct(date),
month = month(date, label = TRUE, abbr = FALSE,
locale = Sys.setlocale("LC_TIME", "en")),
currency = case_when(
auction_location == "Hong Kong" ~ "hkd",
auction_location == "Paris" ~ "eur",
auction_location == "London" ~ "gbp",
auction_location %in% c("New York", "Online") ~ "usd"
)
)
df_foreigncur <- df_regular2 |>
left_join(df_currency, by = c("currency", "month"))
df_foreigncur |>
filter(item == "sculptures", auction_location == "Hong Kong") |>
mutate(final_bid_localcurrency = final_bid * rate) |>
summarise(mean(final_bid_localcurrency))
# Answer: C — 230557
Q13: 50x50 matrix → *3 → standardise cols → sum row 35
mat1 <- matrix(0, nrow = 50, ncol = 50)
for (i in 1:50) for (j in 1:50) mat1[i,j] <- 2*i + j
mat1 <- mat1 * 3
mat2 <- apply(mat1, 2, function(x) (x - mean(x)) / sum(x))
sum(mat2[35, ])
# Answer: A — 0.2578168
Q14: mat3 — even→2, odd→3, sum col 35
mat3 <- ifelse(mat1 %% 2 == 0, 2, 3)
sum(mat3[, 35])
# Answer: C — 150
Q15: List with seq + LETTERS, sum vec_num where vec_char == "A"
list1 <- list(
vec_num = seq(from = 5, by = 5, length.out = 520),
vec_char = rep(LETTERS, 20) # 26 * 20 = 520 elements
)
sum(list1$vec_num[list1$vec_char == "A"])
# Answer: C — 24800
Q16: vec_calc — /2 if A-M, *2 if N-Z, sd of A-M part
list1$vec_calc <- ifelse(
list1$vec_char %in% LETTERS[1:13],
list1$vec_num / 2,
list1$vec_num * 2
)
sd(list1$vec_calc[list1$vec_char %in% LETTERS[1:13]])
# Answer: B — 375.65
Q17: Seconds between 8:32 AM and 15:30
start <- as.POSIXct("2025-06-23 08:32:00")
end <- as.POSIXct("2025-06-23 15:30:00")
as.numeric(difftime(end, start, units = "secs"))
# Answer: C — 25080
file:///C:/Users/weron/AppData/Local/Temp/2a05e0b2-fb8b-4b49-95eb-914357cd3efd_dAp.zip.efd/exam_study_guide_PRINT (4).html 3/16
HBA12H Data & Programming Skills — FULL Study Guide
Based on lecture scripts + June 2025 Exam Set A (seed = 1000)
EXAM DAY SETUP (do this first, every time!)
# 1. Open examfunction.R
# 2. Line 17: replace XXXX with your seed value, e.g.:
value_seed <- 1000
# 3. Select ALL lines → Run
# 4. Close examfunction.R → Open a NEW empty R script
# 5. Save it as exam_YOURSTUDENTNUMBER.R and save often!
# You now have df_regular + tidyverse + readxl loaded
PART 1 — DATA FRAME QUESTIONS (seed = 1000)
Q1: Count auctions — paintings in London
df_regular |>
filter(item == "paintings", auction_location == "London") |>
summarise(n = n())
# Answer: C — 501
Q2: Min final_bid — maps, Europe buyers
df_regular |>
filter(item == "maps", final_bidder_location == "Europe") |>
summarise(min(final_bid))
# Answer: B — 445.7761 (RStudio may show 446 due to rounding)
# TIP: to see full decimals, run options(digits = 10) at the top of your script
# or wrap result in print(digits = 10)
Q3: Avg gap (final_bid - estimated_bid) — wines, num_bids >= 5
df_regular |>
filter(item == "wines", num_bids >= 5) |>
mutate(gap_fin_est_bid = final_bid - estimated_bid) |>
summarise(mean(gap_fin_est_bid))
# Answer: C — 30.3228913
Q4: Second busiest day for London auctions
df_regular |>
filter(auction_location == "London") |>
mutate(day = wday(date, label = TRUE, abbr = FALSE,
week_start = getOption("lubridate.week.start", 1),
locale = Sys.setlocale("LC_TIME", "en"))) |>
group_by(day) |>
summarise(n = n()) |>
arrange(desc(n))
# Row 2 = Answer: C — Tuesday
Q5: Avg offered_quantity — paintings, weeks 26-52
# NOTE: typo in data — "offered_quantity" (one t!)
df_regular |>
mutate(week = isoweek(date)) |>
filter(item == "paintings", week >= 26) |>
summarise(mean(offered_quantity))
# Answer: C — 4.3181818
Q6: Item with highest share of accepted bids
df_regular |>
mutate(accepted = final_bid >= min_bid) |>
file:///C:/Users/weron/AppData/Local/Temp/2a05e0b2-fb8b-4b49-95eb-914357cd3efd_dAp.zip.efd/exam_study_guide_PRINT (4).html 1/16
,22.06.2026, 18:33 HBA12H Exam Study Guide
group_by(item) |>
summarise(share = mean(accepted)) |>
arrange(desc(share))
# Answer: A — manuscripts
Q7: Combine regular + specials, count manuscripts
df_specials <- read.csv(here::here("data", "raw", "specials_bid_data.csv"))
df_full <- bind_rows(
df_regular |> mutate(type = "regular"),
df_specials |> mutate(type = "special")
)
df_full |> filter(item == "manuscripts") |> summarise(n = n())
# Answer: B — 825
Q8: Avg final_bid difference (regular - special) for paintings
avg_reg <- df_full |> filter(item=="paintings", type=="regular") |> pull(final_bid) |> mean()
avg_spe <- df_full |> filter(item=="paintings", type=="special") |> pull(final_bid) |> mean()
avg_reg - avg_spe
# Answer: C — -45360.08
Q9: Fee for antiques, not accepted, special auction
df_auction_fee <- read.csv(here::here("data", "raw", "auction_fee_data.csv"))
df_auction_fee |>
mutate(accepted_false = as.numeric(str_remove(accepted_false, "%")) / 100) |>
filter(item == "antiques", type == "special") |>
select(accepted_false)
# Answer: A — 0.03
Q10: Tidy fee data → join → fee_revenue → top item in Paris
# Step 1: tidy fee data
df_fee_tidy <- df_auction_fee |>
mutate(
accepted_true = as.numeric(str_remove(accepted_true, "%")) / 100,
accepted_false = as.numeric(str_remove(accepted_false, "%")) / 100
) |>
pivot_longer(cols = c(accepted_true, accepted_false),
names_to = "accepted", values_to = "fee") |>
mutate(accepted = accepted == "accepted_true") # → logical TRUE/FALSE
# Step 2: create accepted in df_regular
df_regular_acc <- df_regular |> mutate(accepted = final_bid >= min_bid)
# Step 3: join on item + accepted, only regular fees
df_joined <- df_regular_acc |>
left_join(df_fee_tidy |> filter(type == "regular"), by = c("item", "accepted"))
# Step 4: fee_revenue, filter Paris, top item
df_joined |>
filter(auction_location == "Paris") |>
mutate(fee_revenue = final_bid * offered_quantity * fee) |>
group_by(item) |>
summarise(total = sum(fee_revenue)) |>
arrange(desc(total))
# Answer: C — paintings
Q11: Import exchange rates → tidy → avg HKD rate
df_currency <- read_xlsx(here::here("data", "raw", "exchange_rates_2024.xlsx"))
# Rename the long ECB column names
df_currency <- df_currency |>
rename(
date = DATE,
gbp = `UK pound sterling/Euro (EXR.M.GBP.EUR.SP00.A)`,
hkd = `Hong Kong dollar/Euro (EXR.M.HKD.EUR.SP00.A)`,
usd = `US dollar/Euro (EXR.M.USD.EUR.SP00.A)`
) |>
mutate(
date = as.POSIXct(date),
month = month(date, label = TRUE, abbr = FALSE,
file:///C:/Users/weron/AppData/Local/Temp/2a05e0b2-fb8b-4b49-95eb-914357cd3efd_dAp.zip.efd/exam_study_guide_PRINT (4).html 2/16
, 22.06.2026, 18:33 HBA12H Exam Study Guide
locale = Sys.setlocale("LC_TIME", "en")),
eur = 1
) |>
pivot_longer(cols = c(gbp, hkd, usd, eur),
names_to = "currency", values_to = "rate")
df_currency |> filter(currency == "hkd") |> summarise(mean(rate, na.rm = TRUE))
# Answer: C — 8.442975
Q12: Add currency to df_regular → join → avg local bid for sculptures in HK
df_regular2 <- df_regular |>
mutate(
date = as.POSIXct(date),
month = month(date, label = TRUE, abbr = FALSE,
locale = Sys.setlocale("LC_TIME", "en")),
currency = case_when(
auction_location == "Hong Kong" ~ "hkd",
auction_location == "Paris" ~ "eur",
auction_location == "London" ~ "gbp",
auction_location %in% c("New York", "Online") ~ "usd"
)
)
df_foreigncur <- df_regular2 |>
left_join(df_currency, by = c("currency", "month"))
df_foreigncur |>
filter(item == "sculptures", auction_location == "Hong Kong") |>
mutate(final_bid_localcurrency = final_bid * rate) |>
summarise(mean(final_bid_localcurrency))
# Answer: C — 230557
Q13: 50x50 matrix → *3 → standardise cols → sum row 35
mat1 <- matrix(0, nrow = 50, ncol = 50)
for (i in 1:50) for (j in 1:50) mat1[i,j] <- 2*i + j
mat1 <- mat1 * 3
mat2 <- apply(mat1, 2, function(x) (x - mean(x)) / sum(x))
sum(mat2[35, ])
# Answer: A — 0.2578168
Q14: mat3 — even→2, odd→3, sum col 35
mat3 <- ifelse(mat1 %% 2 == 0, 2, 3)
sum(mat3[, 35])
# Answer: C — 150
Q15: List with seq + LETTERS, sum vec_num where vec_char == "A"
list1 <- list(
vec_num = seq(from = 5, by = 5, length.out = 520),
vec_char = rep(LETTERS, 20) # 26 * 20 = 520 elements
)
sum(list1$vec_num[list1$vec_char == "A"])
# Answer: C — 24800
Q16: vec_calc — /2 if A-M, *2 if N-Z, sd of A-M part
list1$vec_calc <- ifelse(
list1$vec_char %in% LETTERS[1:13],
list1$vec_num / 2,
list1$vec_num * 2
)
sd(list1$vec_calc[list1$vec_char %in% LETTERS[1:13]])
# Answer: B — 375.65
Q17: Seconds between 8:32 AM and 15:30
start <- as.POSIXct("2025-06-23 08:32:00")
end <- as.POSIXct("2025-06-23 15:30:00")
as.numeric(difftime(end, start, units = "secs"))
# Answer: C — 25080
file:///C:/Users/weron/AppData/Local/Temp/2a05e0b2-fb8b-4b49-95eb-914357cd3efd_dAp.zip.efd/exam_study_guide_PRINT (4).html 3/16