@iremaydas
Cung cấp hướng dẫn lập trình R cơ sở bao gồm các cấu trúc dữ liệu, sắp xếp dữ liệu, mô hình thống kê, trực quan hóa và I/O, chỉ sử dụng các gói có trong bản cài đặt R tiêu chuẩn
---
Tên: base-r
mô tả: Cung cấp hướng dẫn lập trình R cơ sở bao gồm các cấu trúc dữ liệu, sắp xếp dữ liệu, mô hình thống kê, trực quan hóa và I/O, chỉ sử dụng các gói có trong bản cài đặt R tiêu chuẩn
---
# Kỹ năng lập trình cơ bản R
Tài liệu tham khảo toàn diện về lập trình cơ sở R - bao gồm cấu trúc dữ liệu, luồng điều khiển, chức năng, I/O, tính toán thống kê và vẽ đồ thị.
## Tham khảo nhanh
### Cấu trúc dữ liệu
```r
# Vectors (atomic)
x <- c(1, 2, 3) # numeric
y <- c("a", "b", "c") # character
z <- c(TRUE, FALSE, TRUE) # logical
# Factor
f <- factor(c("low", "med", "high"), levels = c("low", "med", "high"), ordered = TRUE)
# Matrix
m <- matrix(1:6, nrow = 2, ncol = 3)
m[1, ] # first row
m[, 2] # second column
# List
lst <- list(name = "ali", scores = c(90, 85), passed = TRUE)
lst$name # access by name
lst[[2]] # access by position
# Data frame
df <- data.frame(
id = 1:3,
name = c("a", "b", "c"),
value = c(10.5, 20.3, 30.1),
stringsAsFactors = FALSE
)
df[df$value > 15, ] # filter rows
df$new_col <- df$value * 2 # add column
```
### Đặt lại
```r
# Vectors
x[1:3] # by position
x[c(TRUE, FALSE)] # by logical
x[x > 5] # by condition
x[-1] # exclude first
# Data frames
df[1:5, ] # first 5 rows
df[, c("name", "value")] # select columns
df[df$value > 10, "name"] # filter + select
subset(df, value > 10, select = c(name, value))
# which() for index positions
idx <- which(df$value == max(df$value))
```
### Luồng điều khiển
```r
# if/else
if (x > 0) {
"positive"
} else if (x == 0) {
"zero"
} else {
"negative"
}
# ifelse (vectorized)
ifelse(x > 0, "pos", "neg")
# for loop
for (i in seq_along(x)) {
cat(i, x[i], "\n")
}
# while
while (condition) {
# body
if (stop_cond) break
}
# switch
switch(type,
"a" = do_a(),
"b" = do_b(),
stop("Unknown type")
)
```
### Chức năng
```r
# Define
my_func <- function(x, y = 1, ...) {
result <- x + y
return(result) # or just: result
}
# Anonymous functions
sapply(1:5, function(x) x^2)
# R 4.1+ shorthand:
sapply(1:5, \(x) x^2)
# Useful: do.call for calling with a list of args
do.call(paste, list("a", "b", sep = "-"))
```
###Ứng tuyển Gia đình
```r
# sapply — simplify result to vector/matrix
sapply(lst, length)
# lapply — always returns list
lapply(lst, function(x) x[1])
# vapply — like sapply but with type safety
vapply(lst, length, integer(1))
# apply — over matrix margins (1=rows, 2=cols)
apply(m, 2, sum)
# tapply — apply by groups
tapply(df$value, df$group, mean)
# mapply — multivariate
mapply(function(x, y) x + y, 1:3, 4:6)
# aggregate — like tapply for data frames
aggregate(value ~ group, data = df, FUN = mean)
```
### Thao tác với chuỗi
```r
paste("a", "b", sep = "-") # "a-b"
paste0("x", 1:3) # "x1" "x2" "x3"
sprintf("%.2f%%", 3.14159) # "3.14%"
nchar("hello") # 5
substr("hello", 1, 3) # "hel"
gsub("old", "new", text) # replace all
grep("pattern", x) # indices of matches
grepl("pattern", x) # logical vector
strsplit("a,b,c", ",") # list("a","b","c")
trimws(" hi ") # "hi"
tolower("ABC") # "abc"
```
### Dữ liệu vào/ra
```r
# CSV
df <- read.csv("data.csv", stringsAsFactors = FALSE)
write.csv(df, "output.csv", row.names = FALSE)
# Tab-delimited
df <- read.delim("data.tsv")
# General
df <- read.table("data.txt", header = TRUE, sep = "\t")
# RDS (single R object, preserves types)
saveRDS(obj, "data.rds")
obj <- readRDS("data.rds")
# RData (multiple objects)
save(df1, df2, file = "data.RData")
load("data.RData")
# Connections
con <- file("big.csv", "r")
chunk <- readLines(con, n = 100)
close(con)
```
### Vẽ sơ đồ cơ sở
```r
# Scatter
plot(x, y, main = "Title", xlab = "X", ylab = "Y",
pch = 19, col = "steelblue", cex = 1.2)
# Line
plot(x, y, type = "l", lwd = 2, col = "red")
lines(x, y2, col = "blue", lty = 2) # add line
# Bar
barplot(table(df$category), main = "Counts",
col = "lightblue", las = 2)
# Histogram
hist(x, breaks = 30, col = "grey80",
main = "Distribution", xlab = "Value")
# Box plot
boxplot(value ~ group, data = df,
col = "lightyellow", main = "By Group")
# Multiple plots
par(mfrow = c(2, 2)) # 2x2 grid
# ... four plots ...
par(mfrow = c(1, 1)) # reset
# Save to file
png("plot.png", width = 800, height = 600)
plot(x, y)
dev.off()
# Add elements
legend("topright", legend = c("A", "B"),
col = c("red", "blue"), lty = 1)
abline(h = 0, lty = 2, col = "grey")
text(x, y, labels = names, pos = 3, cex = 0.8)
```
### Thống kê
```r
# Descriptive
mean(x); median(x); sd(x); var(x)
quantile(x, probs = c(0.25, 0.5, 0.75))
summary(df)
cor(x, y)
table(df$category) # frequency table
# Linear model
fit <- lm(y ~ x1 + x2, data = df)
summary(fit)
coef(fit)
predict(fit, newdata = new_df)
confint(fit)
# t-test
t.test(x, y) # two-sample
t.test(x, mu = 0) # one-sample
t.test(before, after, paired = TRUE)
# Chi-square
chisq.test(table(df$a, df$b))
# ANOVA
fit <- aov(value ~ group, data = df)
summary(fit)
TukeyHSD(fit)
# Correlation test
cor.test(x, y, method = "pearson")
```
### Thao tác dữ liệu
```r
# Merge (join)
merged <- merge(df1, df2, by = "id") # inner
merged <- merge(df1, df2, by = "id", all = TRUE) # full outer
merged <- merge(df1, df2, by = "id", all.x = TRUE) # left
# Reshape
wide <- reshape(long, direction = "wide",
idvar = "id", timevar = "time", v.names = "value")
long <- reshape(wide, direction = "long",
varying = list(c("v1", "v2")), v.names = "value")
# Sort
df[order(df$value), ] # ascending
df[order(-df$value), ] # descending
df[order(df$group, -df$value), ] # multi-column
# Remove duplicates
df[!duplicated(df), ]
df[!duplicated(df$id), ]
# Stack / combine
rbind(df1, df2) # stack rows (same columns)
cbind(df1, df2) # bind columns (same rows)
# Transform columns
df$log_val <- log(df$value)
df$category <- cut(df$value, breaks = c(0, 10, 20, Inf),
labels = c("low", "med", "high"))
```
### Môi trường & Gỡ lỗi
```r
ls() # list objects
rm(x) # remove object
rm(list = ls()) # clear all
str(obj) # structure
class(obj) # class
typeof(obj) # internal type
is.na(x) # check NA
complete.cases(df) # rows without NA
traceback() # after error
debug(my_func) # step through
browser() # breakpoint in code
system.time(expr) # timing
Sys.time() # current time
```
## Tệp tham khảo
Để biết thông tin chi tiết hơn, hãy đọc các tệp tham chiếu trong `references/`:
### Chức năng Gotchas & Tham khảo nhanh (được cô đọng từ Tài liệu tham khảo R 4.5.3)
Những hành vi không rõ ràng, những hành vi mặc định đáng ngạc nhiên và những tương tác phức tạp - chỉ những điều mà Claude chưa biết:
- **data-wrangling.md** — Đọc khi: tập hợp con trả về loại sai, áp dụng trên khung dữ liệu gây ra sự ép buộc không mong muốn, hợp nhất/tách/cbind hoạt động kỳ quặc, mức hệ số vẫn tồn tại sau khi lọc, bảng/các trường hợp cạnh trùng lặp.
- **modeling.md** — Đọc khi: cú pháp công thức khó hiểu (`I()`, `*` so với `:`, `/`), aov đưa ra loại SS sai, glm âm thầm phù hợp với OLS, nls sẽ không hội tụ, dự đoán trả về tỷ lệ sai, tối ưu hóa/tối ưu hóa nhu cầu điều chỉnh.
- **statistics.md** — Đọc khi: kiểm tra giả thuyết cho kết quả đáng ngạc nhiên, cần chọn phương pháp p.just đúng, các tham số phân cụm có vẻ sai, việc đặt tên hàm phân phối khó hiểu (tiền tố `d`/`p`/`q`/`r`).
- **visualization.md** — Đọc khi: cài đặt mệnh giá được đặt lại đột ngột, tương tác bố cục/mfrow khó hiểu, nhãn trục bị cắt bớt, màu sắc trông không ổn, cần các sơ đồ đặc biệt (đường viền, phối cảnh, khảm, cặp).
- **io-and-text.md** — Đọc khi: read.table âm thầm loại bỏ dữ liệu hoặc phân tích sai các cột, biểu thức chính quy hoạt động khác với mong đợi, định dạng sprintf phức tạp, đầu ra write.table có tên hàng không mong muốn.
- **dates-and-system.md** — Đọc khi: Chuyển đổi ngày/POSIXct sai ngày, múi giờ sai lệch một, đơn vị thời gian khác nhau không mong muốn, cần tìm/liệt kê/kiểm tra tệp theo chương trình.
- **misc-utilities.md** — Đọc khi: do.call hoạt động khác với cuộc gọi trực tiếp, cần Giảm/Lọc/Bản đồ, trình xử lý tryCatch không kích hoạt, chuỗi trả về all.equal không logic, các hàm chuỗi thời gian cần thiết lập.
## Mẹo viết mã R tốt
- Sử dụng `vapply()` trên `sapply()` trong mã sản xuất — nó thực thi các kiểu trả về
- Thích `seq_along(x)` hơn `1:length(x)` — cái sau bị hỏng khi `x` trống
- Sử dụng `stringsAsFactors = FALSE` trong `read.csv()`/`data.frame()` (mặc định đã thay đổi trong R 4.0)
- Vector hóa các thao tác thay vì viết vòng lặp khi có thể
- Sử dụng `stop()`, `warning()`, `message()` để xử lý lỗi — không phải `print()`
- `<<-` gán cho môi trường gốc — sử dụng một cách tiết kiệm và có chủ ý
- `with(df, expr)` tránh lặp lại `df$` ở mọi nơi
- `Sys.setenv()` và `.Renviron` cho các biến môi trường
TẬP TIN: tài liệu tham khảo/misc-utilities.md
# Tiện ích khác — Tham khảo nhanh
> Các hành vi không rõ ràng, lỗi sai và các giá trị mặc định phức tạp cho hàm R.
> Chỉ có điều Claude chưa biết thôi.
---
## do.call
- `do.call(fun, args_list)` — `args` phải là một **danh sách**, ngay cả đối với một đối số duy nhất.
- `quote = TRUE` ngăn việc đánh giá các đối số trước cuộc gọi — cần thiết khi truyền biểu thức/ký hiệu.
- Hoạt động của `substitute` bên trong `do.call` khác với cuộc gọi trực tiếp. Ngữ nghĩa không được xác định đầy đủ cho trường hợp này.
- Mẫu hữu ích: `do.call(rbind, list_of_dfs)` để kết hợp danh sách các khung dữ liệu.
---
## Giảm / Lọc / Bản đồ / Tìm / Định vị
Những người trợ giúp lập trình chức năng của R từ cơ sở - thực sự không rõ ràng.
- `Reduce(f, x)` áp dụng hàm nhị phân `f` tích lũy: `Reduce("+", 1:4)` = `((1+2)+3)+4`. Hướng quan trọng đối với các hoạt động không giao hoán.
- `Reduce(f, x, accumulate = TRUE)` trả về tất cả các kết quả trung gian — tương đương với `itertools.accumulate` của Python.
- `Reduce(f, x, right = TRUE)` gập từ bên phải: `f(x1, f(x2, f(x3, x4)))`.
- `Reduce` với `init` thêm giá trị bắt đầu: `Reduce(f, x, init = v)` = `f(f(f(v, x1), x2), x3)`.
- `Filter(f, x)` giữ các phần tử trong đó `f(elem)` là `TRUE`. Không giống như `x[sapply(x, f)]`, xử lý `NULL`/trống một cách chính xác.
- `Map(f, ...)` là trình bao bọc đơn giản cho `mapply(f, ..., SIMPLIFY = FALSE)` — luôn trả về một danh sách.
- `Find(f, x)` trả về phần tử **đầu tiên** trong đó `f(elem)` là `TRUE`. `Find(f, x, right = TRUE)` cuối cùng.
- `Position(f, x)` trả về **chỉ mục** của kết quả khớp đầu tiên (như `Find` nhưng trả về vị trí chứ không phải giá trị).
---
## độ dài
- `lengths(x)` trả về độ dài của **mỗi phần tử** của danh sách. Tương đương với `sapply(x, length)` nhưng nhanh hơn (được triển khai trong C).
- Hoạt động trên mọi đối tượng giống như danh sách. Trả về vectơ số nguyên.
---
## điều kiện (tryCatch / withCallingHandlers)
- `tryCatch` **giải phóng** ngăn xếp cuộc gọi — trình xử lý chạy trong môi trường gọi chứ không phải nơi xảy ra lỗi. Không thể tiếp tục thực hiện.
- `withCallingHandlers` KHÔNG giải phóng — trình xử lý chạy ở nơi điều kiện được báo hiệu. Có thể kiểm tra/đăng nhập rồi để điều kiện lan truyền.
- `tryCatch(expr, error = function(e) e)` trả về đối tượng tình trạng lỗi.
- `tryCatch(expr, warning = function(w) {...})` nhận được cảnh báo **đầu tiên** và thoát. Sử dụng `withCallingHandlers` + `invokeRestart("muffleWarning")` để chặn cảnh báo nhưng vẫn tiếp tục.
- Mệnh đề `tryCatch` `finally` luôn chạy (như Java try/finally).
- `globalCallingHandlers()` đăng ký các trình xử lý tồn tại trong phiên (hữu ích cho việc ghi nhật ký).
- Điều kiện tùy chỉnh: `stop(errorCondition("msg", class = "myError"))` sau đó bắt bằng `tryCatch(..., myError = function(e) ...)`.
---
## tất cả.bằng nhau
- Kiểm tra **gần bằng** với dung sai (mặc định `1.5e-8`, tức là `sqrt(.Machine$double.eps)`).
- Trả về `TRUE` hoặc một **chuỗi ký tự** mô tả sự khác biệt — KHÔNG phải `FALSE`. Sử dụng `isTRUE(all.equal(x, y))` trong điều kiện.
- Đối số `tolerance` kiểm soát dung sai số. `scale` để so sánh tuyệt đối và tương đối.
- Kiểm tra thuộc tính, tên, kích thước — kỹ lưỡng hơn `==`.
---
## chung
- `combn(n, m)` hoặc `combn(x, m)`: tạo tất cả các kết hợp `m` mục từ `x`.
- Trả về **ma trận** với các hàng `m`; mỗi cột là một sự kết hợp.
- Đối số `FUN` áp dụng một hàm cho mỗi kết hợp: `combn(5, 3, sum)` trả về tổng của tất cả các tập hợp con 3 phần tử.
- `simplify = FALSE` trả về danh sách thay vì ma trận.
---
## sửa đổi Danh sách
- `modifyList(x, val)` thay thế các thành phần của danh sách `x` bằng các thành phần trong `val` theo **name**.
- Đặt giá trị thành `NULL` **xóa** phần tử đó khỏi danh sách.
- **Có** thêm tên mới không có trong `x` — nó sử dụng `x[names(val)] <- val` nội bộ, do đó, bất kỳ tên nào trong `val` đều được thêm hoặc thay thế.
---
## liệt kê lại
- Nghịch đảo `unlist`: cho một vectơ phẳng và danh sách khung xương, xây dựng lại cấu trúc lồng nhau.
- `relist(flesh, skeleton)` — `flesh` là dữ liệu phẳng, `skeleton` cung cấp hình dạng.
- Làm việc với các thừa số, ma trận và danh sách lồng nhau.
---
## txtProgressBar
- `txtProgressBar(min, max, style = 3)` — kiểu 3 hiển thị phần trăm + thanh (hữu ích nhất).
- Cập nhật với `setTxtProgressBar(pb, value)`. Đóng bằng `close(pb)`.
- Kiểu 1: xoay `|/-\`, kiểu 2: tiến trình đơn giản. Chỉ có kiểu 3 hiển thị phần trăm.
---
## đối tượng.kích thước
- Trả về **ước tính** bộ nhớ được một đối tượng sử dụng. Không phải lúc nào cũng chính xác đối với các tài liệu tham khảo được chia sẻ.
- `format(object.size(x), units = "MB")` cho đầu ra mà con người có thể đọc được.
- Không tính kích thước của môi trường hoặc con trỏ bên ngoài.
---
## đã cài đặt.packages / update.packages
- `installed.packages()` có thể chậm (quét tất cả các gói). Sử dụng `find.package()` hoặc `requireNamespace()` để kiểm tra gói cụ thể.
- `update.packages(ask = FALSE)` cập nhật tất cả các gói mà không cần nhắc.
- `lib.loc` chỉ định thư viện nào cần kiểm tra/cập nhật.
---
## họa tiết / bản demo
- `vignette()` liệt kê tất cả họa tiết; `vignette("name", package = "pkg")` mở một cái cụ thể.
- `demo()` liệt kê tất cả các bản demo; `demo("topic")` chạy một cách tương tác.
- `browseVignettes()` mở trình duyệt họa tiết trong HTML.
---
## Chuỗi thời gian: acf/arima/ts/stl/phân hủy
- `ts(data, start, frequency)`: `frequency` là số quan sát trên một đơn vị thời gian (12 cho hàng tháng, 4 cho hàng quý).
- `acf` mặc định `type = "correlation"`. Sử dụng `type = "partial"` cho PACF. `plot = FALSE` để ngăn chặn việc tự động vẽ đồ thị.
- `arima(x, order = c(p,d,q))` cho các mẫu ARIMA. `seasonal = list(order = c(P,D,Q), period = S)` cho thành phần theo mùa.
- `arima` xử lý các giá trị `NA` trong chuỗi thời gian (thông qua bộ lọc Kalman).
- `stl` yêu cầu `s.window` (thời hạn theo mùa) — phải được chỉ định, không có mặc định. `s.window = "periodic"` giả sử tính thời vụ cố định.
- `decompose`: đơn giản hơn `stl`, sử dụng đường trung bình động. `type = "additive"` hoặc `"multiplicative"`.
- `stl` thành phần kết quả: `$time.series` ma trận với các cột `seasonal`, `trend`, `remainder`.
TẬP TIN: tài liệu tham khảo/data-wrangling.md
# Sắp xếp dữ liệu — Tham khảo nhanh
> Các hành vi không rõ ràng, lỗi sai và các giá trị mặc định phức tạp cho hàm R.
> Chỉ có điều Claude chưa biết thôi.
---
## Trích xuất / Extract.data.frame
Lập chỉ mục những cạm bẫy trong cơ sở R.
- `m[j = 2, i = 1]` là `m[2, 1]` không phải `m[1, 2]` — tên đối số bị **bỏ qua** trong `[`, chỉ khớp theo vị trí. Không bao giờ đặt tên cho chỉ mục.
- Lập chỉ mục yếu tố: `x[f]` sử dụng mã số nguyên của yếu tố `f`, không sử dụng nhãn ký tự của nó. Sử dụng `x[as.character(f)]` để lập chỉ mục dựa trên nhãn.
- `x[[]]` không có chỉ mục luôn là lỗi. `x$name` thực hiện khớp một phần theo mặc định; `x[["name"]]` thì không (chính xác theo mặc định).
- Gán `NULL` thông qua `x[[i]] <- NULL` hoặc `x$name <- NULL` **xóa** thành phần danh sách đó.
- Khung dữ liệu `[` với một cột: `df[, 1]` trả về **vector** (drop=TRUE mặc định cho các cột), nhưng `df[1, ]` trả về **khung dữ liệu** (drop=FALSE cho các hàng). Sử dụng `drop = FALSE` một cách rõ ràng.
- Ma trận lập chỉ mục khung dữ liệu (`df[cbind(i,j)]`) buộc vào ma trận trước - tránh.
---
## tập hợp con
Chỉ sử dụng tương tác; không an toàn cho việc lập trình.
- Đối số `subset` sử dụng **đánh giá không chuẩn** — tên cột được phân giải trong khung dữ liệu, điều này có thể âm thầm nhận ra các biến sai khi sử dụng theo chương trình. Sử dụng `[` với logic rõ ràng trong hàm.
- `NA` trong điều kiện logic được coi là `FALSE` (các hàng được loại bỏ âm thầm).
- Các yếu tố có thể giữ lại mức chưa sử dụng sau khi cài đặt lại; gọi `droplevels()`.
---
## trận đấu / %in%
- `%in%` **không bao giờ trả về NA** — điều này đảm bảo an toàn cho các điều kiện `if()` không giống như `==`.
- `match()` chỉ trả về vị trí của **kết quả phù hợp** đầu tiên; các bản sao trong `table` bị bỏ qua.
- Các yếu tố, vectơ thô và danh sách đều được chuyển đổi thành ký tự trước khi khớp.
- `NaN` khớp với `NaN` nhưng không khớp với `NA`; `NA` chỉ khớp với `NA`.
---
## áp dụng
- Trên **khung dữ liệu**, `apply` ép buộc vào ma trận thông qua `as.matrix` trước tiên — các kiểu hỗn hợp trở thành ký tự.
- Hướng giá trị trả về được hoán vị: nếu FUN trả về vectơ có độ dài n, kết quả có độ mờ `c(n, dim(X)[MARGIN])`. Kết quả hàng trở thành **cột**.
- Kết quả nhân tố được ép buộc về ký tự trong mảng đầu ra.
- `...` đối số không thể chia sẻ tên với `X`, `MARGIN` hoặc `FUN` (rủi ro khớp một phần).
---
## lapply / sapply / vapply
- `sapply` có thể trả về một vectơ, ma trận hoặc danh sách một cách không thể đoán trước — sử dụng `vapply` trong mã không tương tác với mẫu `FUN.VALUE` rõ ràng.
- Gọi trực tiếp các hàm gốc trong `lapply` có thể gây ra sự cố gửi đi; bọc trong `function(x) is.numeric(x)` thay vì `is.numeric` trần.
- `sapply` với `simplify = "array"` có thể tạo ra các mảng có thứ hạng cao hơn (không chỉ ma trận).
---
## gõ nhẹ
- Trả về một **mảng** (không phải khung dữ liệu). Thông tin lớp về các giá trị trả về bị **loại bỏ** (ví dụ: các đối tượng Ngày trở thành số).
- `...` đối số cho FUN **không** được chia thành các ô — chúng áp dụng trên toàn cầu, vì vậy FUN không nên mong đợi các đối số bổ sung có cùng độ dài với X.
- `default = NA` điền vào các ô trống; đặt `default = 0` cho các phép tính tính tổng. Trước R 3.4.0, mã này được mã hóa cứng thành `NA`.
- Sử dụng `array2DF()` để chuyển đổi kết quả sang khung dữ liệu.
---
## ứng dụng bản đồ
- Tên đối số là `SIMPLIFY` (viết hoa toàn bộ) không phải `simplify` — không nhất quán với `sapply`.
- `MoreArgs` phải là một **danh sách** các đối số chưa được vector hóa.
- Tái chế các đối số ngắn hơn thành chiều dài chung; arg có độ dài bằng 0 cho kết quả có độ dài bằng 0.
---
## hợp nhất
- Mặc định `by` là `intersect(names(x), names(y))` — có thể âm thầm hợp nhất trên các cột ngoài ý muốn nếu khung dữ liệu có chung tên cột.
- `by = 0` hoặc `by = "row.names"` hợp nhất trên tên hàng, thêm cột "Row.names".
- `by = NULL` (hoặc cả hai `by.x`/`by.y` có độ dài 0) tạo ra **sản phẩm Descartes**.
- Kết quả được sắp xếp theo mặc định trên cột `by` (`sort = TRUE`). Đối với đầu ra chưa được sắp xếp, hãy sử dụng `sort = FALSE`.
- Các kết hợp khóa trùng lặp sẽ tạo ra **tất cả các kết hợp** (một hàng cho mỗi cặp kết hợp).
---
## tách ra
- Nếu `f` là danh sách các yếu tố thì sử dụng tương tác; các mức chứa `"."` có thể gây ra sự phân chia không mong muốn trừ khi `sep` được thay đổi.
- `drop = FALSE` (mặc định) giữ nguyên các mức hệ số trống dưới dạng thành phần danh sách trống.
- Hỗ trợ cú pháp công thức: `split(df, ~ Month)`.
---
##cbind/rbind
- `cbind` trên các lệnh gọi khung dữ liệu `data.frame(...)`, không phải `cbind.matrix`. Trộn ma trận và khung dữ liệu có thể cho kết quả không mong muốn.
- `rbind` trên khung dữ liệu khớp với các cột **theo tên**, không phải vị trí. Thiếu cột nhận được `NA`.
- `cbind(NULL)` trả về `NULL` (không phải ma trận). Để nhất quán, `rbind(NULL)` cũng trả về `NULL`.
---
## bàn
- Theo mặc định **không bao gồm NA** (`useNA = "no"`). Sử dụng `useNA = "ifany"` hoặc `exclude = NULL` để đếm NA.
- Đặt `exclude` không trống và không mặc định ngụ ý `useNA = "ifany"`.
- Kết quả luôn là một **mảng** (thậm chí 1D), "bảng" lớp. Chuyển đổi sang khung dữ liệu với `as.data.frame(tbl)`.
- Hai loại NA (NA cấp yếu tố và NA thực tế) được xử lý khác nhau tùy thuộc vào `useNA`/`exclude`.
---
## trùng lặp/duy nhất
- `duplicated` đánh dấu lần xuất hiện **thứ hai trở đi** là TRUE, không phải lần xuất hiện đầu tiên. Sử dụng `fromLast = TRUE` để đảo ngược.
- Đối với khung dữ liệu, thực hiện trên toàn bộ hàng. Đối với danh sách, so sánh đệ quy.
- `unique` giữ lần xuất hiện **đầu tiên** của mỗi giá trị.
---
## data.frame (có vấn đề)
- `stringsAsFactors = FALSE` là mặc định kể từ R 4.0.0 (trước đây là TRUE).
- Vectơ nguyên tử tuần hoàn để khớp với cột dài nhất, nhưng chỉ khi chính xác là bội số. Bảo vệ bằng `I()` để ngăn chuyển đổi.
- Chỉ cho phép tên cột trùng lặp với `check.names = FALSE`, nhưng nhiều thao tác sẽ loại bỏ trùng lặp chúng một cách âm thầm.
- Đối số ma trận được mở rộng thành nhiều cột trừ khi được bảo vệ bởi `I()`.
---
## yếu tố (gotchas)
- `as.numeric(f)` trả về **mã số nguyên**, không phải giá trị gốc. Sử dụng `as.numeric(levels(f))[f]` hoặc `as.numeric(as.character(f))`.
- Chỉ `==` và `!=` hoạt động giữa các yếu tố; các yếu tố phải có bộ cấp độ giống hệt nhau. Hỗ trợ các hệ số thứ tự `<`, `>`.
- `c()` trên các bộ cấp độ liên kết thừa số (kể từ R 4.1.0), nhưng các phiên bản trước đó được chuyển đổi thành số nguyên.
- Các cấp độ được sắp xếp theo mặc định, nhưng thứ tự sắp xếp **phụ thuộc vào ngôn ngữ** tại thời điểm tạo.
---
## tổng hợp
- Giao diện công thức (`aggregate(y ~ x, data, FUN)`) giảm `NA` nhóm theo mặc định.
- Phương thức khung dữ liệu yêu cầu `by` dưới dạng **danh sách** (không phải vectơ).
- Trả về các cột được đặt tên theo các biến nhóm, với cột kết quả giữ nguyên tên gốc.
- Nếu FUN trả về nhiều giá trị, cột kết quả là **cột ma trận** bên trong khung dữ liệu.
---
## hoàn thành.trường hợp
- Trả về một vectơ logic: TRUE cho các hàng có **no** NA trên tất cả các cột/đối số.
- Hoạt động trên nhiều đối số (ví dụ: `complete.cases(x, y)` kiểm tra cả hai).
---
## đặt hàng
- Trả về **vectơ hoán vị** của các chỉ số, không phải giá trị được sắp xếp. Sử dụng `x[order(x)]` để sắp xếp.
- Mặc định là tăng dần; sử dụng `-x` cho số giảm dần hoặc `decreasing = TRUE`.
- Để sắp xếp ký tự, tùy thuộc vào miền địa phương. Sử dụng `method = "radix"` để sắp xếp nhanh không phụ thuộc vào miền địa phương.
- `sort.int()` với `method = "radix"` nhanh hơn nhiều đối với vectơ số nguyên/ký tự lớn.
TẬP TIN: tham chiếu/ngày-và-system.md
# Ngày và Hệ thống — Tham khảo nhanh
> Các hành vi không rõ ràng, lỗi sai và các giá trị mặc định phức tạp cho hàm R.
> Chỉ có điều Claude chưa biết thôi.
---
## Ngày (Lớp ngày)
- `Date` đối tượng được lưu trữ dưới dạng **ngày nguyên kể từ 1970-01-01**. Số học hoạt động theo ngày.
- `Sys.Date()` trả về ngày hiện tại dưới dạng đối tượng Date.
- `seq.Date(from, to, by = "month")` — số gia "tháng" có thể tạo ra các khoảng thời gian có độ dài khác nhau. Thêm 1 tháng vào ngày 31 tháng 1 sẽ có ngày 3 tháng 3 (không phải ngày 28 tháng 2).
- `diff(dates)` trả về đối tượng `difftime` sau ngày.
- `format(date, "%Y")` cho năm, `"%m"` cho tháng, `"%d"` cho ngày, `"%A"` cho tên ngày trong tuần (phụ thuộc vào ngôn ngữ).
- Những năm trước 1CE có thể không được xử lý đúng cách.
- `length(date_vector) <- n` miếng đệm có `NA`s nếu được mở rộng.
---
## DateTimeClasses (POSIXct / POSIXlt)
- `POSIXct`: giây kể từ 1970-01-01 UTC (thu gọn, vectơ số).
- `POSIXlt`: danh sách với các thành phần `$sec`, `$min`, `$hour`, `$mday`, `$mon` (0-11!), `$year` (kể từ năm 1900!), `$wday` (0-6, Chủ Nhật=0), `$yday` (0-365).
- Chuyển đổi giữa POSIXct và Ngày: `as.Date(posixct_obj)` sử dụng `tz = "UTC"` theo mặc định — có thể cung cấp ngày khác với dự định nếu ban đầu ở múi giờ khác.
- `Sys.time()` trả về POSIXct theo múi giờ hiện tại.
- `strptime` trả về POSIXlt; `as.POSIXct(strptime(...))` để nhận POSIXct.
- `difftime` số học: trừ các đối tượng POSIXct sẽ cho ra thời gian khác nhau. Đơn vị được chọn tự động ("giây", "phút", "giờ", "ngày", "tuần").
---
## khoảng cách
- `difftime(time1, time2, units = "auto")` — tự động chọn đơn vị hợp lý nhỏ nhất.
- Đơn vị rõ ràng: `"secs"`, `"mins"`, `"hours"`, `"days"`, `"weeks"`. Không có "tháng" hoặc "năm" (độ dài thay đổi).
- `as.numeric(diff, units = "hours")` để trích xuất giá trị số theo đơn vị cụ thể.
- `units(diff_obj) <- "hours"` thay đổi thiết bị tại chỗ.
---
## system.time / proc.time
- `system.time(expr)` trả về thời gian `user`, `system` và `elapsed`.
- `gcFirst = TRUE` (mặc định): chạy thu gom rác trước thời gian để có kết quả nhất quán hơn.
- `proc.time()` trả về thời gian tích lũy kể từ khi R bắt đầu — lấy chênh lệch trong các khoảng thời gian.
- `elapsed` (đồng hồ treo tường) có thể nhỏ hơn `user` (BLAS đa luồng) trở lên (I/O chờ).
---
## Sys.ngủ
- `Sys.sleep(seconds)` — cho phép phân số giây. Giấc ngủ thực tế có thể dài hơn (lập lịch cho hệ điều hành).
- Quá trình **nhường** cho HĐH trong chế độ ngủ (không bận-chờ).
---
## tùy chọn (tùy chọn chính)
Các tùy chọn không rõ ràng được chọn:
- `options(scipen = n)`: thành kiến tích cực đối với ký hiệu cố định, tiêu cực đối với ký hiệu khoa học. Mặc định 0. Áp dụng cho `print`/`format`/`cat` chứ không phải `sprintf`.
- `options(digits = n)`: chữ số có nghĩa để in (1-22, mặc định 7). Chỉ gợi ý.
- `options(digits.secs = n)`: chữ số thập phân tối đa cho giây trong định dạng thời gian (0-6, 0 mặc định).
- `options(warn = n)`: -1 = bỏ qua cảnh báo, 0 = thu thập (mặc định), 1 = ngay lập tức, 2 = chuyển thành lỗi.
- `options(error = recover)`: bị lỗi thả vào trình gỡ lỗi. `options(error = NULL)` đặt lại về mặc định.
- `options(OutDec = ",")`: thay đổi dấu phân cách thập phân ở đầu ra (ảnh hưởng đến `format`, `print`, KHÔNG phải `sprintf`).
- `options(stringsAsFactors = FALSE)`: mặc định chung cho `data.frame` (tranh luận kể từ R 4.0.0 trong đó nó đã FALSE).
- `options(expressions = 5000)`: số lượng đánh giá lồng nhau tối đa. Tăng cho đệ quy sâu.
- `options(max.print = 99999)`: điều khiển việc cắt bớt ở đầu ra `print`.
- `options(na.action = "na.omit")`: xử lý NA mặc định trong các hàm mô hình.
- `options(contrasts = c("contr.treatment", "contr.poly"))`: độ tương phản mặc định cho các yếu tố không có thứ tự/có thứ tự.
---
## file.path / basename / dirname
- `file.path("a", "b", "c.txt")` → `"a/b/c.txt"` (dấu phân cách phù hợp với nền tảng).
- `basename("/a/b/c.txt")` → `"c.txt"`. `dirname("/a/b/c.txt")` → `"/a/b"`.
- `file.path` KHÔNG bình thường hóa đường dẫn (không có độ phân giải `..`); sử dụng `normalizePath()` cho điều đó.
---
## list.files
- `list.files(pattern = "*.csv")` — `pattern` là một **regex**, không phải một quả cầu! Sử dụng `glob2rx("*.csv")` hoặc `"\\.csv$"`.
- `full.names = FALSE` (mặc định) chỉ trả về tên cơ sở. Sử dụng `full.names = TRUE` để biết đường dẫn đầy đủ.
- `recursive = TRUE` để tìm kiếm thư mục con.
- `all.files = TRUE` để bao gồm các tệp ẩn (bắt đầu bằng `.`).
---
## tập tin.info
- Trả về khung dữ liệu với `size`, `isdir`, `mode`, `mtime`, `ctime`, `atime`, `uid`, `gid`.
- `mtime`: thời gian sửa đổi (POSIXct). Hữu ích cho `file.info(f)$mtime`.
- Trên một số hệ thống tập tin, `ctime` là thời gian thay đổi trạng thái, không phải thời gian tạo.
---
## file_test
- `file_test("-f", path)`: TRUE nếu tồn tại file thông thường.
- `file_test("-d", path)`: TRUE nếu thư mục tồn tại.
- `file_test("-nt", f1, f2)`: TRUE nếu f1 mới hơn f2.
- Đáng tin cậy hơn `file.exists()` để phân biệt tệp với thư mục.
TẬP TIN: tham khảo/io-and-text.md
# I/O và Xử lý văn bản — Tham khảo nhanh
> Các hành vi không rõ ràng, lỗi sai và các giá trị mặc định phức tạp cho hàm R.
> Chỉ có điều Claude chưa biết thôi.
---
## read.table (gotchas)
- `sep = ""` (mặc định) có nghĩa là **bất kỳ khoảng trắng nào** (dấu cách, tab, dòng mới) — không phải là một chuỗi trống theo nghĩa đen.
- `comment.char = "#"` theo mặc định — các dòng có `#` bị cắt ngắn. Sử dụng `comment.char = ""` để tắt (cũng nhanh hơn).
- `header` tự động phát hiện: đặt thành TRUE nếu hàng đầu tiên có **ít hơn một trường** so với các hàng tiếp theo (trường bị thiếu được coi là tên hàng).
- `colClasses = "NULL"` **bỏ qua** hoàn toàn cột đó — rất hữu ích cho tốc độ.
- `read.csv` giá trị mặc định khác với `read.table`: `header = TRUE`, `sep = ","`, `fill = TRUE`, `comment.char = ""`.
- Đối với các tệp lớn: việc chỉ định `colClasses` và `nrows` làm giảm đáng kể mức sử dụng bộ nhớ. `read.table` chậm đối với khung dữ liệu rộng (hàng trăm cột); sử dụng `scan` hoặc `data.table::fread` cho ma trận.
- `stringsAsFactors = FALSE` kể từ R 4.0.0 (trước đây là TRUE).
---
## write.table (có vấn đề)
- `row.names = TRUE` theo mặc định — tạo ra cột đầu tiên không có tên gây nhầm lẫn cho việc đọc lại. Sử dụng `row.names = FALSE` hoặc `col.names = NA` cho CSV tương thích với Excel.
- `write.csv` sửa `sep = ","`, `dec = "."` và sử dụng `qmethod = "double"` — không thể ghi đè những lỗi này thông qua `...`.
- `quote = TRUE` (mặc định) trích dẫn các cột ký tự/yếu tố. Các cột số không bao giờ được trích dẫn.
- Các cột giống ma trận trong khung dữ liệu sẽ âm thầm mở rộng thành nhiều cột.
- Chậm đối với các khung dữ liệu có nhiều cột (hàng trăm cột); mỗi cột được xử lý riêng biệt theo lớp.
---
## đọc.fwf
- Đọc các tập tin định dạng có chiều rộng cố định. `widths` là vectơ độ rộng trường.
- **Bỏ qua độ rộng âm** nhiều ký tự (hữu ích khi bỏ qua các trường).
- `buffersize` kiểm soát số lượng dòng được đọc cùng một lúc; tăng cho các tập tin lớn.
- Sử dụng `read.table` nội bộ sau khi tách các trường.
---
## số trường
- Đếm các trường trên mỗi dòng trong một tệp - hữu ích để chẩn đoán lỗi đọc.
- Các đối số `sep` và `quote` khớp với các đối số của `read.table`.
---
## grep / grepl / sub / gsub (gotchas)
- Ba chế độ biểu thức chính quy: POSIX mở rộng (mặc định), `perl = TRUE`, `fixed = TRUE`. Họ hành xử khác nhau đối với các trường hợp khó khăn.
- **Đặt tên đối số một cách rõ ràng** — các đối số không được đặt tên sau `x`/`pattern` được khớp về vị trí với `ignore.case`, `perl`, v.v. Nguồn phổ biến của các lỗi im lặng.
- `sub` chỉ thay thế kết quả **đầu tiên**; `gsub` thay thế **tất cả** kết quả phù hợp.
- Tham chiếu ngược: `"\\1"` thay thế (dấu gạch chéo ngược kép trong chuỗi R). Với `perl = TRUE`: `"\\U\\1"` để chuyển đổi chữ hoa.
- `grep(value = TRUE)` trả về **phần tử** phù hợp; `grep(value = FALSE)` (mặc định) trả về **chỉ số**.
- `grepl` trả về vectơ logic - được ưu tiên để lọc.
- `regexpr` trả về vị trí + độ dài khớp đầu tiên (dưới dạng thuộc tính); `gregexpr` trả về tất cả kết quả phù hợp dưới dạng danh sách.
- `regexec` trả về vị trí nhóm khớp + nắm bắt; `gregexec` thực hiện điều này cho tất cả các trận đấu.
- Các lớp ký tự như `[:alpha:]` phải nằm trong `[[:alpha:]]` (dấu ngoặc kép) ở chế độ POSIX.
---
## phân tách
- Trả về một **danh sách** (một phần tử cho mỗi chuỗi đầu vào), ngay cả đối với một chuỗi đơn.
- `split = ""` hoặc `split = character(0)` chia thành các ký tự riêng lẻ.
- So khớp ở đầu chuỗi: phần tử đầu tiên của kết quả là `""`. Trận đấu ở cuối: không có dấu `""`.
- `fixed = TRUE` nhanh hơn và tránh được việc giải thích biểu thức chính quy.
- Lỗi thường gặp: các đối số không được đặt tên âm thầm khớp với `fixed`, `perl`, v.v.
---
## chuỗi con / chuỗi con
- `substr(x, start, stop)`: trích xuất/thay thế chuỗi con. 1-lập chỉ mục, bao gồm cả hai đầu.
- `substring(x, first, last)`: tương tự nhưng `last` mặc định là `1000000L` (có hiệu lực là "kết thúc"). Được vector hóa trên `first`/`last`.
- Mẫu bài tập: `substr(x, 1, 3) <- "abc"` thay thế tại chỗ (phải thay thế có cùng độ dài).
---
## trang trí
- `which = "both"` (mặc định), `"left"` hoặc `"right"`.
- `whitespace = "[ \\t\\r\\n]"` — biểu thức chính quy có thể tùy chỉnh cho những gì được coi là khoảng trắng.
---
##nchar
- `type = "bytes"` đếm byte; `type = "chars"` (mặc định) đếm ký tự; `type = "width"` đếm chiều rộng hiển thị.
- `nchar(NA)` trả về `NA` (không phải 2). `nchar(factor)` hoạt động trên nhãn cấp độ.
- `keepNA = TRUE` (mặc định kể từ R 3.3.0); được đặt thành `FALSE` để đếm `"NA"` là 2 ký tự.
---
## định dạng / định dạngC
- `format(x, digits, nsmall)`: `nsmall` bắt buộc phải có số thập phân tối thiểu. `big.mark = ","` thêm dấu phân cách hàng nghìn.
- `formatC(x, format = "f", digits = 2)`: Định dạng kiểu C. `format = "e"` cho khoa học, `"g"` cho chung.
- `format` trả về vectơ ký tự; luôn được căn phải theo mặc định (`justify = "right"`).
---
## loại.convert
- Chuyển đổi vectơ ký tự thành các kiểu thích hợp (logic, số nguyên, kép, phức tạp, ký tự).
- `as.is = TRUE` (được khuyến nghị): giữ ký tự là ký tự, không phải là yếu tố.
- Áp dụng theo cột trên khung dữ liệu. `tryLogical = TRUE` (R 4.3+) chuyển đổi cột "TRUE"/"FALSE".
---
## bản ghi
- `commandArgs(trailingOnly = TRUE)` nhận các đối số tập lệnh (không bao gồm cờ R/Rscript).
- Dòng `#!` trên Unix: `/usr/bin/env Rscript` hoặc đường dẫn đầy đủ.
- `--vanilla` hoặc `--no-init-file` để bỏ qua quá trình tải `.Rprofile`.
- Mã thoát: `quit(status = 1)` để thoát lỗi.
---
## chụp.đầu ra
- Ghi lại đầu ra từ `cat`, `print` hoặc bất kỳ biểu thức nào ghi vào thiết bị xuất chuẩn.
- `file = NULL` (mặc định) trả về vectơ ký tự. `file = "out.txt"` ghi trực tiếp vào tệp.
- Thay vào đó, `type = "message"` sẽ chụp stderr.
---
## Mã hóa URL / Mã hóa URL
- `URLencode(url, reserved = FALSE)` theo mặc định KHÔNG mã hóa các ký tự dành riêng (`/`, `?`, `&`, v.v.).
- Đặt `reserved = TRUE` để mã hóa URL **thành phần** (giá trị tham số truy vấn).
---
##glob2rx
- Chuyển đổi các mẫu toàn cầu shell thành biểu thức chính quy: `glob2rx("*.csv")` → `"^.*\\.csv$"`.
- Hữu ích với `list.files(pattern = glob2rx("data_*.RDS"))`.
TẬP TIN: tài liệu tham khảo/modeling.md
# Lập mô hình — Tham khảo nhanh
> Các hành vi không rõ ràng, lỗi sai và các giá trị mặc định phức tạp cho hàm R.
> Chỉ có điều Claude chưa biết thôi.
---
## công thức
Các vấn đề cần lưu ý về đặc tả mô hình tượng trưng.
- Bắt buộc phải có `I()` để sử dụng các toán tử số học theo đúng nghĩa đen: `y ~ x + I(x^2)`. Không có `I()`, `^` có nghĩa là vượt qua tương tác.
- `*` = tác dụng chính + tương tác: `a*b` mở rộng thành `a + b + a:b`.
- `(a+b+c)^2` = tất cả các hiệu ứng chính + tất cả tương tác 2 chiều (không bình phương).
- `-` xóa các điều khoản: `(a+b+c)^2 - a:b` chỉ giảm tương tác `a:b`.
- `/` nghĩa là lồng nhau: `a/b` = `a + b %in% a` = `a + a:b`.
- `.` trong công thức có nghĩa là "tất cả các cột khác trong dữ liệu" (trong ngữ cảnh `terms.formula`) hoặc "nội dung trước đó" (trong `update.formula`).
- Đối tượng công thức mang **môi trường** được sử dụng để tra cứu biến; `as.formula("y ~ x")` sử dụng `parent.frame()`.
---
## thuật ngữ / model.matrix
- `model.matrix` tạo ma trận thiết kế bao gồm mã hóa giả. Độ tương phản mặc định: `contr.treatment` cho các yếu tố không có thứ tự, `contr.poly` cho các yếu tố có thứ tự.
- `terms` thuộc tính đối tượng: `order` (thứ tự tương tác mỗi thuật ngữ), ma trận `intercept`, `factors`.
- Tên cột từ `model.matrix` có thể gây ngạc nhiên: ví dụ: nối `factorLevelName`.
---
## xin chào
- Mặc định `family = gaussian(link = "identity")` — `glm()` không có `family` âm thầm phù hợp với OLS (giống như `lm`, nhưng chậm hơn và có đầu ra dựa trên độ lệch).
- Các họ thông dụng: `binomial(link = "logit")`, `poisson(link = "log")`, `Gamma(link = "inverse")`, `inverse.gaussian()`.
- `binomial` chấp nhận phản hồi dưới dạng: vectơ 0/1, logic, hệ số (cấp thứ hai = thành công) hoặc ma trận 2 cột `cbind(success, failure)`.
- `weights` trong `glm` có nghĩa là **trọng số trước** (không phải trọng số tần số) — đối với trọng số tần số, hãy sử dụng thủ thuật cbind hoặc phần bù.
- `predict.glm(type = "response")` cho xác suất dự đoán; mặc định `type = "link"` trả về tỷ lệ logarit (đối với logistic) hoặc tỷ lệ log (đối với Poisson).
- `anova(glm_obj, test = "Chisq")` cho các bài kiểm tra dựa trên độ lệch; `"F"` không hợp lệ đối với các dòng không phải Gaussian.
- Gần như họ (`quasibinomial`, `quasipoisson`) cho phép phân tán quá mức — không có AIC nào được tính toán.
- Hội tụ: `control = glm.control(maxit = 100)` nếu 25 lần lặp mặc định là không đủ.
---
## trên
- `aov` là trình bao bọc xung quanh `lm` lưu trữ thông tin bổ sung cho ANOVA cân bằng. Đối với các thiết kế không cân bằng, SS Loại I (tuần tự) được tính toán - thứ tự của các thuật ngữ rất quan trọng.
- Đối với SS loại III, sử dụng `car::Anova()` hoặc đặt độ tương phản thành `contr.sum`/`contr.helmert`.
- Tầng lỗi đối với các biện pháp lặp lại: `aov(y ~ A*B + Error(Subject/B))`.
- `summary.aov` đưa ra bảng ANOVA; `summary.lm(aov_obj)` đưa ra bản tóm tắt kiểu hồi quy.
---
##nls
- Yêu cầu **giá trị khởi đầu tốt** trong `start = list(...)` hoặc hội tụ không thành công.
- Các mô hình tự khởi động (`SSlogis`, `SSasymp`, v.v.) tự động tính toán các giá trị bắt đầu.
- Thuật toán `"port"` cho phép giới hạn các tham số (`lower`/`upper`).
- Nếu dữ liệu khớp quá chính xác (không có nhiễu dư), quá trình kiểm tra hội tụ không thành công — sử dụng `control = list(scaleOffset = 1)` hoặc dữ liệu jitter.
- đối số `weights` cho NLS có trọng số; `na.action` để xử lý giá trị bị thiếu.
---
## bước / thêm1
- `step` thực hiện lựa chọn mô hình **từng bước** theo AIC (mặc định). Sử dụng `k = log(n)` cho BIC.
- Hướng: `direction = "both"` (mặc định), `"forward"` hoặc `"backward"`.
- `add1`/`drop1` đánh giá việc thêm/xóa một thuật ngữ; `step` gọi chúng lặp đi lặp lại.
- Đối số `scope` xác định giới hạn mô hình trên/dưới để tìm kiếm.
- `step` sửa đổi đối tượng mô hình tại chỗ — có thể chậm đối với các mô hình lớn có nhiều thuật ngữ ứng viên.
---
## dự đoán.lm / dự đoán.glm
- `predict.lm` với `interval = "confidence"` cung cấp CI cho phản hồi **trung bình**; `interval = "prediction"` cung cấp PI cho **quan sát mới** (rộng hơn).
- `newdata` phải có các cột khớp với các biến công thức ban đầu — các hệ số phải có cùng cấp độ.
- `predict.glm` với `type = "response"` đưa ra dự đoán về thang đo phản hồi (ví dụ: xác suất cho logistic); `type = "link"` (mặc định) đưa ra thang đo liên kết.
- `se.fit = TRUE` trả về lỗi tiêu chuẩn; đối với `predict.glm` những giá trị này nằm trên thang **liên kết** bất kể `type`.
- `predict.lm` với `type = "terms"` trả về phần đóng góp của mỗi kỳ hạn.
---
## hoàng thổ
- `span` kiểm soát độ mượt (mặc định 0,75). Span < 1 uses that proportion of points; span > 1 sử dụng tất cả các điểm có khoảng cách được điều chỉnh.
- Tối đa **4 yếu tố dự đoán**. Mức sử dụng bộ nhớ gần như **bậc hai** tính bằng n (1000 điểm ~ 10MB).
- `degree = 0` (hằng số cục bộ) được cho phép nhưng được kiểm tra kém — hãy thận trọng khi sử dụng.
- Không giống với `loess` của S; điều hòa không được thực hiện.
- `normalize = TRUE` (mặc định) chuẩn hóa các yếu tố dự đoán theo thang đo chung; đặt `FALSE` cho các dây không gian.
---
## thấp so với hoàng thổ
- `lowess` là hàm cũ hơn; trả về `list(x, y)` - không thể dự đoán tại các điểm mới.
- `loess` là giao diện công thức mới hơn với phương thức `predict`.
- Tham số `lowess` là `f` (span, mặc định 2/3); Tham số `loess` là `span` (mặc định là 0,75).
- `lowess` `iter` mặc định là 3 (tăng cường lặp lại); `loess` mặc định `family = "gaussian"` (không có độ bền).
---
## mịn.spline
- Tham số làm mịn mặc định được chọn bởi **GCV** (xác thực chéo tổng quát).
- `cv = TRUE` thay vào đó sử dụng CV loại bỏ một lần thông thường — không sử dụng với các giá trị x trùng lặp.
- `spar` và `lambda` kiểm soát độ mượt; `df` có thể chỉ định bậc tự do tương đương.
- Trả về đối tượng với các phương thức `predict`, `print`, `plot`. Thành phần `fit` có các nút thắt và hệ số.
---
## tối ưu
- **Giảm thiểu** theo mặc định. Để tối đa hóa: đặt `control = list(fnscale = -1)`.
- Phương pháp mặc định là Nelder-Mead (không có độ dốc, mạnh nhưng chậm). Kém đối với 1D — sử dụng `"Brent"` hoặc `optimize()`.
- `"L-BFGS-B"` là phương thức duy nhất hỗ trợ các ràng buộc hộp (`lower`/`upper`). Giới hạn tự động chọn phương pháp này với một cảnh báo.
- `"SANN"` (ủ mô phỏng): mã hội tụ **luôn là 0** — nó không bao giờ "lỗi". `maxit` = tổng giá trị hàm (mặc định 10000), không có tiêu chí dừng nào khác.
- `parscale`: tham số tỷ lệ để thay đổi đơn vị trong mỗi tham số sẽ tạo ra sự thay đổi mục tiêu tương đương. Quan trọng đối với các vấn đề có quy mô hỗn hợp.
- `hessian = TRUE`: trả về Hessian số của bài toán **không bị ràng buộc** ngay cả khi ràng buộc hộp đang hoạt động.
- `fn` có thể trả về `NA`/`Inf` (ngoại trừ `"L-BFGS-B"` luôn yêu cầu các giá trị hữu hạn). Giá trị ban đầu phải hữu hạn.
---
## tối ưu hóa / uniroot
- `optimize`: Giảm thiểu 1D trên một khoảng giới hạn. Trả về `minimum` và `objective`.
- `uniroot`: tìm gốc của `f` trong `[lower, upper]`. **Yêu cầu** `f(lower)` và `f(upper)` có dấu ngược nhau.
- `uniroot` với `extendInt = "yes"` có thể tự động kéo dài khoảng thời gian để tìm sự thay đổi dấu — nhưng có thể tìm ra nghiệm giả cho các hàm không thực sự vượt qua 0.
- `nlm`: Bộ giảm thiểu kiểu Newton. gradient/Hessian dưới dạng **thuộc tính** của giá trị trả về từ `fn` (giao diện bất thường).
---
##TukeyHSD
- Yêu cầu đối tượng `aov` được trang bị (không phải `lm`).
- Mặc định `conf.level = 0.95`. Trả về giá trị p đã điều chỉnh và khoảng tin cậy cho tất cả so sánh theo cặp.
- Chỉ có ý nghĩa đối với các thiết kế **cân bằng** hoặc gần cân bằng; có thể tự do cho dữ liệu rất mất cân bằng.
---
## anova (cho lm)
- `anova(model)`: SS tuần tự (Loại I) — **thứ tự các thuật ngữ quan trọng**.
- `anova(model1, model2)`: F-test so sánh các mô hình lồng nhau.
- Đối với SS loại II hoặc III, hãy sử dụng `car::Anova()`.
TẬP TIN: tham khảo/statistics.md
# Thống kê — Tham khảo nhanh
> Các hành vi không rõ ràng, lỗi sai và các giá trị mặc định phức tạp cho hàm R.
> Chỉ có điều Claude chưa biết thôi.
---
## chisq.test
- `correct = TRUE` (mặc định) chỉ áp dụng tính năng sửa lỗi liên tục của Yates cho **bảng 2x2**.
- `simulate.p.value = TRUE`: Monte Carlo với `B = 2000` bản sao (tối thiểu p ~ 0,0005). Mô phỏng giả định **biên độ cố định** (Lấy mẫu kiểu Fisher, không phải giả định chi-sq).
- Để có mức độ phù hợp: truyền vectơ chứ không phải ma trận. `p` phải có tổng bằng 1 (hoặc đặt `rescale.p = TRUE`).
- Đối tượng trả về bao gồm `$expected`, `$residuals` (Pearson) và `$stdres` (chuẩn hóa).
---
## wilcox.test
- `exact = TRUE` theo mặc định cho các mẫu nhỏ không có ràng buộc. Với các mối quan hệ, xấp xỉ bình thường được sử dụng.
- `correct = TRUE` áp dụng hiệu chỉnh tính liên tục cho phép tính gần đúng thông thường.
- `conf.int = TRUE` tính toán ước tính Hodges-Lehmann và khoảng tin cậy (không chỉ giá trị p).
- Kiểm tra theo cặp: `paired = TRUE` sử dụng kiểm tra xếp hạng có chữ ký (Wilcoxon), không sử dụng tổng xếp hạng (Mann-Whitney).
---
## câu cá.test
- Đối với các bảng lớn hơn 2x2, sử dụng mô phỏng (`simulate.p.value = TRUE`) hoặc thuật toán mạng.
- `workspace` kiểm soát bộ nhớ cho thuật toán mạng; tăng nếu bạn gặp lỗi trên các bảng lớn.
- Đối số `or` kiểm tra tỷ lệ chênh lệch cụ thể (mặc định 1) — chỉ dành cho các bảng 2x2.
---
## ks.test
- Kiểm định hai mẫu hoặc một mẫu đối với phân bố tham chiếu.
- **không** xử lý tốt mối quan hệ — cảnh báo và sử dụng phép tính gần đúng tiệm cận.
- Đối với các giả thuyết tổng hợp (các thông số ước tính từ dữ liệu), giá trị p **bảo toàn** (quá lớn). Sử dụng `dgof` hoặc `ks.test` với `exact = NULL` để phân phối riêng biệt.
---
##p.điều chỉnh
- Phương thức: `"holm"` (mặc định), `"BH"` (Benjamini-Hochberg FDR), `"bonferroni"`, `"BY"`, `"hochberg"`, `"hommel"`, `"fdr"` (bí danh cho BH), `"none"`.
- Đối số `n`: tổng số giả thuyết (có thể lớn hơn `length(p)` nếu loại trừ một số giá trị p).
- Xử lý `NA`s: giá trị p được điều chỉnh là `NA` trong đó đầu vào là `NA`.
---
## pairwise.t.test / pairwise.wilcox.test
- `p.adjust.method` mặc định là `"holm"`. Thay đổi thành `"BH"` để kiểm soát FDR.
- `pool.sd = TRUE` (mặc định cho t-test): sử dụng SD gộp trên tất cả các nhóm (giả định phương sai bằng nhau).
- Trả về ma trận các giá trị p, không phải số liệu thống kê kiểm tra.
---
## shapiro.test
- Cỡ mẫu phải nằm trong khoảng từ 3 đến 5000.
- Kiểm tra tính quy phạm; giá trị p thấp = bằng chứng chống lại tính quy chuẩn.
---
## km nghĩa là
- Đề xuất `nstart > 1` (ví dụ: `nstart = 25`): chạy thuật toán từ nhiều lần khởi động ngẫu nhiên, trả về giá trị tốt nhất.
- Mặc định `iter.max = 10` — có thể quá thấp để hội tụ. Tăng cho dữ liệu lớn/phức tạp.
- Thuật toán mặc định là "Hartigan-Wong" (nói chung là tốt nhất). Các điểm rất gần có thể gây ra hiện tượng không hội tụ (cảnh báo bằng `ifault = 4`).
- Đánh số cụm là tùy ý; thứ tự có thể khác nhau giữa các nền tảng.
- Luôn trả về k cụm khi k được chỉ định (ngoại trừ Lloyd-Forgy có thể trả về ít hơn).
---
##hclust
- `method = "ward.D2"` thực hiện chính xác tiêu chí của Ward (sử dụng khoảng cách bình phương). `"ward.D"` cũ hơn không bình phương khoảng cách (được giữ lại để tương thích ngược).
- Đầu vào phải là đối tượng `dist`. Sử dụng `as.dist()` để chuyển đổi ma trận đối xứng.
- `hang = -1` trong `plot()` căn chỉnh tất cả các nhãn ở dưới cùng.
---
## quận
- `method = "euclidean"` (mặc định). Các tùy chọn khác: `"manhattan"`, `"maximum"`, `"canberra"`, `"binary"`, `"minkowski"`.
- Trả về đối tượng `dist` (chỉ hình tam giác phía dưới). Sử dụng `as.matrix()` để lấy ma trận đầy đủ.
- `"canberra"`: các số hạng có tử số và mẫu số bằng 0 bị **bỏ qua** khỏi tổng (không được coi là 0/0).
- Giá trị `Inf`: Khoảng cách Euclide liên quan đến `Inf` là `Inf`. Nhiều `Inf` trong cùng một quan sát sẽ mang lại `NaN` cho một số phương thức.
---
## Prcomp vs Princomp
- `prcomp` sử dụng **SVD** (vượt trội về mặt số lượng); `princomp` sử dụng `eigen` theo hiệp phương sai (kém ổn định hơn, chia tỷ lệ N-1 so với N).
- `scale. = TRUE` trong `prcomp` chuẩn hóa các biến; quan trọng khi các biến có quy mô rất khác nhau.
- `princomp` độ lệch chuẩn khác với `prcomp` theo hệ số `sqrt((n-1)/n)`.
- Cả hai đều trả về `$rotation` (tải) và `$x` (điểm); dấu hiệu của các thành phần có thể khác nhau giữa các lần chạy.
---
## Tỉ trọng
- Băng thông mặc định: `bw = "nrd0"` (quy tắc ngón tay cái của Silverman). Đối với dữ liệu đa phương thức, hãy xem xét `"SJ"` hoặc `"bcv"`.
- `adjust`: hệ số nhân về băng thông. `adjust = 0.5` giảm một nửa băng thông (kém mượt mà hơn).
- Hạt nhân mặc định: `"gaussian"`. Phạm vi mật độ mở rộng ra ngoài phạm vi dữ liệu (được kiểm soát bởi `cut`, 3 băng thông mặc định).
- `n = 512`: số điểm đánh giá. Tăng để vẽ đồ thị mượt mà hơn.
- `from`/`to`: giới hạn rõ ràng phạm vi đánh giá.
---
## lượng tử
- **Chín** `type` tùy chọn (1-9). Mặc định `type = 7` (R mặc định, nội suy tuyến tính). Loại 1 = nghịch đảo của CDF theo kinh nghiệm (mặc định SAS). Loại 4-9 là liên tục; 1-3 là không liên tục.
- `na.rm = FALSE` theo mặc định — trả về NA nếu có bất kỳ NA nào.
- `names = TRUE` theo mặc định, thêm "0%", "25%", v.v. làm tên.
---
## Phân phối (có tất cả)
Tất cả các hàm phân phối đều tuân theo mẫu `d/p/q/r`. Những điểm chung không rõ ràng:
- **`n` đối số trong hàm `r*()`**: nếu `length(n) > 1`, sử dụng `length(n)` làm số đếm chứ không phải chính `n`. Vì vậy `rnorm(c(1,2,3))` tạo ra 3 giá trị chứ không phải 1+2+3.
- `log = TRUE` / `log.p = TRUE`: tính toán theo thang log để đảm bảo độ ổn định về số ở đuôi.
- `lower.tail = FALSE` cung cấp trực tiếp hàm sinh tồn P(X > x) (chính xác hơn 1 - pnorm() ở đuôi).
- **Gamma**: được tham số hóa bởi `shape` và `rate` (= 1/tỷ lệ). Mặc định `rate = 1`. Việc chỉ định cả `rate` và `scale` là một lỗi.
- **Beta**: `shape1` (alpha), `shape2` (beta) — không có tham số `mean`/`sd`.
- **Poisson `dpois`**: `x` có thể không phải là số nguyên (trả về 0 kèm theo cảnh báo về các giá trị không nguyên nếu `log = FALSE`).
- **Weibull**: `shape` và `scale` (không có `rate`). Tham số của R: `f(x) = (shape/scale)(x/scale)^(shape-1) exp(-(x/scale)^shape)`.
- **Lognormal**: `meanlog` và `sdlog` là giá trị trung bình/sd của **log**, không phải của chính bản phân phối.
---
## cor.test
- Phương thức mặc định: `"pearson"`. Ngoài ra `"kendall"` và `"spearman"`.
- Trả về `$estimate`, `$p.value`, `$conf.int` (CI chỉ dành cho Pearson).
- Giao diện công thức: `cor.test(~ x + y, data = df)` — lưu ý `~` không có LHS.
---
## ecdf
- Trả về một **hàm** (hàm bước). Gọi nó trên các giá trị mới: `Fn <- ecdf(x); Fn(3.5)`.
- `plot(ecdf(x))` đưa ra biểu đồ CDF theo kinh nghiệm.
- Hàm trả về là hàm liên tục phải với giới hạn trái (cadlag).
---
## trọng số.mean
- Xử lý `NA` theo trọng số: việc quan sát sẽ bị loại bỏ nếu trọng số là `NA`.
- Trọng số không cần tổng bằng 1; chúng được bình thường hóa trong nội bộ.
TẬP TIN: tài liệu tham khảo/visualization.md
# Trực quan hóa — Tham khảo nhanh
> Các hành vi không rõ ràng, lỗi sai và các giá trị mặc định phức tạp cho hàm R.
> Chỉ có điều Claude chưa biết thôi.
---
## mệnh giá (chắc chắn rồi)
- Cài đặt `par()` dành cho mỗi thiết bị. Mở một thiết bị mới sẽ đặt lại mọi thứ.
- Đặt `mfrow`/`mfcol` đặt lại `cex` thành 1 và `mex` thành 1. Với bố cục 2x2, cơ số `cex` được nhân với 0,83; với hơn 3 hàng/cột, bằng 0,66.
- `mai` (inch), `mar` (dòng), `pin`, `plt`, `pty` đều tương tác. Việc khôi phục tất cả các tham số đã lưu sau khi thay đổi kích thước thiết bị có thể tạo ra kết quả không nhất quán — chiến thắng theo bảng chữ cái cuối cùng.
- `bg` được đặt qua `par()` cũng được đặt `new = FALSE`. Việc đặt `fg` qua `par()` cũng đặt `col`.
- `xpd = NA` clip vào vùng thiết bị (cho phép vẽ ở lề ngoài); `xpd = TRUE` clip để hình vùng; `xpd = FALSE` (mặc định) cắt theo vùng vẽ.
- `mgp = c(3, 1, 0)`: điều khiển dòng tiêu đề (`mgp[1]`), dòng nhãn (`mgp[2]`), dòng trục (`mgp[3]`). Tất cả có đơn vị `mex`.
- `las`: 0 = song song với trục, 1 = ngang, 2 = vuông góc, 3 = dọc. **không** phản hồi `srt`.
- `tck = 1` vẽ các đường lưới ngang qua ô. `tcl = -0.5` (mặc định) đưa ra các dấu tích bên ngoài.
- `usr` với thang đo log: chứa **log10** giới hạn tọa độ, không phải giá trị thô.
- Tham số chỉ đọc: `cin`, `cra`, `csi`, `cxy`, `din`, `page`.
---
## cách trình bày
- `layout(mat)` trong đó `mat` là ma trận các số nguyên xác định cách sắp xếp hình.
- `widths`/`heights` chấp nhận `lcm()` cho kích thước tuyệt đối trộn lẫn với kích thước tương đối.
- Linh hoạt hơn `mfrow`/`mfcol` nhưng không thể truy vấn một khi đã đặt (không giống như `par("mfrow")`).
- `layout.show(n)` trực quan hóa bố cục để gỡ lỗi.
---
## trục / mtext
- `axis(side, at, labels)`: `side` 1=dưới, 2=trái, 3=trên, 4=phải.
- Khoảng cách mặc định giữa các nhãn trục được kiểm soát bởi `par("mgp")`. Nhãn có thể chồng lên nhau nếu không được quản lý.
- `mtext`: `line` đối số định vị văn bản trong các dòng lề (0 = liền kề với ô, dương = hướng ra ngoài). `adj` điều khiển vị trí nằm ngang (0-1).
- `mtext` với `outer = TRUE` ghi vào lề **ngoài** (được đặt bởi `par(oma = ...)`).
---
## đường cong
- Đối số đầu tiên có thể là **biểu thức** trong `x` hoặc một hàm: `curve(sin, 0, 2*pi)` hoặc `curve(x^2 + 1, 0, 10)`.
- `add = TRUE` để phủ lên ô hiện có. Mặc định `n = 101` điểm đánh giá.
- `xname = "x"` theo mặc định; thay đổi nếu biểu thức của bạn sử dụng tên biến khác.
---
## cặp
- Hàm `panel` nhận `(x, y, ...)` cho mỗi cặp. `lower.panel`, `upper.panel`, `diag.panel` cho các vùng khác nhau.
- `gap` kiểm soát khoảng cách giữa các bảng (mặc định 1).
- Giao diện công thức: `pairs(~ var1 + var2 + var3, data = df)`.
---
## âm mưu
- Biểu đồ điều hòa: `coplot(y ~ x | a)` hoặc `coplot(y ~ x | a * b)` cho hai biến điều hòa.
- Chức năng `panel` có thể được tùy chỉnh; `rows`/`columns` bố cục điều khiển.
- Bảng mặc định rút điểm; sử dụng `panel = panel.smooth` cho lớp phủ hoàng thổ.
---
## matplot / matlines / matpoint
- Vẽ các cột của ma trận này với các cột của ma trận khác. Tái chế `col`, `lty`, `pch` trên các cột.
- `type = "l"` theo mặc định (không giống như `plot` mặc định là `"p"`).
- Hữu ích cho việc vẽ nhiều chuỗi thời gian hoặc các đường cong được trang bị đồng thời.
---
## đường viền / fill.contour / hình ảnh
- `contour(x, y, z)`: `z` phải là ma trận có `dim = c(length(x), length(y))`.
- `filled.contour` có bố cục không chuẩn — nó tạo vùng biểu đồ riêng cho phím màu. **Không thể sử dụng `par(mfrow)` với nó**. Việc thêm các phần tử yêu cầu đối số `plot.axes`.
- `image`: vẽ các giá trị z dưới dạng hình chữ nhật được tô màu. Cách phối màu mặc định có thể gây hiểu nhầm; đặt `col` một cách rõ ràng.
- Đối với `image`, `x` và `y` chỉ định **ranh giới ô** hoặc **điểm giữa** tùy theo ngữ cảnh.
---
## persp
- `persp(x, y, z, theta, phi)`: `theta` = góc phương vị, `phi` = vĩ độ.
- Trả về **ma trận biến đổi** (ẩn) để chiếu 3D sang 2D — sử dụng `trans3d()` để thêm điểm/đường vào biểu đồ phối cảnh.
- `shade` và `col` điều khiển độ bóng bề mặt. `border = NA` xóa các đường lưới.
---
## đoạn/mũi tên/trực tràng/đa giác
- Tất cả đều lấy tọa độ vector hóa; tái chế khi cần thiết.
- `arrows`: `code = 1` (đầu ở đầu), `code = 2` (đầu ở cuối, mặc định), `code = 3` (cả hai).
- `polygon`: điểm cuối tự động kết nối với điểm đầu tiên. Điền `col`; `border` điều khiển đường viền.
- `rect(xleft, ybottom, xright, ytop)` — thứ tự đối số lưu ý không giống với các hệ thống khác.
---
## dev / dev.off / dev.copy
- `dev.new()` mở một thiết bị mới. `dev.off()` đóng thiết bị hiện tại (và xóa đầu ra cho các thiết bị tệp như `pdf`).
- `dev.off()` trên thiết bị mở **cuối cùng** sẽ chuyển về thiết bị rỗng.
- `dev.copy(pdf, file = "plot.pdf")` theo sau là `dev.off()` để lưu sơ đồ hiện tại.
- `dev.list()` trả về tất cả các thiết bị đang mở; `dev.cur()` cái đang hoạt động.
---
##pdf
- Phải gọi `dev.off()` để hoàn thiện file. Không có nó, tập tin có thể trống/hỏng.
- `onefile = TRUE` (mặc định): nhiều trang trong một tệp PDF. `onefile = FALSE`: một tệp trên mỗi trang (sử dụng `%d` trong tên tệp để đánh số).
- `useDingbats = FALSE` được khuyến nghị để tránh sự cố với một số trình xem PDF và ký hiệu pch nhất định.
- Kích thước mặc định: 7x7 inch. `family` kiểm soát họ phông chữ.
---
## thiết bị png / bitmap
- `res` kiểm soát dpi (mặc định 72). Để xuất bản: `res = 300` với `width`/`height` thích hợp bằng pixel hoặc inch (với `units = "in"`).
- `type = "cairo"` (trên hệ thống có cairo) mang lại khả năng khử răng cưa tốt hơn mặc định.
- `bg = "transparent"` cho nền trong suốt (PNG hỗ trợ alpha).
---
## màu sắc / rgb / hcl / col2rgb
- `colors()` trả về tất cả 657 màu được đặt tên. `col2rgb("color")` trả về ma trận RGB.
- `rgb(r, g, b, alpha, maxColorValue = 255)` — lưu ý `maxColorValue` mặc định là 1, không phải 255.
- `hcl(h, c, l)`: không gian màu đồng nhất về mặt nhận thức. Được ưu tiên cho thang màu.
- `adjustcolor(col, alpha.f = 0.5)`: cách dễ dàng để thêm độ trong suốt.
---
## colorRamp / colorRampPalette
- `colorRamp` trả về **hàm** ánh xạ [0,1] tới ma trận RGB.
- `colorRampPalette` trả về một **hàm** lấy `n` và trả về `n` màu nội suy.
- `space = "Lab"` mang lại phép nội suy thống nhất về mặt nhận thức hơn `"rgb"`.
---
## bảng màu / recordPlot
- `palette()` trả về bảng màu hiện tại (8 màu mặc định). `palette("Set1")` đặt bảng màu tích hợp sẵn.
- Số nguyên màu trong ô đánh chỉ mục vào bảng màu (có gói). Chỉ số 0 = màu nền.
- `recordPlot()` / `replayPlot()`: lưu và khôi phục một sơ đồ hoàn chỉnh — phụ thuộc vào thiết bị và dễ hỏng trong các phiên.
FILE:assets/analysis_template.R
# =================================================================
# Mẫu phân tích — Cơ sở R
# Sao chép tệp này, đổi tên và điền thông tin chi tiết của bạn.
# =================================================================
# Tác giả :
# Ngày :
#Dữ liệu:
# Mục đích :
# =================================================================
# ── 0. Thiết lập ──────────────────────── ─────────────────────────
# Xóa môi trường (tùy chọn - nhận xét nếu tải vào phiên hiện có)
rm(danh sách = ls())
# Đặt thư mục làm việc nếu cần
# setwd("/path/to/your/project")
# khả năng tái tạo
set.seed(42)
# Thư viện - bỏ ghi chú những gì bạn cần
# thư viện(haven) # đọc .dta / .sav / .sas
# thư viện (readxl) # đọc tệp Excel
# thư viện (openxlsx) # ghi tệp Excel
# thư viện (nước ngoài) # định dạng Stata / SPSS cũ hơn
# thư viện(khảo sát) # phân tích theo khảo sát
# thư viện (lmtest) # Breusch-Pagan, Durbin-Watson, v.v.
# thư viện(sandwich) # lỗi tiêu chuẩn nghiêm trọng
# thư viện(ô tô) # Loại II/III ANOVA, VIF
# ── 1. Tải dữ liệu ────────────────────── ───────────────────────
df <- read.csv("your_data.csv", stringsAsFactors = FALSE)
# df <- readRDS("your_data.rds")
# df <- Haven::read_dta("your_data.dta")
# Cái nhìn đầu tiên — luôn chạy những cái này
mờ(df)
str(df)
đầu(df, 10)
tóm tắt(df)
# ── 2. Kiểm tra chất lượng dữ liệu ────────────────────────────────────
# Thiếu giá trị
and_report<- data.frame(
cột = tên (df),
n_miss = colSums(is.na(df)),
pct_miss = round(colMeans(is.na(df)) * 100, 1),
row.names = NULL
)
in(na_report[na_report$n_miss > 0, ])
# trùng lặp
n_dup <- sum(trùng lặp(df))
cat(sprintf("Các hàng trùng lặp: %d\n", n_dup))
# Giá trị duy nhất cho các cột phân loại
cat_cols <- tên(df)[sapply(df, function(x) is.character(x) | is.factor(x))]
cho (col trong cat_cols) {
cat(sprintf("\n%s (%d duy nhất):\n", col, length(unique(df[[col]]))))
print(bảng(df[[col]], useNA = "ifany"))
}
# ── 3. Làm sạch & Biến đổi ─────────────────────────────────────
# Đổi tên cột (ví dụ)
# tên(df)[names(df) == "old_name"] <- "new_name"
# Chuyển đổi loại
# df$group <- as.factor(df$group)
# df$date <- as.Date(df$date, format = "%Y-%m-%d")
# Mã hóa lại giá trị (ví dụ)
# df$gender <- ifelse(df$gender == 1, "Nam", "Nữ")
# Tạo biến mới (ví dụ)
# df$log_ thu nhập <- log(df$thu nhập + 1)
# df$age_group <- cut(df$age,
# ngắt = c(0, 25, 45, 65, Inf),
# nhãn = c("18-25", "26-45", "46-65", "65+"))
# Lọc hàng (ví dụ)
# df <- df[df$year >= 2010, ]
# df <- df[complete.cases(df[, c("outcome", "predictor")]), ]
# Bỏ các mức yếu tố không sử dụng
# df <- mức giảm (df)
# ── 4. Thống kê mô tả ────────────────────────────────
# Tóm tắt bằng số
num_cols <- tên(df)[sapply(df, is.numeric)]
vòng(sapply(df[num_cols], hàm(x) c(
n = sum(!is.na(x)),
trung bình = trung bình(x, na.rm = TRUE),
sd = sd(x, na.rm = TRUE),
trung vị = trung vị(x, na.rm = TRUE),
min = min(x, na.rm = TRUE),
max = max(x, na.rm = TRUE)
)), 3)
# bảng chéo
# bảng(df$group, df$category, useNA = "ifany")
# prop.table(table(df$group, df$category), lề = 1) # tỷ lệ hàng
# ── 5. Trực quan hóa (EDA) ───────────────────────────────────
par(mfrow = c(2, 2))
# Biểu đồ kết quả chính
lịch sử(df$outcome_var,
main = "Phân phối kết quả",
xlab = "Kết quả",
col = "xanh thép",
viền = "màu trắng",
nghỉ = 30)
# Boxplot theo nhóm
boxplot(outcome_var ~ group_var,
dữ liệu = df,
main = "Kết quả theo nhóm",
col = "màu vàng nhạt",
las = 2)
# Âm mưu phân tán
cốt truyện(df$predictor, df$outcome_var,
main = "Dự đoán vs kết quả",
xlab = "Dự đoán",
ylab = "Kết quả",
pch = 19,
col = adjustmentcolor("steelblue", alpha.f=0.5),
cex = 0,8)
abline(lm(outcome_var ~ dự đoán, data = df),
col = "đỏ", lwd = 2)
# Ma trận tương quan (chỉ cột số)
cor_mat <- cor(df[num_cols], use = "complete.obs")
hình ảnh (cor_mat,
main = "Ma trận tương quan",
col = hcl.colors(20, "RdBu", rev = TRUE))
par(mfrow = c(1, 1))
# ── 6. Phân tích ─────────────────────── ────────────────────────
# ·· 6a. So sánh phương tiện ··
t.test(outcome_var ~ group_var, data = df)
# ·· 6b. Hồi quy tuyến tính ··
phù hợp <- lm(outcome_var ~ dự đoán1 + dự đoán2 + nhóm_var,
dữ liệu = df)
Tóm tắt (phù hợp)
giới hạn (phù hợp)
# Kiểm tra VIF xem có đa cộng tuyến không (cần có ô tô)
# xe::vif(phù hợp)
# Lỗi tiêu chuẩn mạnh mẽ (yêu cầu lmtest + sandwich)
# lmtest::coeftest(fit, vcov = sandwich::vcovHC(fit, type = "HC3"))
# ·· 6c. ANOVA ··
# fit_aov <- aov(outcome_var ~ group_var, data = df)
# tóm tắt(fit_aov)
# TukeyHSD(fit_aov)
# ·· 6ngày. Hồi quy logistic (kết quả nhị phân) ··
# fit_logit <- glm(binary_outcome ~ x1 + x2,
# dữ liệu = df,
# family = nhị thức(link = "logit"))
# tóm tắt(fit_logit)
# exp(coef(fit_logit)) # tỷ lệ chênh lệch
# exp(confint(fit_logit)) # HOẶC khoảng tin cậy
# ── 7. Chẩn đoán mẫu ─────────────────────────────────────
par(mfrow = c(2, 2))
cốt truyện (phù hợp)
par(mfrow = c(1, 1))
# Sự bình thường còn lại
shapiro.test(dư lượng(phù hợp))
# Tính đồng nhất (yêu cầu lmtest)
# lmtest::bptest(phù hợp)
# ── 8. Lưu kết quả ────────────────────── ──────────────────────
# Dữ liệu đã được làm sạch
# write.csv(df, "data_clean.csv", row.names = FALSE)
# saveRDS(df, "data_clean.rds")
# Kết quả mô hình hóa thành tệp văn bản
# chìm("results.txt")
# cat("=== Mô hình tuyến tính ===\n")
# in(tóm tắt(phù hợp))
# cat("\n=== Khoảng tin cậy ===\n")
# print(giới hạn(phù hợp))
# bồn rửa()
# Sơ đồ để nộp
# png("figure1_distributions.png", chiều rộng = 1200, chiều cao = 900, res = 150)
# par(mfrow = c(2, 2))
# # ... âm mưu của bạn ...
# par(mfrow = c(1, 1))
#dev.off()
# =================================================================
# KẾT THÚC MẪU
# =================================================================
TẬP TIN:scripts/check_data.R
# check_data.R - Báo cáo chất lượng dữ liệu nhanh cho mọi khung dữ liệu R
# Cách sử dụng: source("check_data.R") sau đó gọi check_data(df)
# Hoặc: source("check_data.R"); check_data(read.csv("yourfile.csv"))
check_data <- function(df, top_n_levels = 8) {
if (!is.data.frame(df)) stop("Đầu vào phải là khung dữ liệu.")
n_row <- nrow(df)
n_col <- ncol(df)
mèo("════════════════════ ══════════════════════\n")
cat(" BÁO CÁO CHẤT LƯỢNG DỮ LIỆU\n")
mèo("════════════════════ ══════════════════════\n")
cat(sprintf(" Hàng: %d Cột: %d\n", n_row, n_col))
mèo("═════════════════════ ═════════════════════\n\n")
# ── 1. Tổng quan về cột ──────────────────────
cat("── TỔNG QUAN VỀ CỘT ────────────────────────\n")
for (col in name(df)) {
x <- df[[col]]
cls <- class(x)[1]
n_na <- sum(is.na(x))
pct <- round(n_th / n_row * 100, 1);
n_uniq <- chiều dài(duy nhất(x[!is.na(x)]))
na_flag <- if (n_na == 0) "" else sprintf(" *** %d NAs (%.1f%%)", n_na, pct);
cat(sprintf(" %-20s %-12s %d duy nhất%s\n",
col, cls, n_uniq, na_flag))
}
# ── 2. Tóm tắt ────────────────
mèo("\n── TÓM TẮT──────────────────
na_counts <- sapply(df, function(x) sum(is.na(x)))
cols_with_na <- na_counts[na_counts > 0]
if (length(cols_with_na) == 0) {
cat("Không thiếu giá trị. \n")
} khác {
cat(sprintf(" Cột có NA: %d của %d\n\n", length(cols_with_na), n_col))
for (col in name(cols_with_na)) {
bar_len <- round(cols_with_na[col] / n_row * 20)
bar <- dán0(rep("█", bar_len), thu gọn = "")
pct_na <- round(cols_with_na[col] / n_row * 100, 1)
cat(sprintf(" %-20s [%-20s] %d (%.1f%%)\n",
col, bar, cols_with_na[col], pct_na))
}
}
# ── 3. Cột số ───────────────────────
num_cols <- tên(df)[sapply(df, is.numeric)]
if (độ dài(num_cols) > 0) {
cat("\n── CÁC CỘT SỐ ────────────────────────\n")
cat(sprintf(" %-20s %8s %8s %8s %8s %8s\n",
"Cột", "Tối thiểu", "Trung bình", "Trung bình", "Tối đa", "SD"))
cat(sprintf(" %-20s %8s %8s %8s %8s %8s\n",
"──────", "───", "────", "──────", "───", "──"))
cho (col trong num_cols) {
x <- df[[col]][!is.na(df[[col]])]
if (length(x) == 0) tiếp theo
cat(sprintf(" %-20s %8.3g %8.3g %8.3g %8.3g %8.3g\n",
màu xanh,
tối thiểu(x), trung bình(x), trung vị(x), max(x), sd(x)))
}
}
# ── 4. Cột yếu tố/ký tự ───────────
cat_cols <- tên(df)[sapply(df, function(x) is.factor(x) | is.character(x))]
if (length(cat_cols) > 0) {
cat("\n── CÁC CỘT PHÂN LOẠI ────────────────────\n")
cho (col trong cat_cols) {
x <- df[[col]]
tbl <- sắp xếp(bảng(x, useNA = "không"), giảm = TRUE)
n_lv <- chiều dài(tbl)
cat(sprintf("\n %s (%d giá trị duy nhất)\n", col, n_lv))
hiển thị <- phút(top_n_levels, n_lv)
cho (i trong seq_len(show)) {
lbl <- tên(tbl)[i]
cnt <- tbl[i]
pct <- round(cnt / n_row * 100, 1)
cat(sprintf(" %-25s %5d (%.1f%%)\n", lbl, cnt, pct))
}
nếu (n_lv > top_n_levels) {
cat(sprintf(" ... và %d cấp độ khác\n", n_lv - top_n_levels))
}
}
}
# ── 5. Hàng trùng lặp ────────────────────────
cat("\n── SAO CHÉP ─────────────────────────────\n")
n_dup <- sum(trùng lặp(df))
nếu (n_dup == 0) {
cat(" Không có hàng trùng lặp.\n")
} khác {
cat(sprintf(" Đã tìm thấy %d hàng trùng lặp (%.1f%% dữ liệu)\n",
n_dup, n_dup / n_row * 100))
}
mèo("\n═══════════════════ ═══════════════════════\n")
cat(" KẾT THÚC BÁO CÁO\n")
mèo("════════════════════ ══════════════════════\n")
# Trả về ẩn để sử dụng theo chương trình
vô hình(danh sách(
dims = c(hàng = n_row, cols = n_col),
na_counts = na_counts,
n_dupes = n_dup
))
}
TẬP TIN:scripts/scaffold_analysis.R
#!/usr/bin/env Bản ghi
# giàn giáo_analysis.R - Tạo tập lệnh phân tích khởi đầu
#
# Cách sử dụng (từ thiết bị đầu cuối):
# Rscript giàn giáo_analysis.R myproject
# Rscript giàn giáo_analysis.R myproject result_var group_var
#
# Cách sử dụng (từ bảng điều khiển R):
# nguồn("scaffold_analysis.R")
# giàn giáo_analysis("myproject", kết quả = "điểm", nhóm = "điều trị")
#
# Đầu ra: myproject_analysis.R (sẵn sàng chỉnh sửa)
giàn giáo_analysis <- chức năng (project_name,
kết quả = "kết quả",
nhóm = "nhóm",
data_file = NULL) {
if (is.null(data_file)) data_file <- dán0(project_name, ".csv")
out_file <- dán0(project_name, "_analysis.R")
mẫu <- chạy nước rút(
'# =================================================================
# Dự án : %s
# Đã tạo: %s
# =================================================================
# ── 0. Thư viện ────────────────────── ───────────────────────
# Thêm gói bạn cần vào đây
# thư viện(ggplot2)
# thư viện(haven) # cho file .dta
# thư viện (openxlsx) # cho đầu ra Excel
# ── 1. Tải dữ liệu ────────────────────── ───────────────────────
df <- read.csv("%s", stringsAsFactors = FALSE)
# Kiểm tra nhanh — luôn thực hiện việc này trước
cat("Kích thước:", dim(df), "\\n")
str(df)
đầu(df)
# ── 2. Khám phá / EDA ──────────────────── ─────────────────────
tóm tắt(df)
# Đã kiểm tra
na_counts <- colSums(is.na(df))
na_counts[na_counts > 0]
# Phân phối biến chính
hist(df$%s, main = "Phân phối của %s", xlab = "%s")
if ("%s" %%in%% tên(df)) {
bảng(df$%s)
barplot(bảng(df$%s),
main = "Đếm theo %s",
col = "xanh thép",
las = 2)
}
# ── 3. Làm sạch/Biến đổi ──────────────────────────────────────
# df <- df[complete.cases(df), ] # thả hàng với bất kỳ NA nào
# df$%s <- as.factor(df$%s) # chuyển đổi thành hệ số
# ── 4. Phân tích ─────────────────────── ────────────────────────
# Thống kê mô tả theo nhóm
tapply(df$%s, df$%s, trung bình, na.rm = TRUE)
tapply(df$%s, df$%s, sd, na.rm = TRUE)
# t-test (hai nhóm)
# t.test(%s ~ %s, data = df)
# Mô hình tuyến tính
phù hợp <- lm(%s ~ %s, data = df)
Tóm tắt (phù hợp)
giới hạn (phù hợp)
# ANOVA (nhiều nhóm)
# fit_aov <- aov(%s ~ %s, data = df)
# tóm tắt(fit_aov)
# TukeyHSD(fit_aov)
# ── 5. Trực quan hóa kết quả ──────────────────────────────────────
par(mfrow = c(1, 2))
# Boxplot theo nhóm
boxplot(%s ~ %s,
dữ liệu = df,
main = "%s bởi %s",
xlab = "%s",
ylab = "%s",
col = "màu vàng nhạt")
# Chẩn đoán mô hình
cốt truyện (phù hợp, which = 1) # phần dư so với phần phù hợp
par(mfrow = c(1, 1))
# ── 6. Lưu kết quả ────────────────────── ──────────────────────
# Lưu dữ liệu đã được làm sạch
# write.csv(df, "%s_clean.csv", row.names = FALSE)
# Lưu tóm tắt mô hình vào văn bản
# chìm("%s_results.txt")
# tóm tắt(phù hợp)
# bồn rửa()
# Lưu đồ thị vào tập tin
# png("%s_boxplot.png", chiều rộng = 800, chiều cao = 600, res = 150)
# boxplot(%s ~ %s, data = df, col = "light yellow")
#dev.off()
',
tên_dự án,
format(Sys.Date(), "%%Y-%%m-%%d"),
dữ liệu_file,
# Phần 2 - EDA
kết quả, kết quả, kết cục,
nhóm, nhóm, nhóm, nhóm,
# Mục 3
nhóm, nhóm,
# Mục 4
nhóm,
nhóm,
nhóm,
nhóm,
nhóm,
nhóm,
# Mục 5
nhóm,
nhóm,
nhóm, kết quả,
# Mục 6
tên_dự án, tên_dự án, tên_dự án,
kết quả, nhóm
)
writeLines(mẫu, out_file)
cat(sprintf("Đã tạo: %s\n", out_file))
vô hình(out_file)
}
# ── Chạy từ dòng lệnh ─────────────────────────────────────
nếu (! tương tác()) {
args <- commandArgs(trailingOnly = TRUE)
if (độ dài (args) == 0) {
cat("Cách sử dụng: Rscript giàn giáo_analysis.R <project_name> [outcome_var] [group_var]\n")
cat("Ví dụ: Rscript Scaffold_analysis.R Xử lý điểm myproject\n")
thoát (trạng thái = 1)
}
dự án <- args[1]
kết quả <- if (length(args) >= 2) args[2] khác "kết quả"
nhóm <- if (length(args) >= 3) args[3] "nhóm" khác
giàn giáo_analysis(dự án, kết quả = kết quả, nhóm = nhóm)
}
TẬP TIN:README.md
# kỹ năng cơ bản
GitHub: https://github.com/iremaydas/base-r-skill
Kỹ năng Mã Claude để lập trình cơ sở R.
---
##Câu chuyện
Tôi là một ứng cử viên tiến sĩ khoa học chính trị, người thường xuyên sử dụng R nhưng sẽ không bao giờ gọi mình là *người R*. Tôi cần một kỹ năng Mã Claude cho cơ sở R - thứ gì đó không có gọn gàng, không có ggplot2, chỉ đơn giản là R - và tôi không thể tìm thấy ở đâu cả.
Vì vậy, tôi đã tự làm một cái. Lúc 11 giờ đêm. Nhờ Claude giúp tôi xây dựng kỹ năng cho Claude.
Nếu bạn cũng là người thường xuyên sử dụng Google `how to drop NA rows in R` thì đây là dành cho bạn. 🫶
---
## Có gì bên trong
```
base-r/
├── SKILL.md # Main skill file
├── references/ # Gotchas & non-obvious behaviors
│ ├── data-wrangling.md # Subsetting traps, apply family, merge, factor quirks
│ ├── modeling.md # Formula syntax, lm/glm/aov/nls, optim
│ ├── statistics.md # Hypothesis tests, distributions, clustering
│ ├── visualization.md # par, layout, devices, colors
│ ├── io-and-text.md # read.table, grep, regex, format
│ ├── dates-and-system.md # Date/POSIXct traps, options(), file ops
│ └── misc-utilities.md # tryCatch, do.call, time series, utilities
├── scripts/
│ ├── check_data.R # Quick data quality report for any data frame
│ └── scaffold_analysis.R # Generates a starter analysis script
└── assets/
└── analysis_template.R # Copy-paste analysis template
```
Các tệp tham chiếu được cô đọng từ hướng dẫn sử dụng R 4.5.3 chính thức — **19.518 dòng → 945 dòng** (giảm 95%). Chỉ còn lại những thứ không rõ ràng: lỗi lầm, những mặc định đáng ngạc nhiên, những tương tác phức tạp. Những điều Claude đã biết rõ đã bị cắt bỏ.
---
## Cách sử dụng
Thêm kỹ năng này vào thiết lập Mã Claude của bạn bằng cách trỏ tới kho lưu trữ này. Sau đó, Claude sẽ tự động tải các tệp tham chiếu có liên quan khi bạn thực hiện các tác vụ R.
Hoạt động tốt nhất cho:
- Thao tác dữ liệu Base R (không có gọn gàng)
- Lập mô hình thống kê với `lm`, `glm`, `aov`
- Đồ họa cơ bản với `plot`, `par`, `barplot`
- Hiểu lý do tại sao mã R của bạn lại làm điều kỳ lạ đó
Không dành cho: phát triển gói gọn gàng, ggplot2, Shiny hoặc R.
---
## Tập lệnh `check_data.R`
Có lẽ là thứ độc lập hữu ích nhất ở đây. Tìm nguồn và chạy `check_data(df)` trên bất kỳ khung dữ liệu nào để nhận báo cáo được định dạng về thứ nguyên, số lượng NA, tóm tắt bằng số và phân tích theo danh mục.
```r
source("scripts/check_data.R")
check_data(your_df)
```
---
## Được xây dựng với sự trợ giúp từ
- Claude (rõ ràng rồi)
- Hướng dẫn sử dụng R chính thức (tất cả 19.518 dòng)
- Thất vọng nhẹ và vài tách cà phê
---
##Đóng góp
Nếu bạn phát hiện ra thiếu sót, một mặc định sai hoặc điều gì đó đáng lẽ phải có trong tài liệu tham khảo - PR rất được hoan nghênh. Tôi cũng đang học.
---
*Được tạo bởi [@iremaydas](https://github.com/iremaydas) — Ứng viên tiến sĩ, người dùng R không thường xuyên, nhân viên Google toàn thời gian về những điều mà có lẽ tôi nên biết vào lúc này.*