Tuyen Tran, MD
Lập trình & Phân tích

Lộ trình tự học R cho bác sĩ: từ 0 đến chạy phân tích cho paper trong 8 tuần

8 tuần, 30 phút mỗi ngày. Lộ trình mình dùng dạy 1 bác sĩ trẻ Vinmec đi từ con số 0 đến chạy logistic regression cho một nghiên cứu đoàn hệ thật.

Bài này là lộ trình 8 tuần mình đã dùng dạy một bác sĩ trẻ ở Vinmec đi từ chưa bao giờ mở RStudio đến chạy logistic regression cho một nghiên cứu đoàn hệ thật (Nhi Đồng 2). Cô làm song song trực gác, mỗi ngày 30 phút. Sau 8 tuần, paper Methods chạy hoàn toàn bằng R, table và figure publication-ready paste thẳng vào Word.

Lộ trình này không phải Tidyverse 400-page textbook. Không phải data science from scratch. Đây là lộ trình tối thiểu để 1 bác sĩ lâm sàng dùng R cho paper đầu tay trong 2 tháng.

Trước khi bắt đầu: 3 câu hỏi

Đầu tư 30 giờ chỉ có ROI nếu bạn thực sự cần R. Trả lời thật:

  1. Bạn có 1 dataset thật trong tay (paper đang viết, IRB đã pass) trong 8 tuần tới không?
  2. Bạn publish trên 2 paper/năm không?
  3. Có một trong các yếu tố: cohort prospective, MA, multi-center, reviewer chê figure?

Trả lời No cho cả 3 câu, đừng bắt đầu. Đọc trước bài so sánh khi nào SPSS đủ và khi nào nên đổi sang R để xác nhận.

Trả lời Yes ít nhất 1 câu, đặc biệt câu 1, vào lộ trình.

Tuần 1: Setup + import dữ liệu thật

Mục tiêu: Cài R + RStudio, load data của bạn vào R, xem được số dòng cột.

Cài đặt (1 buổi 30 phút):

  • Tải R từ cran.r-project.org
  • Tải RStudio Desktop free từ posit.co
  • Cài hai cái theo thứ tự (R trước, RStudio sau)
  • Mở RStudio, làm quen 4 panel: Source, Console, Environment, Files

Import dataset thật (4 buổi 30 phút):

Lấy data paper đang viết hoặc 1 paper đã publish của bạn. Mở Excel, đổi header tiếng Việt sang không dấu (Tuoi, Gioi, Outcome), unmerge cell, save. Đây là bước prep 5 phút tiết kiệm 1 giờ debug.

data <- read.csv("arm_cohort.csv")
head(data)
str(data)
nrow(data)
ncol(data)

5 lệnh trên đủ cho tuần 1. Hết tuần 1, bạn biết: load CSV, xem 6 dòng đầu, xem kiểu dữ liệu mỗi cột, đếm dòng cột.

Sai lầm phổ biến tuần 1: học theo dataset mtcars hoặc iris. Không nên. R chỉ stick lại nếu bạn dùng cho project thật ngay từ tuần 1. Đã viết kỹ trong bài về 3 thao tác R đầu tiên.

Tuần 2: Descriptive (Bảng 1)

Mục tiêu: Gen Bảng 1 (descriptive theo nhóm) cho paper.

Lệnh cốt lõi:

summary(data)
table(data$gender)
prop.table(table(data$gender)) * 100
mean(data$age, na.rm = TRUE)
median(data$age, na.rm = TRUE)
quantile(data$age, na.rm = TRUE)

Bảng 1 publication-ready:

library(gtsummary)
data %>%
  tbl_summary(by = outcome,
              statistic = list(all_continuous() ~ "{median} ({p25}, {p75})",
                               all_categorical() ~ "{n} ({p}%)")) %>%
  add_p()

Đoạn gtsummary này là "bí kíp" tuần 2. Mình dùng đúng đoạn cho paper chẩn đoán bằng siêu âm của mình (đã đăng JPS 2026). Reviewer #1 không hỏi gì về format Bảng 1.

Output tuần 2: 1 file Rmd (hoặc R script) gen được Bảng 1 từ data thật của bạn. Paste vào Word, sửa đôi chỗ, dùng được luôn cho draft Methods.

Tuần 3: So sánh hai nhóm

Mục tiêu: t-test, Mann-Whitney, chi-square cho paper.

Quy trình quyết định:

  1. Continuous outcome → check phân bố
  2. Phân bố normal → t-test
  3. Phân bố non-normal → Mann-Whitney
  4. Categorical outcome → chi-square hoặc Fisher exact
shapiro.test(data$age[data$outcome == "yes"])
shapiro.test(data$age[data$outcome == "no"])

t.test(age ~ outcome, data = data)
wilcox.test(age ~ outcome, data = data)

chisq.test(data$sex, data$outcome)
fisher.test(data$sex, data$outcome)

Bài tập tuần 3: Chạy 4 test khác nhau trên data của bạn, record p-value, viết 1 đoạn Methods 5 dòng giải thích lý do chọn test nào.

Tuần 4: So sánh nhiều nhóm + correlation

Mục tiêu: ANOVA, Kruskal-Wallis, correlation.

aov_result <- aov(age ~ stage, data = data)
summary(aov_result)
TukeyHSD(aov_result)

kruskal.test(age ~ stage, data = data)

cor.test(data$age, data$crp, method = "spearman")

Bài tập tuần 4: Tự xác định 1 câu hỏi nghiên cứu trong dataset có 3 nhóm trở lên (ví dụ: stage I/II/III). Chạy ANOVA hoặc Kruskal-Wallis. Viết kết quả 2 dòng cho Results.

Tuần 5: Linear regression

Mục tiêu: Fit linear model, đọc output, viết Results.

model <- lm(crp ~ age + sex + bmi, data = data)
summary(model)
confint(model)

library(gtsummary)
tbl_regression(model)

Hiểu output: Estimate (β), Std. Error, t-value, p-value, R-squared. Tuần này là tuần đầu bạn đụng "regression" thực sự. Đừng vội. Dành 4-5 buổi đọc output từng dòng, cho đến khi hiểu mỗi số nghĩa là gì.

Sai lầm phổ biến: chạy regression với 10 covariate khi sample size < 50. Quy tắc 1:10 (events per variable) áp dụng. Nếu bạn có 30 outcome event, max 3 covariate trong model.

Tuần 6: Logistic regression + survival

Mục tiêu: Logistic cho binary outcome, Kaplan-Meier + Cox cho time-to-event.

Logistic:

model <- glm(outcome ~ age + sex + stage + comorbidity,
             data = data, family = binomial)
summary(model)
exp(coef(model))
exp(confint(model))

tbl_regression(model, exponentiate = TRUE)

Survival:

library(survival)
library(survminer)

fit <- survfit(Surv(time, event) ~ stage, data = data)
ggsurvplot(fit, pval = TRUE, risk.table = TRUE)

cox_model <- coxph(Surv(time, event) ~ age + sex + stage, data = data)
summary(cox_model)
tbl_regression(cox_model, exponentiate = TRUE)

Bài tập tuần 6: Gen Bảng 3 cho paper (univariate + multivariate logistic regression). Đây là bảng phức tạp nhất trong paper retrospective phổ biến. Sau tuần 6, bạn đủ kỹ năng cho 80% paper lâm sàng Q1.

Tuần 7: Plot publication-ready với ggplot

Mục tiêu: 5 loại figure thường gặp trong paper.

Histogram:

ggplot(data, aes(x = age)) +
  geom_histogram(bins = 20, fill = "steelblue") +
  theme_classic() +
  labs(x = "Age (years)", y = "Count")

Boxplot theo nhóm:

ggplot(data, aes(x = outcome, y = age, fill = outcome)) +
  geom_boxplot() +
  theme_classic() +
  labs(x = "Outcome", y = "Age (years)")

Scatter với regression line:

ggplot(data, aes(x = age, y = crp)) +
  geom_point() +
  geom_smooth(method = "lm") +
  theme_classic()

Forest plot (cho regression OR):

library(forestplot)
# hoặc dùng tbl_regression %>% plot()

KM curve: đã có ở tuần 6.

Bài tập tuần 7: Replicate Figure 1 và Figure 2 của 1 paper Q1 bạn đã đọc. Dùng data của bạn, không phải data paper đó. Đây là cách học ggplot hiệu quả nhất.

Tuần 8: Rmarkdown + workflow reproducible

Mục tiêu: Đóng gói toàn bộ analysis vào 1 file Rmd gen tự động Methods + Results.

---
title: "Analysis ARM cohort"
output: word_document
---

```{r setup, include=FALSE}
library(tidyverse)
library(gtsummary)
data <- read.csv("arm_cohort.csv")

Methods

Median age was r median(data$age) years ...


**Lợi ích Rmd**: mỗi khi data update, bạn click "Knit" 1 lần, toàn bộ Methods và Results section tự update với số mới. Không phải copy paste lại.

Paper chẩn đoán bằng siêu âm của mình có 3 lần PI thêm ca trong quá trình review. Mỗi lần re-knit chiếm 5 phút. Nếu là SPSS cộng Word manual, mỗi lần là 2-3 giờ.

**Bài tập cuối**: Đóng gói toàn bộ analysis paper của bạn vào 1 file Rmd. Knit ra Word doc. So sánh với draft Methods/Results hiện tại của bạn. Đó là output hoàn chỉnh của 8 tuần.

## Sau 8 tuần: tiếp theo gì

8 tuần này đủ cho paper retrospective hoặc case-control phổ biến. Nếu bạn tiếp tục:

- **Meta-analysis**: học `metafor` (1-2 tuần)
- **Multilevel/mixed model**: học `lme4` (2-3 tuần)
- **Power calculation**: học `pwr` (3-4 buổi)
- **Reproducible workflow chia với cộng tác viên**: GitHub + RStudio Projects (1 tuần)

Đừng học hết một lần. Chỉ học khi paper tiếp theo cần.

## Sai lầm phổ biến trong 8 tuần

**Tuần 1-2**: học bằng dataset tutorial (mtcars, iris). Không stick. Phải dùng data thật.

**Tuần 3-4**: skip statistics theory. Học hàm R mà không hiểu test giả định gì. Kết quả: chạy t-test trên data non-normal, reviewer chê.

**Tuần 5-6**: chạy regression với 10 covariate trên 50 case. Overfit, model unstable. Quy tắc 1:10 phải áp dụng.

**Tuần 7**: copy figure design từ tutorial generic. Không match style journal target. Đọc 3-5 paper trong target journal trước khi gen figure.

**Tuần 8**: skip Rmarkdown vì "phức tạp". Đó là tuần quan trọng nhất. Reproducible workflow là lý do chính học R thay vì SPSS.

Mình đã viết chi tiết hơn về [5 thao tác R thay thế SPSS bác sĩ thường làm hằng ngày](/blog/5-thao-tac-r-thay-the-spss). Đọc kèm trong tuần 2-6 để có context map giữa SPSS click và R lệnh.

## Trường hợp thực: 1 bác sĩ trẻ Vinmec

Bác sĩ trẻ mình hướng dẫn là một nội trú khoa Nhi, đã pass IRB cho 1 retrospective cohort 95 ca dị tật bẩm sinh. Trước khi học R, cô làm SPSS 2 năm, viết 1 bài đăng tạp chí Y học VN.

**Tuần 1-2**: Stuck ở Excel header tiếng Việt. Sửa header 30 phút, sau đó load data smooth. Bảng 1 bằng `gtsummary` chạy tuần 2, paste vào Word.

**Tuần 3-4**: Chạy 6 t-test, 4 chi-square cho paper. Gặp lỗi 1 lần khi data có missing value. Mình giải thích `na.rm = TRUE`, fix trong 5 phút.

**Tuần 5-6**: Đụng logistic regression. 4 biến covariate, 30 outcome event (tỷ lệ 30%). Áp dụng quy tắc 1:10, bỏ 1 biến không significant univariate. Mất 2 buổi đọc output.

**Tuần 7-8**: ggplot KM curve cho subgroup analysis. Replicate Figure 2 của 1 paper Q1 trong cùng lĩnh vực. Đóng gói Rmd. Knit ra Word doc 8 trang Methods cộng Results.

Tổng: 8 tuần × 30 phút = 28 giờ. Kết quả: 1 paper draft Methods/Results hoàn chỉnh, reproducible, ready submit. Cô tiếp tục dùng R cho cohort thứ hai 4 tháng sau.

## FAQ thường gặp

**"Nếu mình không có data thật thì sao?"** Đừng học. Đợi đến khi có IRB pass và data ready. R chỉ stick lại khi dùng cho project thật, không phải tutorial.

**"30 phút/ngày có thực sự đủ không?"** Đủ nếu là 30 phút focus. Không đủ nếu vừa học vừa lướt Facebook. Đặt timer, đóng tab khác.

**"Có cần học statistics theory trước không?"** Cần biết 5 khái niệm: mean/median, normal vs non-normal, p-value, OR/HR, CI. Không cần học tới ANOVA two-way hoặc mixed model. Đủ để chạy 80% paper retrospective.

**"R hay Python tốt hơn?"** Cho clinical research, R áp đảo. `gtsummary`, `metafor`, `survminer` là chuẩn academia. Python mạnh hơn cho ML hoặc imaging analysis, không phải descriptive cohort.

## Hỗ trợ cần thiết

1 bác sĩ tự học 8 tuần solo có ~50% rate hoàn thành. 1 bác sĩ học cùng 1 mentor hoặc khoá có lộ trình rõ có ~80% rate. Khác biệt là khi gặp lỗi tuần 3, có người chỉ trong 5 phút thay vì 2 giờ Google.

Đó là lý do mình design khoá R-stats theo đúng lộ trình 8 tuần này, kèm dataset lâm sàng VN thật, code template paste-được, và Q&A hằng tuần.

---

**Lộ trình 8 tuần này có khoá học đi kèm**: [R-stats trên tuyentranmd.com](https://tuyentranmd.com/courses/r-stats) đóng gói đúng 8 tuần này thành 30 phút mỗi ngày, kèm 5 dataset lâm sàng VN, code template, và Q&A hằng tuần. Thiết kế cho bác sĩ trực gác, không phải sinh viên data science.