Giao diện
↑ R2 · ← Environments & Scoping · → Joins & Grouped Ops
🎯 Mục tiêu
Tidyverse mạnh vì nó cho bạn “ngôn ngữ biến đổi dữ liệu”. Nhưng trong production, thứ bạn cần là: pipeline có contract rõ ràng và behavior ổn định qua thời gian. Bài này chốt mindset đó.
1) Tidyverse như một pipeline có hợp đồng
Một pipeline tốt luôn trả lời được 3 câu:
- Input contract: dữ liệu vào có schema gì (cột bắt buộc, kiểu dữ liệu, keys)?
- Transform contract: bước này làm gì, có thể thay đổi số dòng/số cột không?
- Output contract: dữ liệu ra có schema gì và ai là consumer?
Nếu bạn không viết được contract bằng lời, rất dễ “lỡ tay” đổi shape và làm downstream sai số liệu.
1.1 Invariants nên giữ (trừ khi bạn cố ý phá)
- Keys: khóa định danh của row (ví dụ
user_id,date) không được missing/duplicate nếu bạn tuyên bố đó là key. - Row count: nhiều bước nên giữ số dòng (mutate, rename, relocate). Các bước phá row count phải được ghi rõ (filter, summarise, distinct, join).
- Column semantics: cột “Date” phải còn class Date; cột “category” phải còn levels nếu bạn dùng factor; ...
✅ Checklist triển khai
Contract tối thiểu cho mỗi dataset
- Xác định key (hoặc nói rõ “không có key”)
- Danh sách cột bắt buộc
- Missingness policy (cột nào cho phép NA)
- Timezone/locale policy nếu có datetime
2) Verbs cốt lõi: đọc như một câu, không phải “ảo thuật”
Các verbs thường gặp:
select()/rename()/relocate()để quản lý schemafilter()để giảm rowsmutate()để thêm/đổi columnsarrange()để sắp xếp (đừng dựa vào thứ tự ngẫu nhiên)summarise()/reframe()để giảm hoặc tái cấu trúc rows theo grouppivot_longer()/pivot_wider()để reshape
Mindset: mỗi verb phải trả lời “tôi đang đổi schema hay đổi số dòng?”
3) Pipeline hygiene: code phải debug được
3.1 Đặt tên trung gian khi bước phức tạp
Chain 10 bước không sai, nhưng khi nó bắt đầu chứa logic điều kiện, join, grouped ops, bạn nên “đặt checkpoint”:
- để in ra số dòng,
- để kiểm tra missing keys,
- để unit test bước quan trọng.
Ví dụ (ý tưởng):
- Sau ingest: validate schema + types
- Sau join: validate row explosion không xảy ra
- Trước export: validate output contract
3.2 Không để warnings trôi qua
Trong pipeline, warnings thường là signal:
- parse fail → tạo NA mới
- recycling/coercion → kiểu dữ liệu bị đổi
Rule: warnings phải được giải thích (fix hoặc chấp nhận có lý do và đo lường).
4) Grouped ops: khái niệm và bẫy phổ biến
group_by() tạo trạng thái “grouped data frame”. Nhiều verbs sẽ thay đổi hành vi khi object đang grouped.
4.1 Grouped state là “hidden state”
Bạn có thể đang nghĩ mình làm trên toàn bộ dataset, nhưng thực ra đang làm theo từng group.
Ví dụ bẫy:
mutate()trên grouped df thường tạo feature “within group”slice_*()chọn top-n trong từng group
4.2 Khi grouped ops nguy hiểm
Grouped ops trở nên nguy hiểm khi:
- bạn quên
ungroup()và downstream bị apply theo group không mong muốn, - bạn join một dataset grouped và tạo ra behavior khó đoán,
- bạn
summarise()làm giảm rows nhưng downstream vẫn tưởng row-level.
Kỷ luật:
- Sau khi xong “block logic theo group”, kết thúc bằng
ungroup(). - Với
summarise(), luôn set.groupsđể behavior explicit.
Ví dụ (ý tưởng, không phụ thuộc version):
r
# summarise(..., .groups = "drop") # explicit: drop grouping
# summarise(..., .groups = "keep") # explicit: keep grouping4.3 summarise() vs reframe()
Mindset correctness:
summarise(): thường trả 1 row/group (hoặc vài row tùy expression) → dùng khi bạn thật sự “aggregate”.reframe(): dùng khi bạn muốn trả về nhiều rows/group một cách rõ ý (và chấp nhận row count thay đổi).
Nếu team bạn dùng dplyr version khác nhau, hãy thống nhất convention để tránh drift.
⚠️ Cạm bẫy
Grouped df như một “mode” của dataset. Nếu bạn không reset mode (ungroup), bạn đang để state ẩn chạy xuyên suốt pipeline.
5) Checklist: pipeline “đúng trước, nhanh sau”
✅ Checklist triển khai
Ship-ready transform
- Validate input schema trước khi transform
- Sau
group_by(): kết thúc block bằngungroup() - Sau
join: kiểm tra key uniqueness và row explosion - Trước export: validate output schema + missingness policy