cv.cm

Lập trình · Ngôn ngữ lập trình

Học lập trình R cơ bản cho người mới bắt đầu

7 phút đọc

Trả lời nhanh

R là ngôn ngữ và môi trường miễn phí cho thống kê, phân tích dữ liệu và đồ họa. Ý tưởng cốt lõi là vector hóa: các phép toán áp dụng lên toàn bộ vector và cột của data frame cùng lúc, nên mã phân tích rất ngắn gọn. Trang này trình bày cài đặt R, chạy script, vector và kiểu dữ liệu, cấu trúc điều khiển, hàm, list và data frame, mô hình thống kê, vẽ biểu đồ và xử lý lỗi.

R là gì và dùng để làm gì

R là ngôn ngữ và môi trường mã nguồn mở, miễn phí cho tính toán thống kê và đồ họa. R bắt nguồn từ ngôn ngữ S do Bell Labs phát triển và do R Core Team duy trì. R được vector hóa: hầu hết phép toán làm việc trên toàn bộ vector dữ liệu cùng lúc, giúp mã phân tích dữ liệu ngắn gọn.

R được các nhà thống kê, nhà khoa học dữ liệu, chuyên gia tin sinh học, nhà kinh tế và nhà nghiên cứu sử dụng để làm sạch dữ liệu, xây dựng mô hình thống kê, trực quan hóa và tạo báo cáo có thể tái lập. Hàng nghìn gói bổ sung có sẵn trên CRAN (Comprehensive R Archive Network) và Bioconductor.

Cài đặt R và chạy Hello, world

Tải R từ CRAN cho Windows, macOS hoặc Linux. Nhiều người còn cài RStudio hoặc Positron, là các IDE có trình soạn thảo, console, khung xem biểu đồ và khung trợ giúp. Bạn có thể gõ mã trực tiếp trong console R hoặc lưu vào tệp .R.

# hello.R
print("Hello, world!")
cat("Hello, world!\n")
Rscript hello.R
# [1] "Hello, world!"
# Hello, world!

print hiển thị giá trị giống như console, kèm tiền tố chỉ mục [1]. cat ghi văn bản thuần, nên bạn tự thêm ký tự xuống dòng.

Biến, kiểu cơ bản và vector

Gán bằng <- (phong cách quen dùng) hoặc =. R không có giá trị vô hướng: một số đơn là vector độ dài 1. c() gộp các giá trị thành vector, và phép toán số học áp dụng theo từng phần tử.

x <- 42                 # numeric (double)
n <- 7L                 # integer (L suffix)
name <- "Ada"           # character
ok <- TRUE              # logical
class(x); class(n); class(name)   # "numeric" "integer" "character"
v <- c(2, 4, 6, 8)
v * 10                  # [1] 20 40 60 80
v[2]                    # [1] 4   (indexing starts at 1)
v[v > 4]                # [1] 6 8
length(v); sum(v); mean(v)        # 4 20 5
1:5                     # [1] 1 2 3 4 5
seq(0, 1, by = 0.25)    # [1] 0.00 0.25 0.50 0.75 1.00
KiểuVí dụGhi chú
numeric (double)3.14, 42mặc định cho số
integer42Lsố nguyên, có hậu tố L
character"text"chuỗi
logicalTRUE, FALSENA nghĩa là giá trị bị thiếu
factorfactor(c("lo", "hi"))dữ liệu phân loại với các mức cố định

Cấu trúc điều khiển

R có if/else, for, while và repeat. Với vector, hàm vector hóa ifelse() thường tốt hơn vòng lặp.

temp <- 25
if (temp > 30) {
  print("hot")
} else if (temp > 15) {
  print("mild")         # [1] "mild"
} else {
  print("cold")
}
for (i in 1:3) {
  cat("step", i, "\n")  # step 1 / step 2 / step 3
}
scores <- c(45, 80, 62)
ifelse(scores >= 50, "pass", "fail")
# [1] "fail" "pass" "pass"

if cần một giá trị TRUE hoặc FALSE duy nhất. Truyền vector dài hơn vào if là lỗi từ R 4.2 trở đi; hãy dùng any(), all() hoặc ifelse().

Hàm

Hàm được tạo bằng function và gán cho một tên. Biểu thức được tính cuối cùng được trả về tự động; return() chỉ cần khi thoát sớm. Đối số có thể có giá trị mặc định và có thể truyền theo tên.

bmi <- function(weight_kg, height_m = 1.75) {
  weight_kg / height_m^2
}
bmi(70)                          # [1] 22.85714
bmi(height_m = 1.6, weight_kg = 60)  # [1] 23.4375
square <- function(x) x^2
square(1:4)                      # [1] 1 4 9 16 (vectorized)
sapply(c(1, 4, 9), sqrt)         # [1] 1 2 3
(\(x) x + 1)(10)                 # [1] 11 (short lambda syntax)

Cú pháp lambda ngắn \(x) có từ R 4.1, cùng với pipe gốc |> truyền vế trái làm đối số đầu tiên: c(1, 4, 9) |> sqrt() |> sum() trả về 6.

Cấu trúc dữ liệu cốt lõi: vector, list và data frame

Ngoài vector nguyên tử, R còn có list (chứa được các giá trị khác kiểu), ma trận và data frame. Data frame là bảng mà mỗi cột là một vector cùng độ dài; đây là cấu trúc trung tâm của phân tích dữ liệu.

person <- list(name = "Ann", age = 31, langs = c("R", "SQL"))
person$name                 # [1] "Ann"
person[["langs"]][2]        # [1] "SQL"
df <- data.frame(
  name  = c("Ann", "Bo", "Cy"),
  age   = c(31, 25, 40),
  city  = c("Oslo", "Rome", "Oslo")
)
nrow(df)                    # [1] 3
df$age                      # [1] 31 25 40
df[df$age > 30, "name"]     # [1] "Ann" "Cy"
df$senior <- df$age >= 40   # add a column
aggregate(age ~ city, data = df, FUN = mean)
#   city  age
# 1 Oslo 35.5
# 2 Rome 25.0
str(df)                     # compact structure summary

df[rows, columns] chọn theo vị trí, tên hoặc điều kiện logic. Để trống một vế, như df[1, ], nghĩa là tất cả hàng hoặc tất cả cột.

Thống kê và vẽ biểu đồ

Các hàm thống kê có sẵn: summary, sd, quantile, cor, t.test và lm (mô hình tuyến tính), cùng nhiều hàm khác. Đồ họa cơ bản vẽ biểu đồ chỉ bằng một lệnh gọi.

set.seed(1)
x <- 1:20
y <- 3 * x + rnorm(20, sd = 2)
model <- lm(y ~ x)
round(coef(model), 2)       # intercept near 0, slope near 3
summary(model)$r.squared    # close to 1
plot(x, y, main = "y vs x")
abline(model, col = "red")

Cú pháp công thức y ~ x nghĩa là “mô hình hóa y như một hàm của x” và được dùng trong nhiều hàm xây dựng mô hình. Với biểu đồ nâng cao và xử lý dữ liệu, hầu hết người dùng cài các gói tidyverse, như ggplot2 và dplyr, bằng install.packages("tidyverse").

Xử lý lỗi

Phát sinh lỗi bằng stop() và cảnh báo bằng warning(). Bắt chúng bằng tryCatch(), hàm nhận các hàm xử lý cho error, warning và một khối finally tùy chọn.

safe_log <- function(x) {
  if (!is.numeric(x)) stop("x must be numeric")
  if (any(x <= 0)) warning("non-positive values give NaN or -Inf")
  log(x)
}
result <- tryCatch(
  safe_log("ten"),
  error = function(e) {
    message("Caught: ", conditionMessage(e))
    NA
  },
  finally = message("done")
)
# Caught: x must be numeric
# done
result                      # [1] NA

Một chương trình hoàn chỉnh nhỏ: tổng hợp doanh số

Script này tạo một bảng doanh số nhỏ, tính doanh thu theo khu vực bằng R cơ bản và in ra khu vực tốt nhất.

sales <- data.frame(
  region = c("North", "South", "North", "East", "South"),
  units  = c(10, 4, 6, 8, 12),
  price  = c(2.5, 3.0, 2.5, 4.0, 3.0)
)
sales$revenue <- sales$units * sales$price
by_region <- aggregate(revenue ~ region, data = sales, FUN = sum)
by_region <- by_region[order(-by_region$revenue), ]
print(by_region, row.names = FALSE)
#  region revenue
#   South      48
#   North      40
#    East      32
best <- by_region$region[1]
cat(sprintf("Best region: %s (%.2f)\n", best, max(by_region$revenue)))
# Best region: South (48.00)

Học tiếp ở đâu

  • An Introduction to R, sổ tay chính thức trên CRAN.
  • Trợ giúp tích hợp sẵn: gõ ?mean hoặc help("lm") trong console.
  • R for Data Science của Hadley Wickham và cộng sự, miễn phí trực tuyến, theo hướng tidyverse.
  • CRAN Task Views, liệt kê các gói theo lĩnh vực như kinh tế lượng hoặc học máy.

Câu hỏi thường gặp

Phân tích dữ liệu nên dùng R hay Python?

Cả hai đều mạnh. R có kho phương pháp thống kê sâu rộng và vẽ biểu đồ xuất sắc, phổ biến trong học thuật và thống kê sinh học; Python đa dụng hơn và chiếm ưu thế trong kỹ thuật học máy. Nhiều nhà phân tích học cả hai.

<- và = trong R khác nhau thế nào?

Cả hai đều gán ở cấp cao nhất, và <- là phong cách quen dùng. Bên trong lời gọi hàm, = đặt tên cho đối số, nên f(x = 1) truyền một đối số chứ không tạo biến.

Vì sao R đếm từ 1?

R theo quy ước toán học và thống kê, như tiền thân S, nên phần tử đầu tiên của vector là v[1]. Chỉ mục 0 trả về vector rỗng chứ không báo lỗi.

Tidyverse là gì?

Tidyverse là tập hợp các gói R, gồm dplyr, ggplot2 và tidyr, có thiết kế nhất quán để nhập, làm sạch, biến đổi và vẽ biểu đồ dữ liệu.

Làm sao cài một gói R?

Chạy install.packages("name") một lần để tải từ CRAN, rồi library(name) trong mỗi phiên để nạp.

Tất cả hướng dẫn lập trình