Chuyển đến nội dung chính

Hướng dẫn Utilities trong R

Tìm hiểu một số hàm hữu ích để thao tác cấu trúc dữ liệu, danh sách lồng nhau, biểu thức chính quy và làm việc với thời gian, ngày tháng trong ngôn ngữ lập trình R.
Đã cập nhật 5 thg 10, 2026  · 14 phút đọc

Khám phá cùng AI

ChatGPTClaudePerplexity

Trong hướng dẫn này, bạn sẽ tìm hiểu về một số hàm và tiện ích đơn giản, thường được dùng trong ngôn ngữ lập trình R. Trước hết, chúng ta sẽ bàn về một số hàm liên quan đến toán học. Sau đó, bạn sẽ xem các hàm gắn chặt hơn với cấu trúc dữ liệu của R như thao tác danh sách lồng nhau, biểu thức chính quy, thời gian và ngày tháng.

Các hàm Toán học

Hãy xem các ô mã sau sử dụng một số hàm toán học.

Đầu tiên, bạn sẽ định nghĩa hai vector, x và y, gồm cả giá trị dương và âm.

x <- c(1.1, -2.3, -4.5)
y <- c(2.4,-44, -2.2)
print(x)
[1]  1.1 -2.3 -4.5
print(y)
[1]   2.4 -44.0  -2.2

Giờ hãy lấy hai vector x và y này:

  • Lấy giá trị tuyệt đối của chúng,
  • Làm tròn đến 0 chữ số thập phân,
  • Tính tổng từng cái và
  • Cuối cùng, lấy trung bình của cả hai.
mean(c(sum(round(abs(x))),sum(round(abs(y)))))
27.5

Hãy thử tách dòng mã trên thành các phần nhỏ và soi kỹ từng hàm.

  • Hàm abs() đơn giản là lấy giá trị dương hay giá trị tuyệt đối của các phần tử trong vector x và y.

Ví dụ, khi áp dụng hàm abs() cho x và y, bạn sẽ nhận toàn giá trị dương như bên dưới.

abs(x)
  1. 1.1
  2. 2.3
  3. 4.5
abs(y)
  1. 2.4
  2. 44
  3. 2.2
  • Hàm tiếp theo là round(). Nó chỉ làm tròn đầu vào. Hàm nhận thêm một đối số để bạn chỉ định muốn làm tròn đến bao nhiêu chữ số thập phân. Mặc định, round() làm tròn đến 0 chữ số thập phân.

Ví dụ, sau khi áp dụng round() cho các vector x và y, đầu ra sẽ như sau:

round(x)
  1. 1
  2. -2
  3. -4
round(y)
  1. 2
  2. -44
  3. -2
  • Trong khi đó, hàm sum() sẽ tính tổng các phần tử của vector hoặc ma trận. Ví dụ, nếu bạn truyền một vector hàng vào sum, tổng của tất cả phần tử trong vector hàng sẽ được trả về dưới dạng vô hướng.

Ở đây, vector x và y được truyền vào sum(). Do đó, R tính tổng các phần tử của vector và trả về một vô hướng làm đầu ra.

sum(abs(round(x)))
7
sum(abs(round(y)))
 48
  • Cuối cùng, hàm mean() hay average() sẽ tính trung bình cộng. Nó lấy trung bình của một tập giá trị số, cộng chúng lại rồi chia cho số lượng phần tử trong tập.

Trong trường hợp này, đầu vào của mean() là một vector hàng độ dài hai chứa các số 7 và 48. Vậy trung bình của hai giá trị này sẽ bằng tổng của chúng chia cho số phần tử, tức là 2.

mean(c(7,48))
27.5

Vẫn khá dễ, phải không?

Giờ hãy chuyển sang phần tiếp theo cũng thú vị không kém!

Các hàm cho Cấu trúc Dữ liệu

Bây giờ hãy xem một số cấu trúc dữ liệu như list và vector. Các cách bạn có thể thao tác với cấu trúc dữ liệu list, đảo ngược một list, và cách chuyển đổi từ list sang vector và ngược lại.

Hàm dưới đây là một list(), hay bạn có thể gọi là list của các list, còn gọi là danh sách lồng nhau. Nó tạo một list các phần tử có thể gồm giá trị logic, số và chuỗi.

Trong ví dụ dưới, có ba list bên trong một list, là log, ch và int_vec. Mỗi cái có một kiểu dữ liệu hay đối tượng R tương ứng với logical, numeric và string/character.

list_define <- list(log = TRUE, ch = "hello_datacamp", int_vec = sort(rep(seq(8,2, by = -2), times = 2)))
list_define
$log
TRUE
$ch
'hello_datacamp'
$int_vec
  1. 2
  2. 2
  3. 4
  4. 4
  5. 6
  6. 6
  7. 8
  8. 8
  • log đơn giản là toán tử logic, TRUE hoặc FALSE
  • ch là chuỗi ký tự hello_datacamp
  • int_vec là một dãy giá trị số.

Vì log và ch khá hiển nhiên, hãy xem kỹ hơn int_vec.

int_vec = sort(rep(seq(8,2, by = -2), times = 2))
int_vec
  1. 2
  2. 2
  3. 4
  4. 4
  5. 6
  6. 6
  7. 8
  8. 8

Hãy hiểu biểu thức trên từng bước một.

Hàm seq tạo một dãy số theo thứ tự giảm dần từ 8 đến 2.

Cú pháp của hàm seq(): seq(x1,x2, by = y)

Hai đối số đầu x1 và x2 cho R biết phạm vi của dãy, tức là bắt đầu và kết thúc ở đâu. Đối số by chỉ định mức tăng hoặc giảm của dãy ở mỗi bước.

Ví dụ, dòng mã dưới sẽ tạo dãy từ 100 đến 200 với bước tăng 20.

seq(100,200, by = 20)
  1. 100
  2. 120
  3. 140
  4. 160
  5. 180
  6. 200

Trong ví dụ của chúng ta, hàm sequence sẽ trả về dãy từ 8 đến 2 (bao gồm) với bước giảm 2, tạo ra một vector độ dài 4.

a = seq(8,2, by = -2)
a
  1. 8
  2. 6
  3. 4
  4. 2

Giờ hãy hiểu hàm rep.

Nó có thể lặp lại đối số đầu vào, thường là một vector hay list, bằng cách dùng đối số times, nhận một số nguyên và lặp lại từng ấy lần chuỗi đầu vào. Hàm rep nhận hai đối số: đầu vào và số lần bạn muốn lặp/nhân bản đầu vào.

Áp dụng rep cho ví dụ của chúng ta, là một vector độ dài 4, sẽ cho một vector đầu ra độ dài 8.

b = rep(a, times = 2)

Nếu bạn muốn lặp lại từng phần tử của vector hay list thay vì cả vector, có một lựa chọn thay thế cho times, đó là đối số each.

Điểm khác biệt rõ ràng giữa times và each là mẫu phân bố của mỗi phần tử xuất hiện sẽ khác nhau.

rep(a, each = 2)
  1. 8
  2. 8
  3. 6
  4. 6
  5. 4
  6. 4
  7. 2
  8. 2

Cuối cùng là hàm sort(). Đây là hàm tổng quát, dễ hiểu, dùng để sắp xếp nhiều cấu trúc dữ liệu như vector hay list. Nó không chỉ giới hạn cho số mà còn dùng cho giá trị logic và ký tự. Mặc định, nó sắp xếp tăng dần.

Hãy đưa đầu ra của rep vào sort để có kết quả cuối cùng.

sort(b)
  1. 2
  2. 2
  3. 4
  4. 4
  5. 6
  6. 6
  7. 8
  8. 8

Tuyệt! Vậy là bạn đã giải được biểu thức dài int_vec bên trong list list_define một cách rất gọn gàng.

Tiếp theo, hãy tìm hiểu nội dung của list list_define bằng cách dùng hàm str(). Hàm str() trong R cho phép bạn hiển thị cấu trúc của các đối tượng R.

str(list_define)
List of 3
 $ log    : logi TRUE
 $ ch     : chr "hello_datacamp"
 $ int_vec: num [1:8] 2 2 4 4 6 6 8 8

Hãy xem một vài biểu thức R hay ho:

  • Hàm is có thể dùng để kiểm tra kiểu cấu trúc dữ liệu của bạn, trả về giá trị logic và hữu ích khi xử lý câu lệnh điều kiện.
is.list(list_define) #trả về true nếu đối số truyền vào là list.
TRUE

Ngược lại, nó trả về FALSE nếu truyền vào một vector, vốn không phải list, như dưới đây.

is.list(c(1,2,3)) #trả về false vì bạn đã truyền một vector.
FALSE
  • Chuyển đổi một vector thành list trong R rất đơn giản. Bạn chỉ cần dùng hàm as kèm theo .list(), và truyền vector làm đối số. Thế là đủ để đổi từ vector sang list.
vec_to_list <- as.list(c(1,2,3))
is.list(vec_to_list) #kiểm tra lại với is.list()
TRUE
  • Mặt khác, một list có thể được trải phẳng thành vector bằng hàm unlist. R thực hiện chuyển đổi này bằng cách làm phẳng toàn bộ cấu trúc list và trả về một vector đơn.
list_to_vec <- unlist(vec_to_list)
list_to_vec
  1. 1
  2. 2
  3. 3

Tương tự is.list(), bạn có thể dùng is.vector() để kiểm tra đối số cho trước có phải vector hay không.

is.vector(list_to_vec)
TRUE

Hãy chuyển list lớn list_define thành một vector. Lưu ý rằng một vector chỉ có thể chứa một kiểu dữ liệu hay đối tượng R duy nhất. Do đó, cả giá trị logical và numerical sẽ được chuyển thành chuỗi.

unlist(list_define)
log
'TRUE'
ch
'hello_datacamp'
int_vec1
'2'
int_vec2
'2'
int_vec3
'4'
int_vec4
'4'
int_vec5
'6'
int_vec6
'6'
int_vec7
'8'
int_vec8
'8'

Trước khi chuyển sang chủ đề tiếp theo, hãy xem hàm append() và rev().

  • Đúng như tên gọi, hàm append() cho phép bạn nối hoặc thêm hai hay nhiều vector hoặc list vào một vector hay list hiện có hoặc mới.

Hãy thử append() với list list_define. Bạn sẽ thấy list giờ có 6 phần tử thay vì 3 vì bạn đã nối chính nó vào nó.

str(append(list_define, list_define))
List of 6
 $ log    : logi TRUE
 $ ch     : chr "hello_datacamp"
 $ int_vec: num [1:8] 2 2 4 4 6 6 8 8
 $ log    : logi TRUE
 $ ch     : chr "hello_datacamp"
 $ int_vec: num [1:8] 2 2 4 4 6 6 8 8
  • Cuối cùng, hãy đảo ngược hoặc đổi thứ tự của list list_define với hàm rev() trong R.
str(rev(list_define))
List of 3
 $ int_vec: num [1:8] 2 2 4 4 6 6 8 8
 $ ch     : chr "hello_datacamp"
 $ log    : logi TRUE

Biểu thức chính quy

Nhiều người thấy biểu thức chính quy là chủ đề phức tạp. Tuy nhiên, nó rất quan trọng không chỉ trong R mà còn ở nhiều ngôn ngữ lập trình như Python. Nhiều ngôn ngữ, bao gồm R, cung cấp khả năng biểu thức chính quy tích hợp.

Regex có thể dùng trong rất nhiều ứng dụng, đặc biệt hữu ích khi bạn muốn tiền xử lý dữ liệu văn bản. Nó được dùng trong nhiều bài toán Xử lý Ngôn ngữ Tự nhiên (NLP).

Nó cũng được dùng trong các công cụ tìm kiếm truy vấn và trình soạn thảo văn bản.

Biểu thức chính quy, còn gọi là regex hoặc regexp hay rational operators, là một chuỗi ký tự xác định một mẫu tìm kiếm. Thông thường, các mẫu này được dùng bởi nhiều thuật toán tìm kiếm chuỗi để tìm mẫu, tìm và thay thế mẫu hoặc lọc mẫu khớp.

Hãy bắt đầu chủ đề này bằng cách hiểu cách dùng hàm grep() và grepl().

Để đơn giản, hãy định nghĩa một vector hàng animals_regex độ dài 5 mà bạn sẽ áp dụng các mẫu regex.

animals_regex <- c('cat','dog','cheetah','lion','mice')

Trước tiên, hãy hiểu hàm grepl(). Hàm grepl() trả về kết quả logic, nghĩa là nếu chuỗi khớp mẫu thì trả về TRUE, ngược lại FALSE.

Dưới đây là cú pháp đơn giản, trực quan của grepl() trong đó đối số đầu tiên là mẫu bạn muốn khớp, còn đối số thứ hai là chuỗi hay đầu vào mà bạn muốn tìm hay lọc mẫu. Bạn có thể tạm bỏ qua các đối số còn lại. grepl(pattern, x, ignore.case = FALSE, perl = FALSE, fixed = FALSE, useBytes = FALSE) Hãy tìm xem trong năm con vật trên, con nào có chữ c nhờ grepl().

Trong trường hợp này, bạn đang tìm các con vật có chữ c, tức là mẫu ở đây chính là c.

grepl(pattern = 'c', x = animals_regex)
  1. TRUE
  2. FALSE
  3. TRUE
  4. FALSE
  5. TRUE

Từ đầu ra trên, bạn thấy rằng vì có chữ c trong cat, cheetah và mice, nên TRUE được trả về cho các chỉ số đó trong vector animals_regex, còn FALSE cho những cái không khớp với mẫu c.

Hãy tìm các phần tử bắt đầu bằng c chứ không chỉ đơn giản là có ký tự c trong tên.

Để làm được điều này, bạn chỉ cần dùng ký hiệu mũ $^$ ở đầu mẫu bạn muốn tìm.

grepl(pattern = '^c', x = animals_regex) #chỉ cat và cheetah bắt đầu bằng `c`.
  1. TRUE
  2. FALSE
  3. TRUE
  4. FALSE
  5. FALSE

Vậy từ đầu ra trên, bạn thấy chỉ cat và cheetah bắt đầu bằng c, nên chỉ các vị trí đó trả về TRUE.

Tương tự ký hiệu $^$, ký hiệu $ có thể dùng ở cuối mẫu bạn muốn tìm để khớp các phần tử kết thúc bằng mẫu đó. Để tìm con vật kết thúc bằng n, bạn chỉ cần dùng n theo sau bởi ký hiệu $.

grepl(pattern = 'n$', x = animals_regex) #chỉ lion kết thúc bằng `n`.
  1. FALSE
  2. FALSE
  3. FALSE
  4. TRUE
  5. FALSE

Lưu ý: Để tìm hiểu thêm về biểu thức chính quy, chỉ cần gõ ?regex trong ô mã jupyter notebook và tài liệu về regex sẽ hiện ra. Ngoài ra, nếu muốn tìm hiểu thêm về biểu thức chính quy, bạn có thể xem nguồn này, nơi cung cấp công cụ để thiết kế mẫu tìm kiếm và thử nghiệm trên chuỗi đầu vào của bạn.

  • Tương tự grepl(), còn có hàm grep(), thay vì trả về giá trị logic, nó trả về chỉ số của vector/ma trận khớp với mẫu đã cho.

Cú pháp của grep() giống hệt grepl() và là: grep(pattern, x, ignore.case = FALSE, perl = FALSE, value = FALSE, fixed = FALSE, useBytes = FALSE, invert = FALSE) Hãy lấy cùng ví dụ như trên nhưng lần này áp dụng grep()!

grep(pattern = 'c', x = animals_regex)
  1. 1
  2. 3
  3. 5

Đúng như bạn kỳ vọng, đầu ra trên trả về chỉ số của các phần tử cat, cheetah và mice, chứ không phải TRUE/FALSE. Về cơ bản là vậy!

Hãy dùng hàm which để so sánh grep() và grepl(). Hàm which() đơn giản trả về các chỉ số trong vector tương ứng với các vị trí TRUE của một đối tượng logic.

Nối kết các ý lại, bạn sẽ hiểu rằng vì grepl() có khả năng trả về đối tượng logic, nó có thể được truyền vào which() để chuyển đầu ra thành dạng tương tự như những gì bạn nhận từ grep().

which(grepl(pattern = 'c', x = animals_regex))
  1. 1
  2. 3
  3. 5

Tương tự grepl(), grep() cũng xử lý được nhiều kiểu mẫu biểu thức chính quy khác nhau.

Nếu bạn dùng grep() để tìm các phần tử trong vector animals_regex kết thúc bằng n, bạn sẽ kỳ vọng đầu ra là 4 vì chỉ có lion kết thúc bằng n như dưới đây.

grep(pattern = 'n$', x = animals_regex)
4

Làm tốt lắm!

Bạn đã học các kiến thức cơ bản về biểu thức chính quy như cách lọc các phần tử từ một vector khớp với mẫu cho trước. Tuy nhiên, R không chỉ dừng ở việc khớp mẫu. Nó có nhiều hàm hữu ích, trong đó sub() là một.

Hàm sub(), thay vì lọc mẫu khớp, sẽ thay thế các lần khớp bằng chuỗi khác. Hãy hiểu sâu hơn!

  • Hàm sub() chủ yếu nhận ba đối số đầu vào:
    • pattern là mẫu bạn muốn khớp hay biểu thức chính quy,
    • giá trị replacement sẽ đặt vào vị trí phần tử khớp trong vector và
    • x là vector chuỗi đầu vào bạn sẽ áp dụng regex.

Cú pháp là: sub(pattern, replacement, x, ignore.case = FALSE, perl = FALSE,fixed = FALSE, useBytes = FALSE) Lần này cũng hãy dùng cùng ví dụ như trên để hiểu chức năng của nó!

sub(pattern = 'c', replacement = 'a', x = animals_regex)
  1. 'aat'
  2. 'dog'
  3. 'aheetah'
  4. 'lion'
  5. 'miae'

Từ đầu ra trên, bạn thấy chuỗi cat bị thay thành aat, chuỗi cheetah thành aheetah, và mice thành miae. Với các phần tử này, mẫu đã được khớp thành công.

Cũng lưu ý rằng sub() chỉ tìm lần khớp đầu tiên trong chuỗi, nghĩa là nếu một chuỗi có hai chữ c, chỉ lần xuất hiện đầu tiên của c sẽ được thay bằng a, lần thứ hai giữ nguyên.

Nếu bạn muốn thay mọi lần khớp của một mẫu trong chuỗi tốt hơn, hãy dùng hàm gsub(), tuy nhiên nó ngoài phạm vi hướng dẫn này!

Trước khi sang chủ đề tiếp theo, hãy thử một biểu thức thú vị nữa.

Lần này bạn sẽ dùng toán tử | (hoặc), sẽ cố gắng khớp bất kỳ mẫu nào đã định và nếu khớp, thay bằng -. Nhớ rằng, vì bạn dùng hàm gsub(), nó sẽ thay mọi lần khớp của một mẫu trong chuỗi.

gsub(pattern = 'c|d|l', replacement = '-', x = animals_regex) #các động vật có `c`,`d`,`l` sẽ được thay bằng `-`.
  1. '-at'
  2. '-og'
  3. '-heetah'
  4. '-ion'
  5. 'mi-e'

Hãy chuyển sang chủ đề cuối cùng hôm nay, đó là Thời gian và Ngày tháng!

Thời gian và Ngày tháng

Thông tin thời gian và ngày tháng có thể rất hữu ích trong nhiều tình huống. Ví dụ, giả sử bạn đang làm một bài toán Thị giác Máy tính và muốn biết FPS (khung hình/giây) mà thuật toán của bạn đang chạy. Trong trường hợp như vậy, bạn có thể dùng đối tượng Time để biết tốc độ xử lý của thuật toán thị giác máy tính. Với các bài toán cụ thể khác như dự báo chuỗi thời gian và nghiên cứu tính mùa vụ, sức mạnh của R có thể được tận dụng tối đa.

Bắt đầu, hãy in nhanh ngày hôm nay bằng R với lệnh đơn giản Sys.Date(). Ở đây Sys là hệ thống, tức là trả về ngày theo hệ thống.

Sys.Date()

Đơn giản, phải không?

Thời gian và ngày tháng trong R thuộc đối tượng Date, hay nói cách khác kiểu dữ liệu là Date. Bạn có thể kiểm tra bằng hàm class mà bạn đã học trong hướng dẫn Data Types in R.

Tương tự hàm Date, bạn có hàm time() trả về thời gian hiện tại của hệ thống, thực ra nó trả về cả thời gian và ngày tháng.

Sys.time()
[1] "2020-02-04 02:05:04 IST"

Tạo đối tượng Date

Bạn đã biết cách lấy ngày và giờ hiện tại. Giờ hãy tìm cách tạo ngày cho những ngày khác chỉ bằng cách truyền một chuỗi làm đối số.

Để tạo đối tượng ngày cho ngày 10 tháng 5 năm 1993, bạn sẽ dùng cú pháp sau:

date_may <- as.Date('1993-05-10') #chuyển chuỗi ký tự thành đối tượng date
date_may

class(date_may)
'Date'

Một điểm quan trọng là hàm Date của R mặc định mong bạn nhập ngày theo định dạng YYYY-MM-DD; nếu bạn hoán đổi năm với tháng hoặc ngày sẽ dẫn đến lỗi. Hãy thử xem!

date_may <- as.Date('05-1993-10') #R mặc định theo định dạng ngày ISO
Error in charToDate(x): character string is not in a standard unambiguous format
Traceback:


1. as.Date("05-1993-10")

2. as.Date.character("05-1993-10")

3. charToDate(x)

4. stop("character string is not in a standard unambiguous format")

Nhưng điều hay là bạn có thể đổi định dạng một cách tường minh bằng cách truyền đối số format và tùy chỉnh.

date_may <- as.Date('05-1993-10', format = '%m-%Y-%d')

Hàm as.Date() sẽ chấp nhận nhiều định dạng ngày khác nhau, nhưng cuối cùng nó sẽ chuyển về định dạng ngày ISO; bạn có thể thấy điều đó bằng cách in biến date_may.

date_may

date_may <- as.Date('05-10-1993', format = '%m-%d-%Y')
date_may

Tính toán với Date

Sẽ thật tuyệt nếu bạn có thể áp dụng các phép toán như cộng trừ cho đối tượng Date trong R?

Hãy cộng 1 vào biến date_may, bạn sẽ thấy nó hiển thị ngày muộn hơn một ngày.

date_may + 1

Tốt, như bạn thấy ở trên, cộng một đã đổi ngày từ 10/05/1993 sang 11/05/1993. Tương tự, bạn có thể trừ một.

Giả sử bạn muốn tìm hiệu số ngày giữa ngày sinh của bạn và anh/chị lớn hơn.

elder_sib <- as.Date('1989-03-21')
date_may - elder_sib
Time difference of 1511 days

Kết luận

Chúc mừng bạn đã hoàn thành hướng dẫn.

Đây là điểm khởi đầu tốt cho người mới bắt đầu muốn học về các hàm tiện ích khác nhau trong R. Một bài tập hay là bạn nên học thêm về Biểu thức chính quy vì chúng được dùng trong rất nhiều ứng dụng và thực sự là công cụ rất mạnh khi làm sạch hay tiền xử lý dữ liệu văn bản.

Vui lòng để lại mọi câu hỏi liên quan đến hướng dẫn này trong phần bình luận bên dưới.

Nếu bạn muốn học thêm về R, hãy tham gia khóa Intermediate R của DataCamp và xem hướng dẫn Sử dụng Hàm trong R của chúng tôi.

Chủ đề
R
Khoa học Dữ liệu

Tìm hiểu thêm về R

Khóa học

Nhập môn viết hàm trong R

4 giờ
54.1K
Nâng cao kỹ năng R bằng cách viết các hàm hiệu quả, có thể tái sử dụng.
Xem chi tiếtRight Arrow
Bắt Đầu Khóa Học
Xem thêmRight Arrow
Liên quan

blog

Claude Opus 4.6: Tính năng, Điểm chuẩn, Bài kiểm tra thực hành và hơn thế nữa

Mô hình mới nhất của Anthropic dẫn đầu ở mã hóa tác tử và lập luận phức tạp. Thêm vào đó, nó có cửa sổ ngữ cảnh 1M.
Matt Crabtree's photo

Matt Crabtree

10 phút

Xem ThêmXem Thêm