Syllabus học R
PHASE 0 - Setup & Tooling
Ngày 1: Cài đặt môi trường
Khái niệm
R base vs R interpreter (GNU R) vs các implementation khác (Microsoft R Open, renjin) - vì sao ta chọn GNU R chuẩn.
RStudio vs Positron (IDE mới của Posit, hỗ trợ đa ngôn ngữ) - chọn 1 để dùng xuyên suốt.
Thực hành và quan sát
Cài R + IDE. Chạy
R.versionđể xem build info,.Platformđể xem OS/GUI info.Cài
renv::init()ngay từ project đầu tiên - hiểu vì sao "cài global package" là anti-pattern cho production.
Advanced concepts
- So sánh CRAN mirror vs Posit Package Manager (binary packages, tốc độ cài đặt trên Linux).
Ngày 2: Git, cấu trúc project, .Rprofile
Khái niệm
.Rprofilevs.Renviron- thứ tự load khi R khởi động (site-wide → user → project).R project layout chuẩn (chưa phải package):
R/,data/,analysis/,outputs/.
Thực hành và quan sát
Tạo
.gitignorechuẩn cho R (.Rhistory,.RData,renv/library).Viết
.Rprofileproject-level set optionoptions(scipen=999, stringsAsFactors=FALSE), quan sát tác động.
Advanced concepts
Rscript --vanillavs interactive session - sự khác biệt khi chạy trong CI/production (không load .Rprofile của user).
PHASE 1 - Core R Language
Ngày 3: Vectors & atomic types
Khái niệm
6 atomic types: logical, integer, double, character, complex, raw. Type hierarchy khi coerce.
R không có scalar thật - mọi số đơn lẻ là vector độ dài 1.
Thực hành và quan sát
typeof(),class(),storage.mode()- quan sát sự khác biệt giữa 3 hàm này trên cùng object.Test
1Lvs1- integer vs double,.Machine$integer.max.
Advanced concepts
- Implicit coercion order: logical < integer < double < character. Viết vector trộn lẫn và dự đoán kết quả trước khi chạy.
Ngày 4: Lists & cấu trúc đệ quy
Khái niệm
List là vector generic (mỗi phần tử có thể khác type/độ dài) - khác atomic vector.
rapply(), đệ quy trên list lồng nhau.
Thực hành và quan sát
str()trên list lồng sâu để hiểu cấu trúc cây.unlist()và các cạm bẫy khi flatten list có tên trùng.
Advanced concepts
- List columns trong data.frame/tibble (mỗi ô chứa một object phức tạp) - nền tảng cho nested data workflow.
Ngày 5: Matrices & Arrays
Khái niệm
- Matrix = vector với
dimattribute. Column-major storage order (khác Python numpy row-major mặc định).
- Matrix = vector với
Thực hành và quan sát
Tạo matrix, kiểm tra
attributes(), thử đổidim()trực tiếp trên vector.So sánh tốc độ matrix multiplication
%*%với BLAS mặc định vs OpenBLAS.
Advanced concepts
- Array 3D+ và ứng dụng trong xử lý ảnh/tensor cơ bản; sparse matrix với
Matrixpackage.
- Array 3D+ và ứng dụng trong xử lý ảnh/tensor cơ bản; sparse matrix với
Ngày 6: Data frames
Khái niệm
- data.frame = list of vectors cùng độ dài + class "data.frame". Row-based mental model nhưng column-based storage.
Thực hành và quan sát
- So sánh
data.framevstibble(không auto-coerce string, in đẹp hơn, không partial matching$).
- So sánh
Advanced concepts
attr(df, "row.names")- vì sao row names không nên dùng làm dữ liệu thật.
Ngày 7: Factors
Khái niệm
- Factor = integer vector + attribute
levels. Vì sao factor tồn tại (tiết kiệm bộ nhớ, thứ tự categorical).
- Factor = integer vector + attribute
Thực hành và quan sát
Bẫy kinh điển:
as.numeric(factor_vector)trả về level index, không phải giá trị gốc.forcats::fct_reorder(),fct_lump().
Advanced concepts
- Ordered factor và ảnh hưởng lên
lm()/glm()(contrast coding).
- Ordered factor và ảnh hưởng lên
Ngày 8: NA/NULL/NaN/Inf & coercion
Khái niệm
NAlà placeholder trong vector (có type:NA_integer_,NA_real_...),NULLlà "không tồn tại" (độ dài 0),NaNlà kết quả toán học không xác định.
Thực hành và quan sát
is.na(NaN)trả về TRUE - hiểu vì sao.NULL == NULLtrả vềlogical(0).
Advanced concepts
vctrs::vec_ptype2()cách hệ tidyverse hiện đại xử lý coercion an toàn hơn base R.
Ngày 9: Subsetting [, [[, $
Khái niệm
[giữ nguyên type container (list → list),[[trích xuất phần tử đơn (list → element),$là[[với partial matching.
Thực hành và quan sát
- Viết bảng so sánh 6 kiểu index: positive, negative, logical, character, zero, NA - trên cả vector và list.
Advanced concepts
- Subsetting và assignment (
x[i] <- value) - cách R compile thành`[<-`(x, i, value)phía sau.
- Subsetting và assignment (
Ngày 10: Control flow & tư duy vector hóa
Khái niệm
for/while/repeatvs vectorized operations - tại sao for-loop "chậm" thực chất là do overhead interpreter + growing object, không phải bản chất loop.
Thực hành và quan sát
- Benchmark: loop cộng dồn với
c()growing vsVectorizevssum()trực tiếp - dùngbench::mark().
- Benchmark: loop cộng dồn với
Advanced concepts
ifelse()vsdplyr::if_else()vsdata.table::fifelse()- khác biệt về type-safety và NA handling.
Ngày 11: Functions, arguments, ...
Khái niệm
Function là first-class object. Matching argument: exact → partial → positional.
...(dots) - cách truyền và forward argument động.
Thực hành và quan sát
- Viết hàm dùng
..., kiểm tralist(...),..1,..2,nargs().
- Viết hàm dùng
Advanced concepts
- Default argument được evaluate trong function environment (không phải calling environment) - viết ví dụ default arg tham chiếu argument khác.
Ngày 12: Lazy evaluation & promises (nhập môn)
Khái niệm
- R evaluate argument theo kiểu lazy - argument chỉ tính khi thực sự được dùng trong body hàm (promise).
Thực hành và quan sát
Viết hàm với argument gây side-effect (
print) để chứng minh nó không chạy nếu không được reference.force()- khi nào cần dùng (đặc biệt trong closures tạo trong loop).
Advanced concepts
- Đây là nền tảng cho NSE (Phase 3) - ghi chú lại để quay lại đào sâu.
PHASE 2 - Functional Programming
Ngày 13: Closures & environments
Khái niệm
- Closure = function + environment nó được tạo ra (enclosing environment). Đây là cơ chế R giữ "state".
Thực hành và quan sát
- Viết counter function bằng closure, quan sát mỗi closure có environment riêng biệt.
Advanced concepts
- Bẫy closure trong loop (
lapplyvsforvới<-bind biến) - vì sao purrr/lapply an toàn hơn for-loop truyền thống ở điểm này.
- Bẫy closure trong loop (
Ngày 14: Higher-order functions base R
Khái niệm
- Apply family:
sapply,lapply,vapply,mapply,Map- khác biệt về return type và type-safety.
- Apply family:
Thực hành và quan sát
- Thay toàn bộ
sapplybằngvapplytrong 1 script cũ, quan sát lỗi type xuất hiện (đây là lý do dùng vapply trong production).
- Thay toàn bộ
Advanced concepts
Recall()để viết đệ quy ẩn danh.
Ngày 15: purrr map family
Khái niệm
map(),map_dbl(),map_chr(),map2(),pmap()- type-stable functional programming.
Thực hành và quan sát
- Refactor toàn bộ code Ngày 14 sang purrr, so sánh độ dễ đọc và an toàn type.
Advanced concepts
purrr::safely(),possibly(),quietly()- functional error handling.
Ngày 16: Reduce/Filter/Position & function composition
Khái niệm
Reduce()(fold),Filter(),Find(),Position()- functional primitives kinh điển.
Thực hành và quan sát
- Viết pipeline xử lý dữ liệu chỉ bằng compose function (không dùng pipe), rồi viết lại bằng
|>.
- Viết pipeline xử lý dữ liệu chỉ bằng compose function (không dùng pipe), rồi viết lại bằng
Advanced concepts
- Viết hàm
compose(f, g)tự chế mô phỏng function composition.
- Viết hàm
Ngày 17: Functional cho thống kê - Bootstrap
Khái niệm
- Áp dụng functional programming vào resampling (chuẩn bị cho Phase 5).
Thực hành và quan sát
- Viết bootstrap CI bằng
purrr::map_dbl()+sample(), so sánh vớiboot::boot().
- Viết bootstrap CI bằng
Advanced concepts
- Song song hóa bootstrap bằng
furrr::future_map()(preview Phase 10).
- Song song hóa bootstrap bằng
Ngày 18: Review + mini project
Khái niệm - tổng hợp Phase 1-2.
Thực hành và quan sát
- Project: viết một "toolkit" functional xử lý dữ liệu CSV (đọc, clean, transform) chỉ dùng base R + purrr, không dùng dplyr.
Advanced concepts
- Refactor lại bằng OOP ở Phase 3 để so sánh triết lý thiết kế.
PHASE 3 - OOP & Metaprogramming + Tidy Evaluation
Ngày 19: S3 cơ bản
Khái niệm
- S3 = generic function dispatch dựa trên
class()attribute. Không có formal class definition.
- S3 = generic function dispatch dựa trên
Thực hành và quan sát
- Tạo class S3 thủ công, viết
print.myclass(),summary.myclass().
- Tạo class S3 thủ công, viết
Advanced concepts
UseMethod()cơ chế dispatch - dùngsloop::s3_dispatch()để xem chuỗi method resolution.
Ngày 20: S3 nâng cao
Khái niệm
NextMethod()cho inheritance chain, multiple class vector (class(x) <- c("child","parent")).
Thực hành và quan sát
- Xây class hierarchy 3 tầng, gọi
NextMethod()xuyên suốt.
- Xây class hierarchy 3 tầng, gọi
Advanced concepts
- Double dispatch trong S3 (Ops group generic) - ví dụ
+.myclass.
- Double dispatch trong S3 (Ops group generic) - ví dụ
Ngày 21: S4 classes
Khái niệm
setClass(),setGeneric(),setMethod()- formal system với type-checking tại definition time.
Thực hành và quan sát
- Tạo S4 class có slot với type validation, thử gán sai type để thấy lỗi ngay lập tức (khác S3 im lặng).
Advanced concepts
- Multiple dispatch thật sự (dispatch dựa trên nhiều argument) - S3 không làm được điều này.
Ngày 22: S4 validity & generics
Khái niệm
setValidity(),isVirtualClass(), abstract class trong S4.
Thực hành và quan sát
- Package
Matrixdùng S4 rộng rãi - đọc sourceshowMethods("show")để thấy dispatch table.
- Package
Advanced concepts
- S4 trong Bioconductor ecosystem - vì sao lĩnh vực genomics chọn S4 thay vì S3.
Ngày 23: R5 / Reference Classes (R5)
Khái niệm
- Reference semantics (mutable) khác hẳn S3/S4 (copy-on-modify).
setRefClass().
- Reference semantics (mutable) khác hẳn S3/S4 (copy-on-modify).
Thực hành và quan sát
- Tạo object R5, gán cho biến thứ 2, sửa field, quan sát cả 2 biến cùng thay đổi (aliasing).
Advanced concepts
- So sánh với environment thuần làm mutable object (R5 build trên environment).
Ngày 24: R6
Khái niệm
- R6 = reference class hiện đại, cú pháp gọn hơn R5, encapsulation với private/public.
Thực hành và quan sát
- Viết class R6 có
privatefield +activebinding (getter/setter).
- Viết class R6 có
Advanced concepts
- R6 dùng trong Shiny module,
plumber, và nhiều package production - vì sao mutable object hữu ích ở đây (tránh copy state lớn).
- R6 dùng trong Shiny module,
Ngày 25: So sánh & chọn hệ OOP
Khái niệm
- Bảng quyết định: khi nào S3 (đơn giản, hầu hết use case) / S4 (formal, validation, multiple dispatch) / R6 (mutable, stateful service như DB connection, cache).
Thực hành và quan sát
- Refactor lại project Ngày 18 bằng cả 3 hệ, ghi nhận trade-off thực tế.
Advanced concepts
- Đọc
vctrs- dùng S3 nhưng với kỷ luật design pattern rất chặt (record type, prototype).
- Đọc
Ngày 26: Non-standard evaluation - quote/eval/substitute
Khái niệm
- NSE: code có thể được capture như dữ liệu (expression) trước khi evaluate - nền tảng của công thức
y ~ x, vàsubset().
- NSE: code có thể được capture như dữ liệu (expression) trước khi evaluate - nền tảng của công thức
Thực hành và quan sát
quote(x + y),eval(quote(x+y), list(x=1,y=2)),substitute()trong function body.
Advanced concepts
bquote()cho quasiquotation thủ công (tiền thân của!!trong rlang).
Ngày 27: rlang & quosures
Khái niệm
- Quosure = expression + environment nó thuộc về - giải quyết vấn đề NSE không biết biến free thuộc scope nào.
Thực hành và quan sát
enquo()trong hàm tự viết,quo_get_expr(),quo_get_env().
Advanced concepts
- Vì sao
dplyr::filter()cần quosure để hoạt động đúng khi biến trong cả data frame lẫn global env trùng tên.
- Vì sao
Ngày 28: !!, !!!, tidyselect
Khái niệm
- Quasiquotation:
!!unquote 1 giá trị,!!!unquote-splice 1 list/vector nhiều giá trị vào....
- Quasiquotation:
Thực hành và quan sát
- Viết hàm wrapper quanh
dplyr::select()nhận vector tên cột động, dùng!!!.
- Viết hàm wrapper quanh
Advanced concepts
tidyselect::eval_select()- cơ chế đằng saustarts_with(),everything().
Ngày 29: Curly-curly {{ }}
Khái niệm
{{ }}= đường tắt củaenquo()+!!, dùng để viết hàm tidyverse-style nhận data-variable làm argument.
Thực hành và quan sát
- Viết hàm
my_summary(df, group_var, value_var)dùng{{ group_var }}tronggroup_by().
- Viết hàm
Advanced concepts
across()kết hợp với tidyselect để áp dụng hàm lên nhiều cột động.
Ngày 30: vctrs fundamentals
Khái niệm
vctrschuẩn hoá coercion (vec_ptype2), recycling (vec_size2) cho toàn bộ tidyverse hiện đại.
Thực hành và quan sát
- Tạo 1 vector class mới (ví dụ
percent) kế thừavctrs::new_vctr(), định nghĩa format method.
- Tạo 1 vector class mới (ví dụ
Advanced concepts
- Đọc source
vctrsđể hiểu vì saodplyr::bind_rows()không bao giờ silent-coerce sai kiểu nhưrbind()base R.
- Đọc source
PHASE 4 - Data Wrangling
Ngày 31: dplyr core verbs
Khái niệm
filter/select/mutate/arrange/summarise/group_by- lazy vs eager evaluation trong pipeline.
Thực hành và quan sát
- Viết pipeline
|>xử lý dataset thật (vdnycflights13), quan sátgroup_by()ảnh hưởng đếnmutate()khácsummarise()thế nào.
- Viết pipeline
Advanced concepts
dplyr::rowwise()và performance cost so với vectorizedmutate().
Ngày 32: dplyr joins & advanced grouping
Khái niệm
inner/left/right/full/semi/anti_join- semantic khác nhau, đặc biệt semi/anti cho filtering-by-relation.
Thực hành và quan sát
- Benchmark join trên dataset 1M dòng, quan sát cảnh báo "many-to-many relationship".
Advanced concepts
dplyr::group_map(),group_split()cho custom logic theo từng nhóm.
Ngày 33: tidyr reshaping
Khái niệm
pivot_longer/pivot_widerthay thếgather/spread- mental model "một quan sát một dòng".
Thực hành và quan sát
- Reshape dữ liệu wide (nhiều cột năm) sang long, rồi ngược lại, kiểm tra tính idempotent.
Advanced concepts
nest()/unnest()cho list-column workflow (mô hình hoá theo nhóm).
Ngày 34: stringr & regex
Khái niệm
stringrwrapstringi(ICU-based), khác base R regex engine (POSIX/PCRE).
Thực hành và quan sát
- Viết regex xử lý dữ liệu text bẩn thực tế (số điện thoại, email) bằng
str_extract,str_detect.
- Viết regex xử lý dữ liệu text bẩn thực tế (số điện thoại, email) bằng
Advanced concepts
- Lookahead/lookbehind trong PCRE mode (
perl=TRUEhoặcstringrmặc định dùng ICU).
- Lookahead/lookbehind trong PCRE mode (
Ngày 35: lubridate
Khái niệm
- Xử lý datetime, timezone,
POSIXctvsPOSIXltvsDate.
- Xử lý datetime, timezone,
Thực hành và quan sát
- Xử lý dữ liệu chuỗi thời gian đa timezone, DST transition - bẫy kinh điển khi cộng ngày qua ranh giới DST.
Advanced concepts
interval(),duration(),period()- khác biệt về semantic (period tôn trọng lịch, duration tính giây tuyệt đối).
Ngày 36: data.table cú pháp cơ bản
Khái niệm
DT[i, j, by]- "subset, select/compute, group by" trong 1 cú pháp thống nhất.
Thực hành và quan sát
- Convert 1 pipeline dplyr Ngày 31 sang data.table tương đương, so sánh độ dài code.
Advanced concepts
.SD,.SDcolscho thao tác trên tập con cột động.
Ngày 37: data.table joins & advanced ops
Khái niệm
- Join qua
DT[i]với key,merge.data.table(), rolling join (roll=TRUE).
- Join qua
Thực hành và quan sát
- Thực hiện rolling join cho time-series (vd: khớp giá gần nhất trước mỗi timestamp).
Advanced concepts
- Non-equi join (
DT1[DT2, on = .(a >= b)]).
- Non-equi join (
Ngày 38: readr/vroom & import dữ liệu lớn
Khái niệm
vroomdùng lazy reading + ALTREP (liên kết Phase 9) để đọc file lớn cực nhanh.
Thực hành và quan sát
- So sánh thời gian đọc file CSV 1GB:
read.csvvsreadr::read_csvvsdata.table::freadvsvroom.
- So sánh thời gian đọc file CSV 1GB:
Advanced concepts
- Column type guessing mechanism - vì sao đôi khi cần chỉ định
col_typestường minh trong production.
- Column type guessing mechanism - vì sao đôi khi cần chỉ định
Ngày 39: Benchmark dplyr vs data.table
Khái niệm
- Trade-off: dplyr (readability, ecosystem) vs data.table (raw speed, memory efficiency trên big data).
Thực hành và quan sát
- Benchmark group-by-aggregate trên 10M, 50M dòng - dùng
bench::mark(), vẽ biểu đồ scaling.
- Benchmark group-by-aggregate trên 10M, 50M dòng - dùng
Advanced concepts
dtplyr- dịch cú pháp dplyr sang data.table backend, dùng khi muốn cả 2 lợi thế.
Ngày 40: Capstone Data Wrangling
Thực hành và quan sát
- Lấy 1 dataset thật lộn xộn (vd Kaggle), làm full pipeline: import → clean → reshape → join → export, viết bằng cả dplyr và data.table để so sánh.
Advanced concepts
- Viết test cho pipeline bằng
testthat(chuẩn bị tư duy production sớm).
- Viết test cho pipeline bằng
PHASE 5 - Statistical Foundations
Ngày 41: Xác suất cơ bản
Khái niệm
- Random variable, PMF/PDF, CDF; các phân phối phổ biến: Bernoulli, Binomial, Poisson, Normal, Exponential.
Thực hành và quan sát
- Vẽ và mô phỏng từng phân phối bằng
rbinom/rnorm/rpois+ggplot2, so khớp lý thuyết vs mô phỏng.
- Vẽ và mô phỏng từng phân phối bằng
Advanced concepts
- Moment generating function - dùng R symbolic (
Derivpackage) để verify công thức mean/variance.
- Moment generating function - dùng R symbolic (
Ngày 42: Xác suất có điều kiện & Bayes
Khái niệm
- P(A|B), định lý Bayes, base rate fallacy.
Thực hành và quan sát
- Code ví dụ kinh điển "xét nghiệm y tế dương tính giả" bằng R, minh hoạ base rate ảnh hưởng thế nào.
Advanced concepts
- Naive Bayes classifier viết from-scratch bằng base R (không dùng package).
Ngày 43: Joint distribution, Expectation, Variance, Covariance
Khái niệm
- E[X], Var(X), Cov(X,Y), correlation - công thức và ý nghĩa hình học.
Thực hành và quan sát
- Mô phỏng 2 biến correlated bằng
MASS::mvrnorm(), verify covariance matrix từ sample.
- Mô phỏng 2 biến correlated bằng
Advanced concepts
- Law of Total Variance / Law of Total Expectation minh hoạ bằng simulation.
Ngày 44: Sampling distribution & CLT
Khái niệm
- Central Limit Theorem - vì sao sample mean tiệm cận Normal bất kể phân phối gốc.
Thực hành và quan sát
- Simulation: lấy mẫu từ phân phối lệch (exponential), vẽ histogram của sample mean qua nhiều lần lặp, quan sát hội tụ về Normal.
Advanced concepts
- Standard error vs standard deviation - phân biệt rõ 2 khái niệm hay bị nhầm.
Ngày 45: Maximum Likelihood Estimation (MLE)
Khái niệm
- Likelihood function, log-likelihood, tối ưu hoá để tìm estimator.
Thực hành và quan sát
- Viết MLE cho phân phối Normal bằng
optim()từ đầu, so sánh vớimean()/sd()closed-form.
- Viết MLE cho phân phối Normal bằng
Advanced concepts
- Fisher Information & Cramér-Rao bound (chỉ cần hiểu khái niệm, không cần chứng minh chi tiết).
Ngày 46: MAP & nhập môn Bayesian
Khái niệm
- Maximum A Posteriori - MLE + prior. Posterior ∝ Likelihood × Prior.
Thực hành và quan sát
- Beta-Binomial conjugate model viết bằng tay, vẽ prior → posterior update khi có thêm dữ liệu.
Advanced concepts
- Giới thiệu
brms/rstancho Bayesian modeling thực chiến (chỉ demo, đào sâu sau nếu cần).
- Giới thiệu
Ngày 47: Confidence Interval
Khái niệm
- Ý nghĩa thực sự của CI (tần suất luận, không phải "95% xác suất giá trị thật nằm trong khoảng").
Thực hành và quan sát
- Simulation 1000 lần lấy mẫu, tính CI mỗi lần, đếm bao nhiêu % chứa true parameter - minh hoạ định nghĩa CI trực quan.
Advanced concepts
- Bootstrap CI (percentile, BCa) so với CI closed-form.
Ngày 48: Hypothesis Testing
Khái niệm
- Null/alternative hypothesis, p-value, Type I/II error,
t.test,chisq.test.
- Null/alternative hypothesis, p-value, Type I/II error,
Thực hành và quan sát
- Viết t-test từ đầu (tính statistic + so với phân phối t) rồi verify bằng
t.test().
- Viết t-test từ đầu (tính statistic + so với phân phối t) rồi verify bằng
Advanced concepts
- Vấn đề multiple testing - Bonferroni, FDR (
p.adjust()).
- Vấn đề multiple testing - Bonferroni, FDR (
Ngày 49: Power Analysis
Khái niệm
- Statistical power, effect size, mối quan hệ sample size ↔ power ↔ significance level.
Thực hành và quan sát
pwr::pwr.t.test()tính sample size cần thiết cho A/B test với effect size cho trước.
Advanced concepts
- Simulation-based power analysis khi công thức closed-form không tồn tại (thiết kế phức tạp).
Ngày 50: OLS derivation
Khái niệm
- Linear regression từ góc nhìn đại số tuyến tính: β = (XᵀX)⁻¹Xᵀy.
Thực hành và quan sát
- Implement OLS bằng phép nhân ma trận thuần (
solve(),%*%), so kết quả vớilm().
- Implement OLS bằng phép nhân ma trận thuần (
Advanced concepts
- QR decomposition - vì sao
lm()không dùng trực tiếp công thức nghịch đảo ma trận (numerical stability).
- QR decomposition - vì sao
Ngày 51: GLM theory
Khái niệm
- Link function, exponential family, logistic/poisson regression như trường hợp đặc biệt của GLM.
Thực hành và quan sát
- Fit
glm(family=binomial), tự tính log-odds → probability bằng tay, verify vớipredict(type="response").
- Fit
Advanced concepts
- Iteratively Reweighted Least Squares (IRLS) - cơ chế optimization đứng sau
glm().
- Iteratively Reweighted Least Squares (IRLS) - cơ chế optimization đứng sau
Ngày 52: Regularization - Ridge
Khái niệm
- Bias-variance tradeoff, L2 penalty, vì sao ridge giúp khi có multicollinearity.
Thực hành và quan sát
glmnet(alpha=0), vẽ coefficient path theo lambda.
Advanced concepts
- Ridge tương đương Bayesian regression với Gaussian prior trên coefficient - kết nối lại Ngày 46.
Ngày 53: Regularization - Lasso & Elastic Net
Khái niệm
- L1 penalty gây sparsity (feature selection tự động), Elastic Net kết hợp L1+L2.
Thực hành và quan sát
glmnet(alpha=1)+ cross-validationcv.glmnet()để chọn lambda tối ưu.
Advanced concepts
- Vì sao L1 tạo sparse solution về mặt hình học (constraint region là hình thoi, không phải hình tròn như L2).
Ngày 54: Bootstrap
Khái niệm
- Resampling with replacement để ước lượng sampling distribution mà không cần giả định phân phối.
Thực hành và quan sát
- Bootstrap CI cho median (không có công thức closed-form đẹp) - so sánh
bootpackage với code tự viết (link lại Ngày 17).
- Bootstrap CI cho median (không có công thức closed-form đẹp) - so sánh
Advanced concepts
- Block bootstrap cho dữ liệu time-series (không thể resample độc lập do autocorrelation).
Ngày 55: Cross-validation & model evaluation
Khái niệm
- k-fold CV, leave-one-out, train/validation/test split, các metric: RMSE, AUC, F1.
Thực hành và quan sát
- Implement k-fold CV thủ công bằng vòng lặp, sau đó dùng
rsample/tidymodelsđể so sánh.
- Implement k-fold CV thủ công bằng vòng lặp, sau đó dùng
Advanced concepts
- Data leakage - các lỗi kinh điển (chuẩn hoá dữ liệu trước khi split, time-series CV cần respect thứ tự thời gian).
PHASE 6 - Visualization Internals
Ngày 56: Grammar of Graphics & ggplot2 cơ bản
Khái niệm
- Layered grammar: data → aes mapping → geom → stat → scale → coord → facet → theme.
Thực hành và quan sát
- Xây 1 chart từ
ggplot()rỗng, thêm từng layer một, quan sát ảnh hưởng.
- Xây 1 chart từ
Advanced concepts
- Vì sao
aes()phân biệt "mapped" vs "set" (đặt trongaes()vs ngoài).
- Vì sao
Ngày 57: Scales, guides, coord systems
Khái niệm
- Scale transform (log, sqrt),
coord_flip,coord_polar,coord_fixed- khác biệt giữa transform data và transform coordinate.
- Scale transform (log, sqrt),
Thực hành và quan sát
- Vẽ cùng 1 data bằng
coord_cartesianvscoord_polar, quan sát statistic layer có thay đổi hay không.
- Vẽ cùng 1 data bằng
Advanced concepts
- Custom scale với
scales::trans_new().
- Custom scale với
Ngày 58: Facets, themes, stats/geoms
Khái niệm
facet_wrapvsfacet_grid; phân biệtgeom_*(hình dạng) vàstat_*(biến đổi thống kê) - mỗi geom có default stat và ngược lại.
Thực hành và quan sát
- Viết
geom_bar()bằnggeom_col() + stat_count()để hiểu chúng tương đương.
- Viết
Advanced concepts
- Viết custom theme hoàn chỉnh (
theme_minimal()modified) cho báo cáo công ty.
- Viết custom theme hoàn chỉnh (
Ngày 59: ggplot_build() - pipeline internals
Khái niệm
- Quá trình render:
ggplot_build()→ggplot_gtable()→ grid graphics.
- Quá trình render:
Thực hành và quan sát
- Gọi
ggplot_build(p)$datađể xem dữ liệu đã qua stat transform trước khi vẽ (vd histogram bins).
- Gọi
Advanced concepts
gridpackage nền tảng - ggplot2 thực chất build trêngrid, không phải base graphics.
Ngày 60: Đọc source code ggplot2
Khái niệm
- Cấu trúc package:
ggproto- hệ OOP riêng của ggplot2 (dựa trên R6-like prototype).
- Cấu trúc package:
Thực hành và quan sát
- Đọc source
Geom,Statbase ggproto object trên GitHub, tìm hiểucompute_group().
- Đọc source
Advanced concepts
- Viết 1
geom_*tùy chỉnh bằng cách extendggproto.
- Viết 1
Ngày 61: Interactive visualization
Khái niệm
htmlwidgetsframework - cách R "bridge" sang JavaScript (D3, Plotly.js, Leaflet).
Thực hành và quan sát
- Convert
ggplotsang interactive bằngplotly::ggplotly(), quan sát HTML/JSON sinh ra.
- Convert
Advanced concepts
- Viết 1 htmlwidget tối giản (wrap 1 thư viện JS nhỏ) để hiểu cơ chế binding R ↔ JS.
PHASE 7 - Database & Analytics Engineering
Ngày 62: SQL refresher
Khái niệm
- JOIN các loại, GROUP BY, window functions (
OVER), CTE.
- JOIN các loại, GROUP BY, window functions (
Thực hành và quan sát
- Viết lại toàn bộ pipeline dplyr Ngày 31-32 bằng SQL thuần trên SQLite local.
Advanced concepts
- Execution order thực sự của SQL query (FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY).
Ngày 63: DBI & kết nối database
Khái niệm
DBIlà interface chuẩn, driver cụ thể (RPostgres,RMariaDB,odbc) implement bên dưới.
Thực hành và quan sát
- Kết nối Postgres (Docker container local),
dbGetQuery(),dbWriteTable(), parameterized query chống SQL injection.
- Kết nối Postgres (Docker container local),
Advanced concepts
- Connection pooling với
poolpackage cho ứng dụng Shiny/Plumber production.
- Connection pooling với
Ngày 64: Query optimization
Khái niệm
- Index (B-tree), execution plan, partitioning bảng lớn.
Thực hành và quan sát
EXPLAIN ANALYZEtrên query chậm, thêm index, so sánh lại execution plan.
Advanced concepts
- Covering index, vì sao index không phải lúc nào cũng giúp (write-heavy workload).
Ngày 65: dbplyr internals
Khái niệm
- Lazy evaluation: dplyr verb trên tbl kết nối DB không chạy ngay, chỉ build SQL query cây.
Thực hành và quan sát
show_query()trên pipeline dplyr, so sánh SQL sinh ra với SQL viết tay Ngày 62.
Advanced concepts
- Đọc source
dbplyrđể hiểu cách nó dịchmutate()→SELECT ... AS, và giới hạn (không phải mọi hàm R dịch được sang SQL).
- Đọc source
Ngày 66: Apache Arrow - columnar format
Khái niệm
- Columnar vs row-based storage, zero-copy, memory-mapped file - vì sao Arrow nhanh cho analytics.
Thực hành và quan sát
- Đọc file lớn bằng
arrow::read_parquet()so vớiread.csv(), đo memory footprint bằnglobstr::obj_size().
- Đọc file lớn bằng
Advanced concepts
- Arrow IPC format và cách chia sẻ dữ liệu zero-copy giữa R và Python trong cùng tiến trình.
Ngày 67: Parquet & Feather
Khái niệm
- Parquet (columnar, nén tốt, có schema + statistics per column-chunk) vs Feather (tối ưu tốc độ I/O, ít nén hơn).
Thực hành và quan sát
- Benchmark write/read: CSV vs Parquet vs Feather trên cùng dataset, so kích thước file và tốc độ.
Advanced concepts
- Predicate pushdown - Parquet cho phép skip row-group không match filter mà không cần đọc hết file.
Ngày 68: Arrow Dataset API
Khái niệm
- Xử lý dataset lớn hơn RAM bằng partition + lazy scan, không load hết vào memory.
Thực hành và quan sát
- Tạo Hive-partitioned dataset (
partition = "year"), query vớidplyrverb thông quaarrow, quan sát chỉ đọc partition liên quan.
- Tạo Hive-partitioned dataset (
Advanced concepts
- So sánh Arrow Dataset API với Spark RDD/DataFrame về mặt triết lý lazy execution.
Ngày 69: Arrow + DuckDB
Khái niệm
- DuckDB - OLAP embedded database, tích hợp zero-copy với Arrow.
Thực hành và quan sát
duckdb+dbplyrquery trực tiếp lên file Parquet không cần load vào R memory, benchmark so với data.table trên cùng tác vụ aggregate.
Advanced concepts
- DuckDB vectorized execution engine - vì sao nó nhanh hơn SQLite/Postgres cho OLAP dù cùng chạy local.
PHASE 8 - data.table Deep Dive
Ngày 70: Reference semantics :=
Khái niệm
:=modify-in-place, không copy toàn bộ object - khác hẳn triết lý copy-on-modify của base R/dplyr.
Thực hành và quan sát
tracemem()trước/sauDT[, col := val]so vớidf$col <- val, chứng minh data.table không tạo bản copy mới.
Advanced concepts
- Cạm bẫy: truyền data.table vào hàm rồi modify bằng
:=bên trong - ảnh hưởng object gốc bên ngoài (side-effect cần cẩn trọng trong production).
- Cạm bẫy: truyền data.table vào hàm rồi modify bằng
Ngày 71: Keys & binary search
Khái niệm
setkey()sắp xếp vật lý dữ liệu theo cột key, cho phép binary search O(log n) thay vì vector scan O(n).
Thực hành và quan sát
- Benchmark filter có key vs không key trên dataset lớn.
Advanced concepts
- Multi-column key và composite binary search.
Ngày 72: Secondary indexes
Khái niệm
setindex()- tạo index phụ không sắp xếp lại dữ liệu vật lý (khác key), cho phép nhiều "chiều" truy vấn nhanh.
Thực hành và quan sát
- So sánh
setkey(1 key) với nhiềusetindex()cho các cột filter khác nhau.
- So sánh
Advanced concepts
options(datatable.auto.index=TRUE)- cơ chế auto-index ngầm khi filter lặp lại.
Ngày 73: Group aggregation engine (GForce)
Khái niệm
- data.table có "GForce" - optimized C-level path cho các hàm aggregate phổ biến (
sum,mean,min,max) khi dùng trongby.
- data.table có "GForce" - optimized C-level path cho các hàm aggregate phổ biến (
Thực hành và quan sát
- Benchmark
DT[, sum(x), by=g](GForce-eligible) vsDT[, .(custom_fn(x)), by=g](fallback path chậm hơn).
- Benchmark
Advanced concepts
verbose=TRUEoption để xem data.table log nó có dùng GForce hay không.
Ngày 74: fread internals
Khái niệm
fread()dùng memory-mapped file + multi-threaded parsing, tự động detect separator/type.
Thực hành và quan sát
- Benchmark
freadvớinThreadkhác nhau, quan sát scaling.
- Benchmark
Advanced concepts
fread(cmd=...)để pipe qua shell command (vd giải nén trước khi đọc) - pattern hữu ích cho production ETL.
Ngày 75: Đọc source code data.table
Khái niệm
- Package viết chủ yếu bằng C, phần R chỉ là wrapper mỏng gọi
.Call().
- Package viết chủ yếu bằng C, phần R chỉ là wrapper mỏng gọi
Thực hành và quan sát
- Đọc
src/forder.c(thuật toán sort) hoặcsrc/froll.c(rolling functions) trên GitHub - không cần hiểu 100% C, chỉ cần nắm ý tưởng thuật toán chính.
- Đọc
Advanced concepts
- So sánh triết lý thiết kế data.table (tối ưu tối đa cho tốc độ, ít phụ thuộc) với dplyr (tối ưu cho tính nhất quán API, nhiều dependency).
PHASE 9 - R Internals
Ngày 76: R object model - SEXP/SEXPREC
Khái niệm
- Mọi object trong R (kể cả function) là
SEXP(S-expression pointer) trỏ tớiSEXPRECstruct trong C - chứa header (type, attributes, gc info) + payload.
- Mọi object trong R (kể cả function) là
Thực hành và quan sát
.Internal(inspect(x))để xem raw representation của object (type, refcount, memory address).
Advanced concepts
- 25 SEXPTYPE khác nhau (
NILSXP,SYMSXP,LISTSXP,CLOSXP...) - đọc bảng đầy đủ trong R Internals manual.
- 25 SEXPTYPE khác nhau (
Ngày 77: NAMED bits & copy-on-modify
Khái niệm
- Cơ chế cũ: NAMED (0/1/2) đánh dấu object có bị reference bởi nhiều biến hay không, quyết định có cần copy khi modify.
Thực hành và quan sát
.Internal(inspect(x))xem NAMED value thay đổi thế nào qua các phép gány <- x.
Advanced concepts
- R 3.5+ chuyển sang reference counting chính xác hơn (REFCNT) thay vì NAMED 0/1/2 đơn giản.
Ngày 78: tracemem() thực hành
Khái niệm
tracemem()in ra thông báo mỗi khi object bị copy trong bộ nhớ.
Thực hành và quan sát
- Trace 1 pipeline dplyr dài, đếm số lần copy xảy ra; so sánh với data.table
:=(0 copy).
- Trace 1 pipeline dplyr dài, đếm số lần copy xảy ra; so sánh với data.table
Advanced concepts
untracemem(), và giới hạn: tracemem không bắt được copy xảy ra bên trong C code không qua R-level assignment.
Ngày 79: ALTREP
Khái niệm
- ALTREP (R 3.5+): "vector giả" - không lưu dữ liệu thật ngay mà lazy/compact representation (vd
1:1e9không tốn 4GB RAM).
- ALTREP (R 3.5+): "vector giả" - không lưu dữ liệu thật ngay mà lazy/compact representation (vd
Thực hành và quan sát
.Internal(inspect(1:100))thấyALTREPflag; so sánh memory size1:1e9vsc(1:1e9)(force materialize) bằnglobstr::obj_size().
Advanced concepts
vroom/data.tabledùng ALTREP để map thẳng dữ liệu từ disk mà không copy vào RAM ngay (liên kết Ngày 38, 74).
Ngày 80: Environments internals
Khái niệm
- Environment = hash table (frame) + con trỏ tới parent environment (enclosure).
search()trả về chuỗi environment attach.
- Environment = hash table (frame) + con trỏ tới parent environment (enclosure).
Thực hành và quan sát
environmentName(),globalenv(),baseenv(),emptyenv()- vẽ sơ đồ search path thực tế sau khilibrary()vài package.
Advanced concepts
- Namespace environment vs package environment - vì sao
:::truy cập được hàm không export nhưnglibrary()user không thấy chúng quals().
- Namespace environment vs package environment - vì sao
Ngày 81: Lexical vs dynamic scoping
Khái niệm
- R dùng lexical scoping (function tìm biến free trong environment nơi nó được ĐỊNH NGHĨA, không phải nơi gọi).
Thực hành và quan sát
sys.call(),sys.function(),parent.frame()- viết hàm debug in ra call stack.
Advanced concepts
- Dynamic scoping giả lập bằng
parent.frame()- pattern nguy hiểm nhưng đôi khi cần (vd trong NSE của base Rsubset()).
- Dynamic scoping giả lập bằng
Ngày 82: Promises & lazy eval
Khái niệm
- Quay lại Ngày 12: promise thực chất là 1 SEXPTYPE riêng (
PROMSXP) chứa 3 phần: expression, environment, value (cache sau khi force).
- Quay lại Ngày 12: promise thực chất là 1 SEXPTYPE riêng (
Thực hành và quan sát
pryr::promise_info()hoặc thủ công dùngsubstitute()để "nhìn" vào promise trước khi nó bị force.
Advanced concepts
- Memoization tự nhiên của promise - 1 argument chỉ evaluate 1 lần dù được reference nhiều lần trong body.
Ngày 83: Garbage Collector
Khái niệm
- Generational GC (2 generations: young/old) - object mới tạo được scan thường xuyên hơn object sống lâu.
Thực hành và quan sát
gc(verbose=TRUE)đọc output: Ncells, Vcells, used, gc trigger.
Advanced concepts
- Mark-and-sweep algorithm cơ bản - vì sao circular reference trong R vẫn được GC đúng cách (không như reference counting thuần).
Ngày 84: GC tuning
Khái niệm
- Khi nào GC ảnh hưởng performance (nhiều object nhỏ tạo/hủy liên tục trong loop).
Thực hành và quan sát
gcinfo(TRUE), so sánh thời gian chạy có/không preallocate vector trong loop lớn.
Advanced concepts
Rgc()timing profiling - xác định % thời gian chương trình dành cho GC bằngprofvis(link Phase 10).
Ngày 85: Bytecode compiler
Khái niệm
- R có JIT compiler (từ R 2.13, mặc định bật từ R 3.4) biên dịch function sang bytecode chạy trên virtual machine nội bộ, không phải machine code thật.
Thực hành và quan sát
compiler::cmpfun(), so sánhdisassemble()output của hàm trước/sau compile.
Advanced concepts
options(jit.level)các mức độ JIT khác nhau - vì sao JIT giúp loop nhưng không giúp nhiều cho vectorized code (đã nhanh sẵn nhờ C).
Ngày 86: Condition system (tryCatch, restarts)
Khái niệm
- Hệ thống condition của R lấy cảm hứng từ Common Lisp - không chỉ có error/warning mà có
conditionobject tùy chỉnh và cơ chếrestart(khôi phục, không chỉ bắt lỗi).
- Hệ thống condition của R lấy cảm hứng từ Common Lisp - không chỉ có error/warning mà có
Thực hành và quan sát
- Viết custom condition class bằng
structure(class = c("my_error","error","condition")), bắt bằngtryCatch()theo class cụ thể.
- Viết custom condition class bằng
Advanced concepts
withCallingHandlers()+invokeRestart()- pattern nâng cao cho phép "sửa lỗi và tiếp tục chạy" thay vì unwind hoàn toàn stack (điềutryCatchkhông làm được).
Ngày 87: R Language Definition + Capstone Internals
Khái niệm
- Tổng hợp toàn bộ Phase 9, đọc "R Language Definition" manual chính thức để lấp khoảng trống.
Thực hành và quan sát
- Viết 1 bài note tổng hợp cá nhân: "Vòng đời 1 R expression từ parse → evaluate → GC", vẽ sơ đồ.
Advanced concepts
- So sánh kiến trúc R interpreter với CPython (cả hai đều tree-walking interpreter có bytecode layer) để có góc nhìn đối chiếu.
PHASE 10 - Performance Engineering
Ngày 88: Profiling với Rprof/profvis
Khái niệm
- Sampling profiler -
Rprof()lấy mẫu call stack theo interval, không phải instrument từng dòng.
- Sampling profiler -
Thực hành và quan sát
profvis::profvis({...})trên pipeline chậm, đọc flame graph, xác định bottleneck thật (thường bất ngờ, không phải chỗ ta nghĩ).
Advanced concepts
- Giới hạn sampling profiler: hàm chạy quá nhanh có thể "lọt" khỏi mẫu - cần lặp lại đủ số lần.
Ngày 89: Benchmarking chuẩn với bench::mark()
Khái niệm
bench::mark()đo cả thời gian lẫn memory allocation, kiểm tra kết quả các phương án có bằng nhau không (tránh benchmark sai do so sánh táo với cam).
Thực hành và quan sát
- So sánh 3-4 cách viết cùng 1 tác vụ, đọc output
min/median/mem_alloc/n_gc.
- So sánh 3-4 cách viết cùng 1 tác vụ, đọc output
Advanced concepts
bench::press()để benchmark theo nhiều tổ hợp tham số (vd kích thước dữ liệu tăng dần) và vẽ scaling curve.
Ngày 90: Tối ưu vector hóa
Khái niệm
- Pattern tối ưu: preallocate, tránh
rbind/cbind/c()trong loop, dùng vectorized built-in trước khi nghĩ tớiapply.
- Pattern tối ưu: preallocate, tránh
Thực hành và quan sát
- Refactor 1 hàm chậm (từ project cũ) áp dụng từng pattern, benchmark từng bước cải thiện.
Advanced concepts
- Khi nào vector hóa KHÔNG giúp (thuật toán có dependency tuần tự thật sự, vd simulation Markov chain) - đây là lúc cần Rcpp (Phase 11).
Ngày 91: Memory profiling
Khái niệm
lobstr::obj_size(),mem_used()- theo dõi bộ nhớ thực tế object chiếm dụng, kể cả shared reference.
Thực hành và quan sát
- So sánh
obj_size()của list chứa nhiều bản copy dữ liệu giống nhau - quan sát R chia sẻ bộ nhớ (không double-count).
- So sánh
Advanced concepts
Rprofmem()- track từng lần allocation gắn với dòng code cụ thể.
Ngày 92: Parallel computing - base parallel
Khái niệm
- Fork (Unix, copy-on-write, nhanh khởi tạo) vs PSOCK cluster (đa nền tảng, cần serialize dữ liệu qua socket).
Thực hành và quan sát
mclapply()(Linux/Mac) vsparLapply()(Windows-compatible), benchmark overhead khởi tạo cluster.
Advanced concepts
- Vì sao fork không dùng được trong RStudio trên một số OS/context (an toàn thread của GUI).
Ngày 93: future/furrr ecosystem
Khái niệm
futureabstraction layer thống nhất (sequential, multisession, multicore, cluster, thậm chí cloud) đằng sau 1 API.
Thực hành và quan sát
- Đổi
plan(sequential)→plan(multisession)cho cùng 1 đoạn codefurrr::future_map(), không sửa logic.
- Đổi
Advanced concepts
future+progressrcho progress bar trong tác vụ song song - pattern cần thiết cho production long-running job.
Ngày 94: foreach + doParallel
Khái niệm
foreachvới%dopar%- API kiểu khác (gần for-loop hơn map), phổ biến trong codebase cũ/thống kê.
Thực hành và quan sát
- Viết cùng 1 tác vụ bằng
foreach %dopar%vàfurrr::future_map(), so sánh cú pháp + performance.
- Viết cùng 1 tác vụ bằng
Advanced concepts
.combineargument trongforeach- cách gộp kết quả song song (rbind, c, list tùy use case).
Ngày 95: Capstone Performance
Thực hành và quan sát
- Lấy 1 pipeline chậm thật (từ Phase 4 hoặc project cá nhân), áp dụng toàn bộ kỹ thuật Phase 10 theo thứ tự: profile → tối ưu thuật toán/vector hóa → parallel hóa nếu cần → benchmark trước/sau.
Advanced concepts
- Viết báo cáo performance (before/after, % cải thiện, trade-off complexity) như thể present cho team - kỹ năng thực chiến production.
PHASE 11 - C API & Rcpp
Ngày 96: Rcpp cơ bản
Khái niệm
- Rcpp cho phép viết C++ trực tiếp inline, tự động generate glue code kết nối R ↔ C++.
Thực hành và quan sát
Rcpp::cppFunction()viết hàm Fibonacci đệ quy, benchmark so với bản R thuần (chênh lệch rất lớn cho thấy giá trị của compiled code).
Advanced concepts
sourceCpp()với file.cppriêng +// [[Rcpp::export]]- workflow chuẩn cho package thật.
Ngày 97: Rcpp data structures
Khái niệm
NumericVector,IntegerVector,List,DataFrame- wrapper C++ ánh xạ trực tiếp tới SEXP tương ứng.
Thực hành và quan sát
- Viết hàm nhận
DataFrame, loop qua cột, trả vềNumericVectormới.
- Viết hàm nhận
Advanced concepts
- Zero-copy vs copy khi truyền dữ liệu qua lại R ↔ C++ - khi nào Rcpp copy ngầm (cần biết để tránh overhead không đáng).
Ngày 98: Rcpp sugar
Khái niệm
- "Rcpp sugar" - cú pháp vectorized giống R ngay trong C++ (
v1 + v2,sum(),ifelse()) thay vì viết loop tay.
- "Rcpp sugar" - cú pháp vectorized giống R ngay trong C++ (
Thực hành và quan sát
- Viết cùng hàm 2 cách: loop thủ công vs sugar, benchmark (sugar đôi khi chậm hơn loop tối ưu tay - quan trọng để biết giới hạn).
Advanced concepts
- Khi nào nên "xuống" loop C++ thuần thay vì dùng sugar (hot path cực nóng).
Ngày 99: RcppArmadillo
Khái niệm
- Binding tới thư viện linear algebra Armadillo (C++) - cú pháp gần với R/Matlab, tối ưu cho phép toán ma trận.
Thực hành và quan sát
- Implement lại OLS (Ngày 50) bằng RcppArmadillo, benchmark với
lm()và bản R thuần.
- Implement lại OLS (Ngày 50) bằng RcppArmadillo, benchmark với
Advanced concepts
- Liên kết BLAS/LAPACK backend - Armadillo tự động dùng BLAS tối ưu nếu có sẵn trên hệ thống.
Ngày 100: Native R C API - .Call()
Khái niệm
- Trước khi có Rcpp, R expose C API thô: viết hàm C nhận/trả
SEXPtrực tiếp, compile bằngR CMD SHLIB.
- Trước khi có Rcpp, R expose C API thô: viết hàm C nhận/trả
Thực hành và quan sát
- Viết 1 hàm C tối giản (cộng 2 vector) dùng
.Call(), không qua Rcpp - hiểu Rcpp thực ra chỉ là lớp trừu tượng trên API này.
- Viết 1 hàm C tối giản (cộng 2 vector) dùng
Advanced concepts
R.h,Rinternals.h- các header cần include, cấu trúc hàmSEXP myFunc(SEXP a, SEXP b).
Ngày 101: PROTECT/UNPROTECT & memory safety
Khái niệm
- GC của R có thể chạy bất cứ lúc nào giữa các lệnh C - object tạo trong C code cần
PROTECT()để tránh bị GC thu hồi nhầm trước khi trả về R.
- GC của R có thể chạy bất cứ lúc nào giữa các lệnh C - object tạo trong C code cần
Thực hành và quan sát
- Viết hàm C cố tình thiếu
PROTECT(), thử trigger crash bằng cách ép GC chạy (gc()liên tục) - quan sát hành vi bất định (minh hoạ tại sao cần cẩn trọng).
- Viết hàm C cố tình thiếu
Advanced concepts
PROTECT_INDEX,REPROTECTcho trường hợp object thay đổi trong vòng lặp C.
Ngày 102: SEXP manipulation trong C
Khái niệm
- Truy cập trực tiếp macro như
REAL(),INTEGER(),STRING_ELT()để đọc/ghi dữ liệu thô trong SEXP.
- Truy cập trực tiếp macro như
Thực hành và quan sát
- Viết hàm C thao tác trực tiếp con trỏ
double*từREAL(x)- so sánh tốc độ với Rcpp wrapper tương đương.
- Viết hàm C thao tác trực tiếp con trỏ
Advanced concepts
- Rủi ro buffer overflow nếu tính sai độ dài - đây là lý do Rcpp tồn tại (an toàn hơn C API thô).
Ngày 103: ALTREP API - viết custom ALTREP class
Khái niệm
- Có thể tự định nghĩa 1 ALTREP class (vd vector đại diện cho 1 công thức toán học, không lưu trữ giá trị thật cho tới khi cần).
Thực hành và quan sát
- Theo tutorial chính thức của R-core viết 1 ALTREP vector đơn giản kiểu "compact sequence" tối giản.
Advanced concepts
- Đây là kỹ thuật hiếm dùng (chủ yếu R-core hoặc package cực kỳ chuyên sâu như
data.table/vroom) - mục tiêu là HIỂU cơ chế, không nhất thiết dùng thường xuyên.
- Đây là kỹ thuật hiếm dùng (chủ yếu R-core hoặc package cực kỳ chuyên sâu như
Ngày 104: Rcpp internals
Khái niệm
- Rcpp thực chất generate code C++ template wrap quanh
.Call()+ PROTECT/UNPROTECT tự động qua RAII (destructor tự unprotect).
- Rcpp thực chất generate code C++ template wrap quanh
Thực hành và quan sát
- Dùng
Rcpp:::Rcpp.package.skeleton()rồi mở file.cppsinh ra, đối chiếu với những gì học ở Ngày 100-102.
- Dùng
Advanced concepts
Rcpp::wrap()/Rcpp::as()- cơ chế template metaprogramming cho phép tự động convert type C++ ↔ R.
Ngày 105: Capstone C API
Thực hành và quan sát
- Chọn 1 hàm R chậm từ Phase 10 (vd 1 thuật toán có dependency tuần tự không vector hóa được), viết lại bằng Rcpp, benchmark cải thiện.
Advanced concepts
- Đóng gói hàm Rcpp đó thành 1 package mini hoàn chỉnh (chuẩn bị cho Phase 12).
PHASE 12 - Package Development
Ngày 106: Cấu trúc package, usethis/devtools
Khái niệm
- Package = code (
R/) + metadata (DESCRIPTION) + docs (man/) + tests (tests/) + optionally compiled code (src/).
- Package = code (
Thực hành và quan sát
usethis::create_package(),devtools::load_all()(kháclibrary()- load code trực tiếp từ source để dev nhanh).
Advanced concepts
devtools::check()chạy local trước khi push CI, tiết kiệm vòng lặp phản hồi.
Ngày 107: DESCRIPTION file
Khái niệm
Imports(bắt buộc, không attach namespace) vsDepends(attach vào search path, hạn chế dùng) vsSuggests(optional, cho vignette/test) vsLinkingTo(compiled dependency như Rcpp headers).
Thực hành và quan sát
- Thêm dependency vào package Ngày 105 (từ Rcpp capstone) đúng field, chạy
devtools::check()xem cảnh báo.
- Thêm dependency vào package Ngày 105 (từ Rcpp capstone) đúng field, chạy
Advanced concepts
- Version constraint syntax (
pkg (>= 1.2.0)) và semver philosophy trong R ecosystem.
- Version constraint syntax (
Ngày 108: NAMESPACE internals
Khái niệm
export(),S3method(),importFrom()- kiểm soát API bề mặt của package, tránh namespace pollution.
Thực hành và quan sát
- Cố tình gọi hàm không export bằng
:::, quan sát R CMD check cảnh báo (best practice không nên dùng:::production).
- Cố tình gọi hàm không export bằng
Advanced concepts
- Namespace conflict thực tế:
dplyr::filtervsstats::filter- cách R quyết định hàm nào "thắng" dựa trên thứ tựlibrary()load, và cáchconflictedpackage giải quyết triệt để.
- Namespace conflict thực tế:
Ngày 109: Package loading & search path
Khái niệm
library()(attach vào search path, error nếu fail) vsrequire()(return FALSE nếu fail, dùng trong logic) vsloadNamespace()(load nhưng không attach).
Thực hành và quan sát
search()trước/sau mỗi lệnh load, vẽ lại toàn bộ chain.
Advanced concepts
- Lazy-loading database (
.rdb/.rdxfile trong package đã install) - vì saolibrary()nhanh dù package lớn (không load hết code ngay, chỉ load khi cần).
- Lazy-loading database (
Ngày 110: roxygen2
Khái niệm
- Documentation-as-comment, generate
.Rdfile tự động từ#'tags.
- Documentation-as-comment, generate
Thực hành và quan sát
- Viết doc đầy đủ (
@param,@return,@examples,@export) cho hàm Rcpp capstone, chạydevtools::document().
- Viết doc đầy đủ (
Advanced concepts
@family,@seealso, roxygen cho S4/R6 (khác cú pháp so với function thường).
Ngày 111: testthat
Khái niệm
- Unit testing philosophy trong R: mỗi file test tương ứng 1 file R,
expect_equal,expect_error, snapshot testing.
- Unit testing philosophy trong R: mỗi file test tương ứng 1 file R,
Thực hành và quan sát
- Viết test coverage cho toàn bộ hàm trong package, chạy
devtools::test(), đo coverage bằngcovr::package_coverage().
- Viết test coverage cho toàn bộ hàm trong package, chạy
Advanced concepts
testthat::skip_on_cran(), test cho code có side-effect (file I/O, network) bằng mock (mockery/httptest).
Ngày 112: R CMD check & CRAN standards
Khái niệm
R CMD check- bộ kiểm tra toàn diện (syntax, doc consistency, examples chạy được, cross-platform).
Thực hành và quan sát
- Chạy check trên package, sửa từng NOTE/WARNING/ERROR cho tới khi sạch (0 note).
Advanced concepts
rhub/GitHub Actions matrix check trên nhiều OS (Windows/Mac/Linux) - vì sao code chạy được trên máy mình chưa chắc pass trên CRAN.
Ngày 113: Capstone Package
Thực hành và quan sát
- Hoàn thiện package đầy đủ: doc, test, README, NEWS.md, vignette (
usethis::use_vignette()), publish lên GitHub với CI (GitHub Actions chạyR CMD check).
- Hoàn thiện package đầy đủ: doc, test, README, NEWS.md, vignette (
Advanced concepts
- Semantic versioning cho R package +
NEWS.mdchangelog chuẩn - chuẩn bị tư duy maintain lâu dài.
- Semantic versioning cho R package +
PHASE 13 - Production Systems
Ngày 114: plumber - REST API cơ bản
Khái niệm
#* @get/@postannotation sinh route tự động, tương tự Flask/FastAPI nhưng cho R.
Thực hành và quan sát
- Expose 1 model (từ Phase 5) qua endpoint
/predict, test bằngcurl/Postman.
- Expose 1 model (từ Phase 5) qua endpoint
Advanced concepts
plumber::pr_hook()cho logging mỗi request (chuẩn bị Ngày 124).
Ngày 115: plumber nâng cao
Khái niệm
- Async request handling, input validation, API key authentication.
Thực hành và quan sát
- Thêm middleware kiểm tra header
Authorization, trả lỗi 401 nếu thiếu.
- Thêm middleware kiểm tra header
Advanced concepts
future+ plumber async - xử lý nhiều request đồng thời không block (liên kết Phase 10).
Ngày 116: Shiny reactive programming model
Khái niệm
- Reactive graph:
reactive(),observe(),observeEvent(),reactiveVal- dependency tracking tự động khác hẳn imperative programming.
- Reactive graph:
Thực hành và quan sát
- Vẽ sơ đồ reactive graph cho 1 app đơn giản, dùng
reactlogpackage để visualize graph thực tế lúc chạy.
- Vẽ sơ đồ reactive graph cho 1 app đơn giản, dùng
Advanced concepts
- Invalidation cascade - vì sao hiểu sai reactive graph gây ra recompute thừa (performance bug kinh điển của Shiny).
Ngày 117: Shiny modules & kiến trúc scalable
Khái niệm
- Module = namespace hóa UI + server logic, tránh ID collision, cho phép compose app lớn từ nhiều phần độc lập.
Thực hành và quan sát
- Refactor 1 app monolithic thành 3-4 module tái sử dụng được.
Advanced concepts
- R6 object kết hợp module Shiny cho state phức tạp (liên kết Ngày 24).
Ngày 118: Shiny performance - async
Khái niệm
- Shiny mặc định single-threaded per session - tác vụ nặng block toàn bộ UI của user đó.
Thực hành và quan sát
- Dùng
promises+futuređể chạy query DB nặng bất đồng bộ, giữ UI responsive.
- Dùng
Advanced concepts
ExtendedTask(Shiny mới) cho async pattern chuẩn hoá hơn.
Ngày 119: Docker cho R
Khái niệm
rockerproject - base image chuẩn cho R (r-ver, r-base, tidyverse, shiny variants).
Thực hành và quan sát
- Viết Dockerfile multi-stage: stage build (compile package + Rcpp) → stage runtime (chỉ copy binary, giảm image size).
Advanced concepts
- Cache layer Docker cho
renv::restore()- tối ưu tốc độ rebuild khi chỉ code thay đổi, không phải dependency.
- Cache layer Docker cho
Ngày 120: Kubernetes deployment
Khái niệm
- Pod, Deployment, Service, Ingress - deploy plumber API/Shiny app như 1 containerized service có thể scale.
Thực hành và quan sát
- Viết
deployment.yaml+service.yamltối giản, deploy lên local cluster (minikube/kind).
- Viết
Advanced concepts
- HorizontalPodAutoscaler dựa trên CPU/memory - auto-scale khi traffic tăng.
Ngày 121: Reverse proxy
Khái niệm
- Nginx/Traefik đứng trước plumber/Shiny để xử lý TLS termination, load balancing, routing nhiều app qua 1 domain.
Thực hành và quan sát
- Cấu hình Nginx route
/api→ plumber container,/app→ Shiny container.
- Cấu hình Nginx route
Advanced concepts
- Sticky session cho Shiny (cần thiết vì Shiny giữ state theo session, không stateless như REST API thuần).
Ngày 122: Caching
Khái niệm
memoise(cache kết quả hàm trong process) vs Redis (cache ngoài process, chia sẻ giữa nhiều instance).
Thực hành và quan sát
- Thêm
memoise::memoise()quanh 1 hàm query DB chậm, benchmark cache hit vs miss.
- Thêm
Advanced concepts
- Redis +
plumbercho cache dùng chung khi có nhiều pod (memoise local không chia sẻ được giữa các container).
- Redis +
Ngày 123: Monitoring
Khái niệm
- Prometheus (scrape metrics theo interval) + Grafana (visualize) - metrics kiểu counter/gauge/histogram.
Thực hành và quan sát
- Expose endpoint
/metricstừ plumber bằng cách track request count/latency thủ công, cấu hình Prometheus scrape.
- Expose endpoint
Advanced concepts
- Alert rule trong Prometheus (vd cảnh báo khi latency p99 vượt ngưỡng).
Ngày 124: Logging & message queue
Khái niệm
- Structured logging (JSON log thay vì text tự do, dễ query trong hệ thống log tập trung như ELK); message queue (RabbitMQ/Kafka) cho xử lý bất đồng bộ giữa services.
Thực hành và quan sát
- Dùng
logger/futile.loggerpackage log dạng JSON có level (INFO/WARN/ERROR) + context field.
- Dùng
Advanced concepts
- R producer/consumer đơn giản với RabbitMQ (
AMQPclient) - mô phỏng pipeline ETL bất đồng bộ.
- R producer/consumer đơn giản với RabbitMQ (
Ngày 125: Batch orchestration
Khái niệm
- cron cho job đơn giản định kỳ; Airflow/Prefect cho DAG phức tạp có dependency giữa các task.
Thực hành và quan sát
- Viết 1 R script chạy qua
cron(local), sau đó thử orchestrate bằng Prefect gọiRscriptnhư 1 task trong DAG Python.
- Viết 1 R script chạy qua
Advanced concepts
- Idempotency trong batch job - thiết kế job có thể chạy lại an toàn nếu fail giữa chừng (quan trọng cho production ETL thật).
PHASE 14 - Reading Source Code
Ngày 126: R interpreter - eval.c
Khái niệm
eval()C-level - trái tim của interpreter, xử lý từng SEXPTYPE khác nhau (LANGSXP gọi hàm, SYMSXP tra cứu biến...).
Thực hành và quan sát
- Clone R source (
svn/GitHub mirror), đọc hàmRf_eval()trongsrc/main/eval.c, chỉ cần theo dõi switch-case chính, không cần hiểu 100%.
- Clone R source (
Advanced concepts
- So sánh với phần bytecode interpreter (
bcEval()) trong cùng file - 2 con đường thực thi song song (interpreted vs compiled).
- So sánh với phần bytecode interpreter (
Ngày 127: memory.c
Khái niệm
- Cấp phát SEXP, GC implementation thực tế (liên kết lại Ngày 83).
Thực hành và quan sát
- Tìm hàm
R_gc_internal(), đọc comment giải thích generational collection.
- Tìm hàm
Advanced concepts
R_NewEnv, cách environment thực sự được cấp phát như 1 dạng đặc biệt của SEXP.
Ngày 128: envir.c
Khái niệm
- Cài đặt hash table cho environment, cơ chế lookup biến (liên kết Ngày 80-81).
Thực hành và quan sát
- Đọc
findVar(),defineVar()- so với mental model đã học, xác nhận lại hiểu biết.
- Đọc
Advanced concepts
- Active bindings (
makeActiveBinding()) implementation - nền tảng cho R6 active fields.
- Active bindings (
Ngày 129: bytecode.c
Khái niệm
- Cấu trúc bytecode object, danh sách opcode (liên kết Ngày 85).
Thực hành và quan sát
- Đọc danh sách opcode trong
src/main/names.c(bảng ánh xạ), đối chiếu vớidisassemble()output đã làm ở Ngày 85.
- Đọc danh sách opcode trong
Advanced concepts
- So sánh kiến trúc bytecode VM của R với 1 VM đơn giản khác (vd Python's CPython bytecode) - điểm giống/khác.
Ngày 130: Đọc source dplyr
Khái niệm
- Kiến trúc dplyr hiện đại dựa trên
vctrs+rlang, mỗi verb là generic S3 dispatch theo backend (data.frame, dtplyr, dbplyr, arrow).
- Kiến trúc dplyr hiện đại dựa trên
Thực hành và quan sát
- Đọc source
filter.R, theo dõi cách nó dùngmask(data mask) để evaluate expression trong context của data.
- Đọc source
Advanced concepts
- So sánh thiết kế "1 verb, nhiều backend" của dplyr với triết lý "1 package, tối ưu 1 backend duy nhất" của data.table.
Ngày 131: Đọc source data.table (C level) - nâng cao
Khái niệm
- Ôn lại + đào sâu Ngày 75 - tập trung vào
forder.c(radix sort implementation).
- Ôn lại + đào sâu Ngày 75 - tập trung vào
Thực hành và quan sát
- Đọc comment giải thích radix sort - thuật toán sort O(n) trong trường hợp tốt thay vì O(n log n) của comparison sort.
Advanced concepts
- So sánh radix sort với
sort()base R (dùng shell sort/quicksort tuỳ input size) - lý giải vì sao data.table sort nhanh hơn nhiều lần.
- So sánh radix sort với
Ngày 132: Đọc source ggplot2 - nâng cao
Khái niệm
- Ôn lại Ngày 60, đào sâu
ggprotoimplementation thực tế trongggproto.R.
- Ôn lại Ngày 60, đào sâu
Thực hành và quan sát
- Đọc cách
Geom$new()/$draw_panel()được resolve qua environment-based inheritance (không phải S4/R6 chuẩn, mà tự chế bằng environment).
- Đọc cách
Advanced concepts
- Vì sao ggplot2 không dùng R6/S4 có sẵn mà tự viết
ggprotoriêng - trade-off performance vs dependency.
- Vì sao ggplot2 không dùng R6/S4 có sẵn mà tự viết
Ngày 133: Tổng hợp - so sánh design decisions
Khái niệm
- Tổng kết triết lý thiết kế của 3 package lớn: dplyr (đa backend, ưu tiên UX), data.table (single backend, ưu tiên tốc độ tối đa), ggplot2 (grammar trừu tượng, ưu tiên tính mở rộng).
Thực hành và quan sát
- Viết bài blog/note cá nhân tổng hợp 3 triết lý, kèm code minh hoạ mỗi package giải quyết cùng 1 vấn đề khác nhau thế nào.
Advanced concepts
- Đây chính là tư duy "system design" áp dụng cho R package - kỹ năng chuyển giao được sang review code người khác hoặc tự thiết kế package mới.
PHASE 15 - Open Source Contribution
Ngày 134: Tìm hiểu quy trình contribute
Khái niệm
- Good-first-issue label, CONTRIBUTING.md, code of conduct - quy trình chuẩn của hầu hết R package lớn trên GitHub.
Thực hành và quan sát
- Chọn 1 package quen thuộc (dplyr/data.table/tidyr...), đọc CONTRIBUTING.md, tìm 3-5 issue "good first issue".
Advanced concepts
- Đọc git blame + PR history của 1 file để hiểu lịch sử quyết định thiết kế (rất nhiều insight nằm ở review comment cũ).
Ngày 135: PR đầu tiên - bug fix
Khái niệm
- Reproduce bug, viết regression test, fix minimal, viết changelog entry.
Thực hành và quan sát
- Fork repo, tạo branch, fix 1 bug nhỏ đã tìm ở Ngày 134, viết test, mở PR.
Advanced concepts
- Đọc kỹ CI pipeline của repo đó (GitHub Actions) để hiểu tại sao PR pass/fail trước khi maintainer review.
Ngày 136: PR - feature nhỏ hoặc docs
Khái niệm
- Đóng góp không chỉ code - cải thiện documentation, example, vignette cũng rất giá trị và dễ được merge hơn cho người mới.
Thực hành và quan sát
- Chọn 1 hàm thiếu example rõ ràng, viết
@exampleschất lượng, mở PR riêng.
- Chọn 1 hàm thiếu example rõ ràng, viết
Advanced concepts
- Học cách nhận feedback từ maintainer senior - đây là kỹ năng "đọc code review" quan trọng không kém viết code.
Ngày 137: Ongoing - cộng đồng
Khái niệm
- R-devel mailing list (nơi R-core thảo luận thay đổi ngôn ngữ), R Consortium (tài trợ dự án open-source), RStudio/Posit community blog.
Thực hành và quan sát
- Subscribe R-devel, đọc thread gần nhất về 1 thay đổi ngôn ngữ sắp tới - quan sát cách R-core tranh luận trade-off (rất giáo dục).
Advanced concepts
- Đây là điểm bắt đầu của hành trình dài hạn, không có "ngày kết thúc" - duy trì nhịp độ đọc/contribute đều đặn (vd 1 PR/tháng) là mục tiêu thực tế nhất.