###Tính toán tương tự như Excel CỘNG TRỪ NHÂN CHIA:
12 + 1
## [1] 13
12 - 1
## [1] 11
12 / 1
## [1] 12
12 * 1
## [1] 12
###Lũy thừa:
12^3
## [1] 1728
12**3
## [1] 1728
13 %% 3 # phần dư
## [1] 1
13 %/% 3 # phần nguyên
## [1] 4
Tạo Biến
x <- 2
print(x)
## [1] 2
y <- 2 * x + 1
y
## [1] 5
Hàm và phép toán học cơ bản
abs(x) # Trị tuyệt đối
## [1] 2
exp(10) # e^10 (hàm mũ cơ số e)
## [1] 22026.47
sqrt(9) # Căn bậc hai
## [1] 3
log(10) # Log tự nhiên (nepe)
## [1] 2.302585
log(exp(10)) # log(e^10)
## [1] 10
log(10, base = 10) # Log cơ số 10
## [1] 1
round(2.345, digits = 1) # Làm tròn 1 chữ số thập phân
## [1] 2.3
floor(2.5) # Làm tròn xuống
## [1] 2
ceiling(2.345) # Làm tròn lên
## [1] 3
R có bốn kiểu dữ liệu cơ bản:
numeric (double): số thực
integer: số nguyên
character: chuỗi ký tự
logical: giá trị TRUE/FALSE
factor: dữ liệu phân loại (categorical) e ### 3.1 Numeric
my_numeric <- 42.2
typeof(my_numeric)
## [1] "double"
y <- 5L
typeof(y)
## [1] "integer"
my_character <- "universe"
typeof(my_character)
## [1] "character"
a <- TRUE
b <- (5 > 2)
sum(c(TRUE, FALSE, TRUE)) # TRUE=1, FALSE=0
## [1] 2
my_logical_1 <- FALSE
my_logical_2 <- TRUE
typeof(my_logical_1)
## [1] "logical"
Factor là dạng dữ liệu dùng để biểu diễn các nhóm, loại, có thể được sắp thứ tự hoặc không.
# Tạo vector và chuyển sang factor
gender_vector <- c("M", "F", "F", "M", "M")
gender_factor <- factor(gender_vector, levels = c("F", "M"))
levels(gender_factor)
## [1] "F" "M"
# Đổi nhãn levels
levels(gender_factor) <- c("Female", "Male")
table(gender_factor)
## gender_factor
## Female Male
## 2 3
Ví dụ khác:
vector_month <- c(9, 2, 6, 5, 6, 8, 9)
table(vector_month)
## vector_month
## 2 5 6 8 9
## 1 1 2 1 2
factor(vector_month, levels = 1:10)
## [1] 9 2 6 5 6 8 9
## Levels: 1 2 3 4 5 6 7 8 9 10
tìm dạng dữ liệu
typeof(x)
## [1] "double"
class(x)
## [1] "numeric"
mode(x)
## [1] "numeric"
Ép kiểu dữ liêu
#Ép kiểu: as.numeric(), as.integer(), as.character(), as.logical(), factor().
Qua tài liệu này, bạn đã làm quen với:
Các phép toán cơ bản trong R
Các kiểu dữ liệu chính
Cách sử dụng factor cho dữ liệu phân loại
Từ đây, bạn có thể mở rộng sang vector, matrix, data frame (Các kiểu dữ liệu có cấu trúc ) và hàm trong R.
Vector là tập hợp các giá trị có cùng kiểu dữ liệu (numeric, character, logical…).
Tạo các vector cơ bản
numeric_vector <- c(1, 10, 49)
character_vector <- c("a", "b", "c")
boolean_vector <- c(TRUE, FALSE, TRUE)
#nang cao
range1 = 1:100
print(range1)
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
## [19] 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
## [37] 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
## [55] 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
## [73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
## [91] 91 92 93 94 95 96 97 98 99 100
v <- seq(from = 1, by = 3, length.out = 100)
v2 <- 1 + (0:99) * 3
Lưu ý: nếu trộn kiểu, R sẽ tự chuyển về kiểu
“character”
character_vector <- c("a", 123, "b")
character_vector
## [1] "a" "123" "b"
Các phép toán thực hiện từng phần tử tương ứng.
num1 <- c(1, 2, 3, 4)
num2 <- 10:13
# Cộng hai vector
total <- num1 + num2
print(total)
## [1] 11 13 15 17
# Nhân hai vector
multiply <- num1 * num2
print(multiply)
## [1] 10 22 36 52
# Ghép hai vector
all_num <- c(num1, num2)
print(all_num)
## [1] 1 2 3 4 10 11 12 13
# Tính tổng
sum_num1 <- sum(num1)
sum_num1
## [1] 10
# Độ dài vector
len_num1 <- length(num1)
len_num1
## [1] 4
# Help cho các hàm
?sum
## starting httpd help server ... done
?length
# Tính tổng có và không bỏ qua giá trị NA
sum(c(1, 2, 3, 4, NA)) # Không bỏ qua NA
## [1] NA
sum(c(1, 2, 3, 4, NA), na.rm = TRUE) # Bỏ qua NA
## [1] 10
# Dùng dấu :
range1 <- 1:100
head(range1)
## [1] 1 2 3 4 5 6
# Dùng hàm vector()
vector("numeric", length = 10) # tạo vector rỗng gồm 10 phần tử số
## [1] 0 0 0 0 0 0 0 0 0 0
# Dùng hàm seq()
range2 <- seq(1, 100, by = 1)
range3 <- seq(100, 1, by = -1)
range4 <- seq(100, 1, length.out = 50)
head(range4)
## [1] 100.00000 97.97959 95.95918 93.93878 91.91837 89.89796
rep1 <- rep(c(1, 2, 3), 5)
rep1
## [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
x <- c(2, 3, 4, 6, 7, 1)
sort(x) # tăng dần (mặc định)
## [1] 1 2 3 4 6 7
sort(x, decreasing = TRUE) # giảm dần
## [1] 7 6 4 3 2 1
num1 <- c(1, 2, 3, 4)
num1[3] # phần tử thứ 3
## [1] 3
num1[c(1, 4, 2)] # chọn phần tử 1, 4, 2
## [1] 1 4 2
num1[3:length(num1)] # chọn từ phần tử thứ 3 đến hết
## [1] 3 4
# dữ liệu doanhthu
doanhthu <- c(100, 250, 350)
names(doanhthu) <- c("tháng 1", "tháng 2", "tháng 3")
doanhthu
## tháng 1 tháng 2 tháng 3
## 100 250 350
# Xem tên phần tử
attributes(doanhthu)
## $names
## [1] "tháng 1" "tháng 2" "tháng 3"
names(doanhthu)
## [1] "tháng 1" "tháng 2" "tháng 3"
# Truy xuất theo tên ban đầu
doanhthu["tháng 1"]
## tháng 1
## 100
# Đổi tên (nếu cần)
names(doanhthu) <- c("m1", "m2", "m3")
doanhthu
## m1 m2 m3
## 100 250 350
# Sau khi đổi tên, truy xuất theo tên mới
doanhthu["m1"]
## m1
## 100
# tạo vector logic (ví dụ)
BB <- vector(mode = "logical", length = 100)
# --- ĐỊNH NGHĨA/KHỞI TẠO m4 trước khi sử dụng ---
m4 <- 4 # ví dụ: gán m4 là một số; hoặc m4 <- c(2,3,4) nếu muốn vector
# Hàm kiểm chẵn lẻ (sử dụng tham số rõ ràng và an toàn)
check_even_odd <- function(x) {
if (!is.numeric(x)) stop("Tham số phải là số (numeric).")
# xử lý vector hoặc scalar: trả về chuỗi mô tả cho mỗi phần tử
sapply(x, function(v) {
if (is.na(v)) return(NA)
if (v %% 2 == 0) {
paste(v, "là số chẵn")
} else {
paste(v, "là số lẻ")
}
})
}
# Thử chạy
check_even_odd(m4) # với m4 = 4 -> "4 là số chẵn"
## [1] "4 là số chẵn"
check_even_odd(c(2,3,5)) # test vector
## [1] "2 là số chẵn" "3 là số lẻ" "5 là số lẻ"
BB <- vector(mode = "logical", length = 100)
head(BB)
## [1] FALSE FALSE FALSE FALSE FALSE FALSE
check_even_odd <- function(m4) {
if (m4 %% 2 == 0) {
return(paste(m4, "là số chẵn"))
} else {
return(paste(m4, "là số lẻ"))
}
}
# Thử nghiệm
check_even_odd(5)
## [1] "5 là số lẻ"
check_even_odd(10)
## [1] "10 là số chẵn"
Matrix là một dạng dữ liệu có dạng ma trận kích thước m x n. Trong đó m là số dòng, n là số cột. Các dòng và các cột của một matrix phải cùng kiểu dữ liệu.
Cú pháp chung tạo một matrix:
# --- Tạo dữ liệu nguồn (không dùng tên trùng hàm) ---
vals <- 1:12 # vector dữ liệu
nrow_val <- 3 # số hàng
ncol_val <- 4 # số cột
# Tạo tên cho hàng và cột (tùy chọn)
rownames_vec <- paste0("R", 1:nrow_val) # c("R1","R2","R3")
colnames_vec <- paste0("C", 1:ncol_val) # c("C1","C2","C3","C4")
# Tạo ma trận theo cột (mặc định byrow = FALSE)
m_col <- matrix(vals,
nrow = nrow_val,
ncol = ncol_val,
byrow = FALSE,
dimnames = list(rownames_vec, colnames_vec))
m_col
## C1 C2 C3 C4
## R1 1 4 7 10
## R2 2 5 8 11
## R3 3 6 9 12
# Tạo ma trận theo hàng (byrow = TRUE)
m_row <- matrix(vals,
nrow = nrow_val,
ncol = ncol_val,
byrow = TRUE,
dimnames = list(rownames_vec, colnames_vec))
m_row
## C1 C2 C3 C4
## R1 1 2 3 4
## R2 5 6 7 8
## R3 9 10 11 12
Ví dụ:
# Tạo matrix 3x4
y <- matrix(1:12, nrow = 3, ncol = 4)
print(y)
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
Tạo matrix từ các vector:
cells <- c(12, 3, 45, 2)
rnames <- c("R1", "R2")
cnames <- c("C1", "C2")
mymatrix1 <- matrix(cells, nrow = 2, ncol = 2, byrow = TRUE,
dimnames = list(rnames, cnames))
mymatrix1 # byrow = TRUE: đánh số thứ tự theo dòng
## C1 C2
## R1 12 3
## R2 45 2
mymatrix2 <- matrix(cells, nrow = 2, ncol = 2, byrow = FALSE,
dimnames = list(rnames, cnames))
mymatrix2 # byrow = FALSE: đánh số thứ tự theo cột
## C1 C2
## R1 12 45
## R2 3 2
Tạo matrix từ data frame:
df <- data.frame(seq(1, 5, 1), seq(2, 6, 1))
colnames(df) <- c("x", "y")
mymatrix3 <- as.matrix(df)
mymatrix3
## x y
## [1,] 1 2
## [2,] 2 3
## [3,] 3 4
## [4,] 4 5
## [5,] 5 6
Truy xuất phần tử: matrix[dòng, cột]
# Lấy phần tử cột thứ nhất
mymatrix3[, 1]
## [1] 1 2 3 4 5
# Lấy dòng thứ 2 và 3 (tương đương mymatrix3[2:3, ])
mymatrix3[c(2, 3), ]
## x y
## [1,] 2 3
## [2,] 3 4
# Lấy phần tử tại dòng 2, cột 1
mymatrix3[2, 1]
## x
## 2
# Lấy các dòng 2-3 và cột 1-2
mymatrix3[2:3, 1:2]
## x y
## [1,] 2 3
## [2,] 3 4
# Nhân ma trận với một số
mymatrix3 * 2
## x y
## [1,] 2 4
## [2,] 4 6
## [3,] 6 8
## [4,] 8 10
## [5,] 10 12
mymatrix3 ^ 2
## x y
## [1,] 1 4
## [2,] 4 9
## [3,] 9 16
## [4,] 16 25
## [5,] 25 36
#Chuyển vị ma trận
mymatrix3_t <- t(mymatrix3)
mymatrix3_t
## [,1] [,2] [,3] [,4] [,5]
## x 1 2 3 4 5
## y 2 3 4 5 6
# Nhân hai ma trận
y <- matrix(1:12, nrow = 3, ncol = 4)
z <- matrix(12:24, nrow = 4, ncol = 3)
## Warning in matrix(12:24, nrow = 4, ncol = 3): data length [13] is not a
## sub-multiple or multiple of the number of rows [4]
mul <- y %*% z
mul # Ma trận kết quả có kích thước 3x3
## [,1] [,2] [,3]
## [1,] 312 400 488
## [2,] 366 470 574
## [3,] 420 540 660
List là tập hợp các phần tử có thể có kiểu dữ liệu khác nhau (vector, matrix, số, …).
cơ bản:
my_vector <- 1:10
my_matrix <- matrix(1:9, ncol = 3)
my_num <- 10
#Tạo list không đặt tên
my_list <- list(my_vector, my_matrix, my_num)
Tạo list có đặt tên:
my_list <- list(vector = my_vector,
matrix = my_matrix,
number = my_num)
print(my_list)
## $vector
## [1] 1 2 3 4 5 6 7 8 9 10
##
## $matrix
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
##
## $number
## [1] 10
# Truy xuất bằng chỉ số
my_list[[1]]
## [1] 1 2 3 4 5 6 7 8 9 10
# Truy xuất bằng tên
my_list[["matrix"]]
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
my_list$vector
## [1] 1 2 3 4 5 6 7 8 9 10
Lưu ý:
Dùng [] trả về một list (một phần tử).
Dùng [[]] trả về chính đối tượng đó (với kiểu dữ liệu gốc).
class(my_list["matrix"]) # list
## [1] "list"
class(my_list[["matrix"]]) # matrix
## [1] "matrix" "array"
List có thể chứa một list khác:
my_list2 <- list(list = my_list,
matrix = my_matrix)
my_list2[["matrix"]]
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
Gộp hai list:
my_list_3 <- append(my_list, my_list2)
print(my_list_3)
## $vector
## [1] 1 2 3 4 5 6 7 8 9 10
##
## $matrix
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
##
## $number
## [1] 10
##
## $list
## $list$vector
## [1] 1 2 3 4 5 6 7 8 9 10
##
## $list$matrix
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
##
## $list$number
## [1] 10
##
##
## $matrix
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
Hoặc dùng
my_list_4 <- c(my_list, my_list2)
my_list_4
## $vector
## [1] 1 2 3 4 5 6 7 8 9 10
##
## $matrix
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
##
## $number
## [1] 10
##
## $list
## $list$vector
## [1] 1 2 3 4 5 6 7 8 9 10
##
## $list$matrix
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
##
## $list$number
## [1] 10
##
##
## $matrix
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
Thêm phần tử vào list:
my_list[['number2']] <- 123
print(my_list)
## $vector
## [1] 1 2 3 4 5 6 7 8 9 10
##
## $matrix
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
##
## $number
## [1] 10
##
## $number2
## [1] 123
Xóa phần tử khỏi list:
my_list[["matrix"]] <- NULL
print(my_list)
## $vector
## [1] 1 2 3 4 5 6 7 8 9 10
##
## $number
## [1] 10
##
## $number2
## [1] 123
Array về cơ bản tương tự matrix nhưng có thể có nhiều chiều hơn (ví dụ: 3 chiều).
Cú pháp:
# --- Khởi tạo dữ liệu (không dùng tên trùng hàm) ---
vals <- 1:24 # dữ liệu nguồn
nrow_val <- 3 # số hàng
ncol_val <- 4 # số cột
nmatrix_val <- 2 # số ma trận (kênh thứ 3)
# Tên hàng/cột/ma trận (tùy chọn)
rownames_vec <- paste0("R", 1:nrow_val)
colnames_vec <- paste0("C", 1:ncol_val)
matnames_vec <- paste0("M", 1:nmatrix_val)
# Kiểm tra tính đúng kích thước trước khi tạo array
if (prod(c(nrow_val, ncol_val, nmatrix_val)) != length(vals)) {
stop("Kích thước dim không khớp với length(vals). Sửa vals hoặc dim.")
}
# Tạo array an toàn
array_1 <- array(data = vals,
dim = c(nrow_val, ncol_val, nmatrix_val),
dimnames = list(rownames_vec, colnames_vec, matnames_vec))
# In kết quả
array_1
## , , M1
##
## C1 C2 C3 C4
## R1 1 4 7 10
## R2 2 5 8 11
## R3 3 6 9 12
##
## , , M2
##
## C1 C2 C3 C4
## R1 13 16 19 22
## R2 14 17 20 23
## R3 15 18 21 24
Ví dụ:
v <- c(5, 9, 3, 10, 11, 12, 13, 14, 15)
cnames <- c("C1", "C2", "C3")
rnames <- c("R1", "R2", "R3")
mnames <- c("Matrix1", "Matrix2")
arr <- array(v, dim = c(3, 3, 2),
dimnames = list(rnames, cnames, mnames))
arr
## , , Matrix1
##
## C1 C2 C3
## R1 5 10 13
## R2 9 11 14
## R3 3 12 15
##
## , , Matrix2
##
## C1 C2 C3
## R1 5 10 13
## R2 9 11 14
## R3 3 12 15
Truy xuất phần tử: array[dòng, cột, ma trận]
# Lấy dòng 1 của matrix1
arr[1, , 1]
## C1 C2 C3
## 5 10 13
# Lấy cột 1 của matrix1
arr[, 1, 1]
## R1 R2 R3
## 5 9 3
# Lấy dòng 2 và 3 của matrix2
arr[2:3, , 2]
## C1 C2 C3
## R2 9 11 14
## R3 3 12 15
Tính tổng theo dòng và cột:
# Tổng theo dòng (theo chiều thứ 1)
sum_row <- apply(arr, 1, sum)
sum_row
## R1 R2 R3
## 56 68 60
# Tổng theo cột (theo chiều thứ 2)
sum_column <- apply(arr, 2, sum)
sum_column
## C1 C2 C3
## 34 66 84
Data frame là cấu trúc dữ liệu dạng bảng, mỗi cột có thể có kiểu dữ liệu khác nhau, nhưng cùng một cột thì phải cùng kiểu.
df <- data.frame(id = 1:4,
score = c(9.0, 7.5, 8.2, 6.9),
name = c("A", "B", "C", "D"))
df
## id score name
## 1 1 9.0 A
## 2 2 7.5 B
## 3 3 8.2 C
## 4 4 6.9 D
Kiểm tra cấu trúc, phân tử:
str(df)
## 'data.frame': 4 obs. of 3 variables:
## $ id : int 1 2 3 4
## $ score: num 9 7.5 8.2 6.9
## $ name : chr "A" "B" "C" "D"
dim(df)
## [1] 4 3
head(df)
## id score name
## 1 1 9.0 A
## 2 2 7.5 B
## 3 3 8.2 C
## 4 4 6.9 D
Truy xuất phần tử:
# Truy xuất cột
df$score
## [1] 9.0 7.5 8.2 6.9
df[, 2]
## [1] 9.0 7.5 8.2 6.9
# Lấy subset theo điều kiện
subset(df, score > 8)
## id score name
## 1 1 9.0 A
## 3 3 8.2 C
# Hoặc dùng
my_data_1 <- df[df$score > 8, ]
my_data_1
## id score name
## 1 1 9.0 A
## 3 3 8.2 C
Thống kê cơ bản:
summary(df)
## id score name
## Min. :1.00 Min. :6.90 Length:4
## 1st Qu.:1.75 1st Qu.:7.35 Class :character
## Median :2.50 Median :7.85 Mode :character
## Mean :2.50 Mean :7.90
## 3rd Qu.:3.25 3rd Qu.:8.40
## Max. :4.00 Max. :9.00
Thêm cột/hàng:
# Thêm cột
df$passed <- df$score >= 7.0
df
## id score name passed
## 1 1 9.0 A TRUE
## 2 2 7.5 B TRUE
## 3 3 8.2 C TRUE
## 4 4 6.9 D FALSE
# Thêm hàng
df <- rbind(df, data.frame(id = 5, score = 8.0, name = "E", passed = TRUE))
df
## id score name passed
## 1 1 9.0 A TRUE
## 2 2 7.5 B TRUE
## 3 3 8.2 C TRUE
## 4 4 6.9 D FALSE
## 5 5 8.0 E TRUE
Truy xuất theo dòng, cột:
# Lấy cột thứ 2
df[, 2]
## [1] 9.0 7.5 8.2 6.9 8.0
# Lấy dòng thứ 1
df[1, ]
## id score name passed
## 1 1 9 A TRUE
Xóa dòng/cột:
# Xóa dòng thứ 1
df[-1, ]
## id score name passed
## 2 2 7.5 B TRUE
## 3 3 8.2 C TRUE
## 4 4 6.9 D FALSE
## 5 5 8.0 E TRUE
# Xóa cột thứ 1
df[, -1]
## score name passed
## 1 9.0 A TRUE
## 2 7.5 B TRUE
## 3 8.2 C TRUE
## 4 6.9 D FALSE
## 5 8.0 E TRUE
Cập nhật phần tử:
# Cập nhật phần tử dòng 2, cột 2
df[2, 2] <- 8.0
df
## id score name passed
## 1 1 9.0 A TRUE
## 2 2 8.0 B TRUE
## 3 3 8.2 C TRUE
## 4 4 6.9 D FALSE
## 5 5 8.0 E TRUE
Ví dụ: Lọc dữ liệu
# Tạo data frame mẫu
df <- data.frame(
id = 1:6,
name = c("An", "Bình", "An", "Hà", "Mai", "An"),
score = c(8, 7, 9, 6, 10, 5),
maritalstatus = c("S", "M", "M", "S", "M", "M")
)
# Cách 1: dùng subset
df_an <- subset(df, maritalstatus == "M")
df_an
## id name score maritalstatus
## 2 2 Bình 7 M
## 3 3 An 9 M
## 5 5 Mai 10 M
## 6 6 An 5 M
# Cách 2: dùng indexing
my_data_1 <- df[df$maritalstatus == "M", ]
my_data_1
## id name score maritalstatus
## 2 2 Bình 7 M
## 3 3 An 9 M
## 5 5 Mai 10 M
## 6 6 An 5 M
# Cách 3: dùng dplyr
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
my_data_12 <- df %>%
filter(maritalstatus == "M")
my_data_12
## id name score maritalstatus
## 1 2 Bình 7 M
## 2 3 An 9 M
## 3 5 Mai 10 M
## 4 6 An 5 M