Skip to main content

Command Palette

Search for a command to run...

Syllabus học R

Updated
49 min readView as Markdown

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

    • .Rprofile vs .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 .gitignore chuẩn cho R (.Rhistory, .RData, renv/library).

    • Viết .Rprofile project-level set option options(scipen=999, stringsAsFactors=FALSE), quan sát tác động.

  • Advanced concepts

    • Rscript --vanilla vs 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 1L vs 1 - 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 dim attribute. Column-major storage order (khác Python numpy row-major mặc định).
  • Thực hành và quan sát

    • Tạo matrix, kiểm tra attributes(), thử đổi dim() 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 Matrix package.

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.frame vs tibble (không auto-coerce string, in đẹp hơn, không partial matching $).
  • 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).
  • 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).

Ngày 8: NA/NULL/NaN/Inf & coercion

  • Khái niệm

    • NA là placeholder trong vector (có type: NA_integer_, NA_real_...), NULL là "không tồn tại" (độ dài 0), NaN là 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 == NULL trả 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), $[[ 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.

Ngày 10: Control flow & tư duy vector hóa

  • Khái niệm

    • for/while/repeat vs 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 vs Vectorize vs sum() trực tiếp - dùng bench::mark().
  • Advanced concepts

    • ifelse() vs dplyr::if_else() vs data.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 tra list(...), ..1, ..2, nargs().
  • 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 (lapply vs for với <- bind biến) - vì sao purrr/lapply an toàn hơn for-loop truyền thống ở điểm này.

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.
  • Thực hành và quan sát

    • Thay toàn bộ sapply bằng vapply trong 1 script cũ, quan sát lỗi type xuất hiện (đây là lý do dùng vapply trong production).
  • 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 |>.
  • Advanced concepts

    • Viết hàm compose(f, g) tự chế mô phỏng function composition.

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ới boot::boot().
  • Advanced concepts

    • Song song hóa bootstrap bằng furrr::future_map() (preview Phase 10).

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.
  • Thực hành và quan sát

    • Tạo class S3 thủ công, viết print.myclass(), summary.myclass().
  • Advanced concepts

    • UseMethod() cơ chế dispatch - dùng sloop::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.
  • Advanced concepts

    • Double dispatch trong S3 (Ops group generic) - ví dụ +.myclass.

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 Matrix dùng S4 rộng rãi - đọc source showMethods("show") để thấy dispatch table.
  • 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().
  • 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ó private field + active binding (getter/setter).
  • 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).

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).

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().
  • 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.

Ngày 28: !!, !!!, tidyselect

  • Khái niệm

    • Quasiquotation: !! unquote 1 giá trị, !!! unquote-splice 1 list/vector nhiều giá trị vào ....
  • 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 !!!.
  • Advanced concepts

    • tidyselect::eval_select() - cơ chế đằng sau starts_with(), everything().

Ngày 29: Curly-curly {{ }}

  • Khái niệm

    • {{ }} = đường tắt của enquo() + !!, 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 }} trong group_by().
  • 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

    • vctrs chuẩ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ừa vctrs::new_vctr(), định nghĩa format method.
  • Advanced concepts

    • Đọc source vctrs để hiểu vì sao dplyr::bind_rows() không bao giờ silent-coerce sai kiểu như rbind() base R.

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 (vd nycflights13), quan sát group_by() ảnh hưởng đến mutate() khác summarise() thế nào.
  • Advanced concepts

    • dplyr::rowwise() và performance cost so với vectorized mutate().

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_wider thay 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

    • stringr wrap stringi (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.
  • Advanced concepts

    • Lookahead/lookbehind trong PCRE mode (perl=TRUE hoặc stringr mặc định dùng ICU).

Ngày 35: lubridate

  • Khái niệm

    • Xử lý datetime, timezone, POSIXct vs POSIXlt vs Date.
  • 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, .SDcols cho 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).
  • 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)]).

Ngày 38: readr/vroom & import dữ liệu lớn

  • Khái niệm

    • vroom dù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.csv vs readr::read_csv vs data.table::fread vs vroom.
  • Advanced concepts

    • Column type guessing mechanism - vì sao đôi khi cần chỉ định col_types tường minh trong production.

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.
  • 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).

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.
  • Advanced concepts

    • Moment generating function - dùng R symbolic (Deriv package) để verify công thức mean/variance.

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.
  • 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ới mean()/sd() closed-form.
  • 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/rstan cho Bayesian modeling thực chiến (chỉ demo, đào sâu sau nếu cần).

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.
  • 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().
  • Advanced concepts

    • Vấn đề multiple testing - Bonferroni, FDR (p.adjust()).

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ới lm().
  • 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).

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ới predict(type="response").
  • Advanced concepts

    • Iteratively Reweighted Least Squares (IRLS) - cơ chế optimization đứng sau glm().

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-validation cv.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 boot package với code tự viết (link lại Ngày 17).
  • 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.
  • 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.
  • Advanced concepts

    • Vì sao aes() phân biệt "mapped" vs "set" (đặt trong aes() vs ngoài).

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.
  • Thực hành và quan sát

    • Vẽ cùng 1 data bằng coord_cartesian vs coord_polar, quan sát statistic layer có thay đổi hay không.
  • Advanced concepts

    • Custom scale với scales::trans_new().

Ngày 58: Facets, themes, stats/geoms

  • Khái niệm

    • facet_wrap vs facet_grid; phân biệt geom_* (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ằng geom_col() + stat_count() để hiểu chúng tương đương.
  • Advanced concepts

    • Viết custom theme hoàn chỉnh (theme_minimal() modified) cho báo cáo công ty.

Ngày 59: ggplot_build() - pipeline internals

  • Khái niệm

    • Quá trình render: ggplot_build()ggplot_gtable() → grid graphics.
  • 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).
  • Advanced concepts

    • grid package nền tảng - ggplot2 thực chất build trên grid, 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).
  • Thực hành và quan sát

    • Đọc source Geom, Stat base ggproto object trên GitHub, tìm hiểu compute_group().
  • Advanced concepts

    • Viết 1 geom_* tùy chỉnh bằng cách extend ggproto.

Ngày 61: Interactive visualization

  • Khái niệm

    • htmlwidgets framework - cách R "bridge" sang JavaScript (D3, Plotly.js, Leaflet).
  • Thực hành và quan sát

    • Convert ggplot sang interactive bằng plotly::ggplotly(), quan sát HTML/JSON sinh ra.
  • 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.
  • 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

    • DBI là 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.
  • Advanced concepts

    • Connection pooling với pool package cho ứng dụng Shiny/Plumber production.

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 ANALYZE trê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ịch mutate()SELECT ... AS, và giới hạn (không phải mọi hàm R dịch được sang SQL).

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ới read.csv(), đo memory footprint bằng lobstr::obj_size().
  • 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ới dplyr verb thông qua arrow, quan sát chỉ đọc partition liên quan.
  • 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 + dbplyr query 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/sau DT[, col := val] so với df$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).
  • 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ều setindex() cho các cột filter khác nhau.
  • 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 trong by.
  • Thực hành và quan sát

    • Benchmark DT[, sum(x), by=g] (GForce-eligible) vs DT[, .(custom_fn(x)), by=g] (fallback path chậm hơn).
  • Advanced concepts

    • verbose=TRUE option để 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 fread với nThread khác nhau, quan sát scaling.
  • 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().
  • Thực hành và quan sát

    • Đọc src/forder.c (thuật toán sort) hoặc src/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.
  • 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ới SEXPREC struct trong C - chứa header (type, attributes, gc info) + payload.
  • 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.

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án y <- 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).
  • 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:1e9 không tốn 4GB RAM).
  • Thực hành và quan sát

    • .Internal(inspect(1:100)) thấy ALTREP flag; so sánh memory size 1:1e9 vs c(1:1e9) (force materialize) bằng lobstr::obj_size().
  • Advanced concepts

    • vroom/data.table dù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.
  • Thực hành và quan sát

    • environmentName(), globalenv(), baseenv(), emptyenv() - vẽ sơ đồ search path thực tế sau khi library() vài package.
  • Advanced concepts

    • Namespace environment vs package environment - vì sao ::: truy cập được hàm không export nhưng library() user không thấy chúng qua ls().

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 R subset()).

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).
  • Thực hành và quan sát

    • pryr::promise_info() hoặc thủ công dùng substitute() để "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ằng profvis (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ánh disassemble() 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ó condition object tùy chỉnh và cơ chế restart (khôi phục, không chỉ bắt lỗi).
  • 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ằng tryCatch() theo class cụ thể.
  • 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ều tryCatch khô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.
  • 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.
  • 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ới apply.
  • 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).
  • 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) vs parLapply() (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

    • future abstraction 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 code furrr::future_map(), không sửa logic.
  • Advanced concepts

    • future + progressr cho 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

    • foreach vớ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%furrr::future_map(), so sánh cú pháp + performance.
  • Advanced concepts

    • .combine argument trong foreach - 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 .cpp riê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ề NumericVector mới.
  • 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.
  • 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.
  • 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ả SEXP trực tiếp, compile bằng R CMD SHLIB.
  • 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.
  • Advanced concepts

    • R.h, Rinternals.h - các header cần include, cấu trúc hàm SEXP 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.
  • 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).
  • Advanced concepts

    • PROTECT_INDEX, REPROTECT cho 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.
  • 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.
  • 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.

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).
  • Thực hành và quan sát

    • Dùng Rcpp:::Rcpp.package.skeleton() rồi mở file .cpp sinh ra, đối chiếu với những gì học ở Ngày 100-102.
  • 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/).
  • Thực hành và quan sát

    • usethis::create_package(), devtools::load_all() (khác library() - 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) vs Depends (attach vào search path, hạn chế dùng) vs Suggests (optional, cho vignette/test) vs LinkingTo (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.
  • Advanced concepts

    • Version constraint syntax (pkg (>= 1.2.0)) và semver philosophy trong R ecosystem.

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).
  • Advanced concepts

    • Namespace conflict thực tế: dplyr::filter vs stats::filter - cách R quyết định hàm nào "thắng" dựa trên thứ tự library() load, và cách conflicted package giải quyết triệt để.

Ngày 109: Package loading & search path

  • Khái niệm

    • library() (attach vào search path, error nếu fail) vs require() (return FALSE nếu fail, dùng trong logic) vs loadNamespace() (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/.rdx file trong package đã install) - vì sao library() nhanh dù package lớn (không load hết code ngay, chỉ load khi cần).

Ngày 110: roxygen2

  • Khái niệm

    • Documentation-as-comment, generate .Rd file tự động từ #' tags.
  • Thực hành và quan sát

    • Viết doc đầy đủ (@param, @return, @examples, @export) cho hàm Rcpp capstone, chạy devtools::document().
  • 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.
  • 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ằng covr::package_coverage().
  • 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ạy R CMD check).
  • Advanced concepts

    • Semantic versioning cho R package + NEWS.md changelog chuẩn - chuẩn bị tư duy maintain lâu dài.

PHASE 13 - Production Systems

Ngày 114: plumber - REST API cơ bản

  • Khái niệm

    • #* @get/@post annotation 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ằng curl/Postman.
  • 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.
  • 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.
  • Thực hành và quan sát

    • Vẽ sơ đồ reactive graph cho 1 app đơn giản, dùng reactlog package để visualize graph thực tế lúc chạy.
  • 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.
  • Advanced concepts

    • ExtendedTask (Shiny mới) cho async pattern chuẩn hoá hơn.

Ngày 119: Docker cho R

  • Khái niệm

    • rocker project - 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.

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.yaml tối giản, deploy lên local cluster (minikube/kind).
  • 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.
  • 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.
  • Advanced concepts

    • Redis + plumber cho cache dùng chung khi có nhiều pod (memoise local không chia sẻ được giữa các container).

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 /metrics từ plumber bằng cách track request count/latency thủ công, cấu hình Prometheus scrape.
  • 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.logger package log dạng JSON có level (INFO/WARN/ERROR) + context field.
  • Advanced concepts

    • R producer/consumer đơn giản với RabbitMQ (AMQP client) - mô phỏng pipeline ETL bất đồng bộ.

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ọi Rscript như 1 task trong DAG Python.
  • 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àm Rf_eval() trong src/main/eval.c, chỉ cần theo dõi switch-case chính, không cần hiểu 100%.
  • 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).

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.
  • 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.
  • Advanced concepts

    • Active bindings (makeActiveBinding()) implementation - nền tảng cho R6 active fields.

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ới disassemble() output đã làm ở Ngày 85.
  • 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).
  • Thực hành và quan sát

    • Đọc source filter.R, theo dõi cách nó dùng mask (data mask) để evaluate expression trong context của data.
  • 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).
  • 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.

Ngày 132: Đọc source ggplot2 - nâng cao

  • Khái niệm

    • Ôn lại Ngày 60, đào sâu ggproto implementation thực tế trong ggproto.R.
  • 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).
  • Advanced concepts

    • Vì sao ggplot2 không dùng R6/S4 có sẵn mà tự viết ggproto riêng - trade-off performance vs dependency.

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 @examples chất lượng, mở PR riêng.
  • 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.

Knowledge

Part 1 of 50