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

Các kiểu dữ liệu trong R

Tìm hiểu về các kiểu dữ liệu và tầm quan trọng của chúng trong một ngôn ngữ lập trình. Cụ thể hơn, học cách sử dụng các kiểu dữ liệu như vector, ma trận, list và dataframe trong ngôn ngữ R.
· 12 phút đọc

Khám phá cùng AI

sơ đồ cấu trúc dữ liệu r

Trước khi bắt đầu phần giới thiệu và tìm hiểu về các kiểu dữ liệu khác nhau trong R, hãy nhanh chóng thiết lập môi trường R trên Terminal và Jupyter Notebook.

Lệnh sau dành cho hệ điều hành Mac, sẽ cài đặt R trên terminal của bạn.

brew install r --build-from-source

Để xác minh cài đặt đã thành công, chỉ cần gõ R (chữ hoa) trong terminal, bạn sẽ vào phiên làm việc R như minh họa bên dưới.

phiên r

Để cài đặt trên các hệ điều hành khác, bạn có thể xem hướng dẫn này.

Giờ hãy thêm ngôn ngữ lập trình R làm kernel trên jupyter notebook. Hãy chắc chắn bạn đã cài đặt jupyter notebook trên hệ thống.

Mở terminal, vào phiên R và nhập hai lệnh dưới đây, chúng sẽ thêm kernel R vào jupyter notebook của bạn.

install.packages('IRkernel')
IRkernel::installspec()

Sau khi hai lệnh trên chạy thành công, hãy khởi chạy jupyter từ terminal và mở một notebook với kernel R như hình dưới:

kernel r

Bây giờ bạn đã sẵn sàng viết những dòng mã R đầu tiên trên jupyter notebook.

Giới thiệu

Để khai thác R một cách tối đa, điều rất quan trọng là bạn phải biết và hiểu các kiểu dữ liệu và cấu trúc dữ liệu khác nhau trong R cùng cách chúng hoạt động. Chúng đóng vai trò chủ chốt trong hầu hết các bài toán, đặc biệt khi bạn làm việc với các bài toán học máy vốn rất tập trung vào dữ liệu.

Trong một ngôn ngữ lập trình, chúng ta thường cần biến để lưu trữ thông tin, có thể là số nguyên, ký tự, số thực dấu phẩy động, boolean, v.v. type (kiểu) của biến hoàn toàn dựa trên loại thông tin mà nó chứa. Nếu biến được gán một số nguyên, thì kiểu dữ liệu của biến là int. Biến đơn giản chỉ là các vị trí bộ nhớ được dành riêng để lưu trữ giá trị. Ngay khi bạn tạo một biến, một vùng nhớ sẽ được cấp phát cho nó.

Dựa trên kiểu dữ liệu của biến, hệ điều hành sẽ cấp phát một lượng bộ nhớ nhất định. Ví dụ, trong R, một biến chứa số nguyên sẽ dùng 4 byte bộ nhớ và 1 byte cho một ký tự.

Trong các ngôn ngữ như C, C++, và Java, biến được khai báo theo kiểu dữ liệu; tuy nhiên, trong Python và R, biến là một đối tượng. Đối tượng về bản chất là một cấu trúc dữ liệu có một vài thuộc tính và phương thức áp dụng lên các thuộc tính đó.

Có nhiều loại đối tượng R hay cấu trúc dữ liệu khác nhau sẽ được thảo luận trong hướng dẫn này như:

  • Vector

  • List

  • Ma trận

  • Mảng

  • Yếu tố (Factor)

  • Data Frame

Trước hết, hãy hiểu một số kiểu dữ liệu cơ bản dùng để xây dựng các đối tượng R như Numeric, Integer, Character, Factor và Logical.

  • Numeric: Các số có giá trị thập phân hoặc là phân số có kiểu dữ liệu numeric.
num <- 1.2
print(num)
[1] 1.2

Bạn có thể kiểm tra kiểu dữ liệu của a bằng từ khóa class().

class(num)
'numeric'
  • Integer: Các số không chứa phần thập phân có kiểu dữ liệu integer. Tuy nhiên, để tạo kiểu integer, bạn cần dùng tường minh as.integer() và truyền biến làm đối số.
int <- as.integer(2.2)
print(int)
[1] 2
class(int)
'integer'
  • Character: Đúng như tên gọi, một chữ cái hoặc tổ hợp chữ cái được đặt trong dấu ngoặc kép được R xem là kiểu dữ liệu character. Có thể là chữ cái hoặc chữ số.
char <- "datacamp"
print(char)
[1] "datacamp"
class(char)
'character'
char <- "12345"
print(char)
[1] "12345"
class(char)
'character'
  • Logical: Biến có thể mang giá trị True và False như boolean được gọi là biến logical.
log_true <- TRUE
print(log_true)
[1] TRUE
class(log_true)
'logical'
log_false <- FALSE
print(log_false)
[1] FALSE
class(log_false)
'logical'
  • Factor: Đây là kiểu dữ liệu dùng để biểu diễn mối quan hệ định tính như màu sắc, tốt & xấu, điểm xếp hạng khóa học hay phim, v.v. Chúng hữu ích trong mô hình thống kê.

Để làm điều này, bạn sẽ dùng hàm c(), hàm này trả về một vector (một chiều) bằng cách kết hợp tất cả phần tử.

fac <- factor(c("good", "bad", "ugly","good", "bad", "ugly"))
print(fac)
[1] good bad  ugly good bad  ugly
Levels: bad good ugly
class(fac)
'factor'

Factor fac có ba mức là good, bad và ugly; bạn có thể kiểm tra bằng từ khóa levels, và kiểu của các mức là character.

levels(fac)
  1. 'bad'
  2. 'good'
  3. 'ugly'
nlevels(fac)
3
class(levels(fac))
'character'

Trước khi tiếp tục, hãy điểm qua vài mẹo quan trọng có thể rất hữu ích!

  • Hãy luôn nhớ rằng ngôn ngữ R phân biệt chữ hoa chữ thường. Tất cả các đối tượng đã định nghĩa ở trên phải được dùng đúng như vậy, viết hoa hay viết thường, như ví dụ dưới đây.
Num
Error in eval(expr, envir, enclos): object 'Num' not found
Traceback:
  • Trong R, bạn có thể kiểm tra tất cả các biến hoặc đối tượng đã được bạn định nghĩa trong môi trường làm việc bằng từ khóa ls(), như dưới đây.
ls()
  1. 'char'
  2. 'int'
  3. 'num'

List

Đánh chỉ mục List trong Python
(Nguồn)

Không giống vector, một list có thể chứa các phần tử thuộc nhiều kiểu dữ liệu khác nhau và thường được gọi là một tập hợp giá trị có thứ tự. Nó có thể chứa vector, hàm, ma trận, thậm chí là một list khác bên trong (list lồng nhau).

Các list trong R đánh chỉ mục bắt đầu từ 1, tức là chỉ mục bắt đầu bằng một.

Hãy hiểu khái niệm list bằng một ví dụ nhanh có ba kiểu dữ liệu khác nhau được lưu trong một list.

lis1 <- 1:5  # Integer Vector
lis1
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
lis2 <- factor(1:5)  # Factor Vector
lis2
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
Mức:
  1. '1'
  2. '2'
  3. '3'
  4. '4'
  5. '5'
lis3 <- letters[1:5]  # Character Vector
lis3
  1. 'a'
  2. 'b'
  3. 'c'
  4. 'd'
  5. 'e'
combined_list <- list(lis1, lis2, lis3)
combined_list
    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
  1. Mức:
    1. '1'
    2. '2'
    3. '3'
    4. '4'
    5. '5'
    1. 'a'
    2. 'b'
    3. 'c'
    4. 'd'
    5. 'e'

Hãy truy cập từng vector trong list riêng biệt. Để làm vậy, bạn sẽ dùng ngoặc vuông kép vì ba vector nằm cùng một cấp trong list. python combined_list[[1]]

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5

python combined_list[[2]]

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
Mức:
  1. '1'
  2. '2'
  3. '3'
  4. '4'
  5. '5'
combined_list[[3]]
  1. 'a'
  2. 'b'
  3. 'c'
  4. 'd'
  5. 'e'

Bây giờ, hãy thử truy cập phần tử thứ năm từ vector thứ ba, kết quả là chữ cái e.

combined_list[[3]][5]
'e'

Cuối cùng, thử làm phẳng list. Một điều quan trọng cần nhớ là vì combined_list là sự kết hợp của kiểu character và numeric, kiểu character sẽ được ưu tiên, và kiểu dữ liệu của toàn bộ list sẽ trở thành character.

flat_list <- unlist(combined_list)
class(flat_list)
'character'
flat_list
  1. '1'
  2. '2'
  3. '3'
  4. '4'
  5. '5'
  6. '1'
  7. '2'
  8. '3'
  9. '4'
  10. '5'
  11. 'a'
  12. 'b'
  13. 'c'
  14. 'd'
  15. 'e'
length(flat_list)
15

Vector

vector ma trận
(Nguồn)

Vector là một đối tượng dùng để lưu trữ nhiều thông tin hay giá trị cùng kiểu dữ liệu. Một vector không thể đồng thời chứa số nguyên và ký tự. Ví dụ, nếu bạn muốn lưu tổng điểm của 100 sinh viên, thay vì tạo 100 biến khác nhau cho từng sinh viên, bạn sẽ tạo một vector độ dài 100 để lưu toàn bộ điểm trong đó.

Có thể tạo một vector bằng hàm c(), hàm này sẽ kết hợp tất cả phần tử và trả về một mảng một chiều.

Hãy tạo một vector marks với dữ liệu của năm sinh viên thuộc lớp numeric.

marks <- c(88,65,90,40,65)
class(marks)
'numeric'

Hãy kiểm tra độ dài của vector, kết quả sẽ là số phần tử chứa trong đó.

length(marks)
5

Bây giờ, hãy thử truy cập một phần tử cụ thể theo chỉ mục.

marks[4]
40
marks[5]
65
marks[6] #trả về NA vì không có phần tử thứ sáu trong vector

<NA>

  • Slicing: Tương tự Python, bạn cũng có thể áp dụng khái niệm slicing trong R.

    Hãy thử truy cập các phần tử từ phần tử thứ hai đến thứ năm bằng slicing.

marks[2:5]
  1. 65
  2. 90
  3. 40
  4. 65

Giờ hãy tạo một vector character tương tự như khi tạo vector numeric.

char_vector <- c("a", "b", "c")
print(char_vector)
[1] "a" "b" "c"
class(char_vector)

'character'

length(char_vector)
3
char_vector[1:3]
  1. 'a'
  2. 'b'
  3. 'c'

Nếu chúng ta tạo một vector có cả giá trị numeric và character, các giá trị numeric sẽ được chuyển sang kiểu character.

char_num_vec <- c(1,2, "a")
char_num_vec
  1. '1'
  2. '2'
  3. 'a'
class(char_num_vec)
'character'

Hãy tạo một vector với 1024 giá trị numeric bằng cách dùng khái niệm slicing.

vec <- c(1:1024)

Bây giờ, thử truy cập phần tử giữa và phần tử cuối. Để làm vậy, bạn sẽ dùng hàm length.

vec[length(vec)]
1024
vec[length(vec)/2]
512
  • Làm thế nào để tạo một vector số lẻ?

Để tạo một vector số lẻ, bạn có thể dùng hàm seq, hàm này nhận ba tham số: bắt đầu, kết thúc và bước nhảy.

seq(1,10, by = 2)
  1. 1
  2. 3
  3. 5
  4. 7
  5. 9

Ma trận

ma trận trong r
(Nguồn)

Tương tự vector, ma trận dùng để lưu trữ thông tin cùng kiểu dữ liệu. Tuy nhiên, khác với vector, ma trận có khả năng lưu trữ thông tin hai chiều.

Cú pháp định nghĩa một ma trận là:

M <- matrix(vector, nrow=r, ncol=c, byrow=FALSE, dimnames=list(char_vector_rownames, char_vector_colnames))

byrow=TRUE biểu thị ma trận được điền theo hàng. byrow=FALSE biểu thị ma trận được điền theo cột (mặc định).

Hãy nhanh chóng định nghĩa một ma trận M có kích thước $2\times3$.

M = matrix( c('AI','ML','DL','Tensorflow','Pytorch','Keras'), nrow = 2, ncol = 3, byrow = TRUE)
print(M)
     [,1]         [,2]      [,3]   
[1,] "AI"         "ML"      "DL"   
[2,] "Tensorflow" "Pytorch" "Keras"

Hãy dùng khái niệm slicing và lấy phần tử theo hàng và cột.

M[1:2,1:2] #kích thước thứ nhất chọn cả hai hàng, kích thước thứ hai sẽ chọn
#các phần tử từ cột 1 và cột 2
Một ma trận: 2 × 2 kiểu chr
AIML
TensorflowPytorch

DataFrame

data frame
(Nguồn)

Không giống ma trận, Data frame là dạng tổng quát hơn của ma trận. Nó chứa dữ liệu theo dạng bảng. Dữ liệu trong data frame có thể trải dài qua nhiều cột với các kiểu dữ liệu khác nhau. Cột thứ nhất có thể là character, cột thứ hai có thể là integer, và cột thứ ba có thể là logical.

Các biến hoặc đặc trưng nằm theo cột, còn gọi là header, trong khi các quan sát nằm theo hàng với phần tử đầu là tên của hàng theo sau là dữ liệu thực, còn gọi là data rows.

DataFrame có thể được tạo bằng hàm data.frame().

DataFrame được sử dụng rộng rãi để đọc tệp phân tách bằng dấu phẩy (CSV), tệp văn bản. Việc sử dụng không chỉ giới hạn ở đọc dữ liệu; bạn còn có thể dùng chúng cho bài toán học máy, đặc biệt khi xử lý dữ liệu số. DataFrame hữu ích cho việc hiểu dữ liệu, tiền xử lý dữ liệu, vẽ và trực quan hóa.

Hãy tạo một tập dữ liệu giả và tìm hiểu một số hàm chuyên biệt cho data frame.

dataset <- data.frame(
   Person = c("Aditya", "Ayush","Akshay"),
   Age = c(26, 26, 27),
   Weight = c(81,85, 90),
   Height = c(6,5.8,6.2),
   Salary = c(50000, 80000, 100000)
)
print(dataset)
  Person Age Weight Height Salary
1 Aditya  26     81    6.0  5e+04
2  Ayush  26     85    5.8  8e+04
3 Akshay  27     90    6.2  1e+05
class(dataset)
'data.frame'
nrow(dataset) # lệnh này sẽ cho bạn biết số hàng trong dataframe dataset
3
ncol(dataset) # lệnh này sẽ cho bạn biết số cột trong dataframe dataset
5
df1 = rbind(dataset, dataset) # nối theo hàng, sẽ ghép các đối số theo chiều hàng.
df1
Một data.frame: 6 × 5
PersonAgeWeightHeightSalary
<fct><dbl><dbl><dbl><dbl>
Aditya26816.05e+04
Ayush26855.88e+04
Akshay27906.21e+05
Aditya26816.05e+04
Ayush26855.88e+04
Akshay27906.21e+05
df2 = cbind(dataset, dataset) # nối theo cột, sẽ ghép các đối số theo chiều cột.
df2
Một data.frame: 3 × 10
PersonAgeWeightHeightSalaryPersonAgeWeightHeightSalary
<fct><dbl><dbl><dbl><dbl><fct><dbl><dbl><dbl><dbl>
Aditya26816.05e+04Aditya26816.05e+04
Ayush26855.88e+04Ayush26855.88e+04
Akshay27906.21e+05Akshay27906.21e+05

Hãy xem hàm head rất hữu ích khi bạn có hàng triệu bản ghi và chỉ muốn xem vài hàng đầu của dữ liệu. Tương tự, hàm tail sẽ in ra vài hàng cuối cùng.

head(df1,3) # ở đây chỉ in ba hàng
Một data.frame: 3 × 5
 PersonAgeWeightHeightSalary
 <fct><dbl><dbl><dbl><dbl>
1Aditya26816.05e+04
2Ayush26855.88e+04
3Akshay27906.21e+05
str(dataset) #hàm này trả về thông tin lớp hoặc kiểu dữ liệu riêng cho từng cột.
'data.frame':    3 obs. of  5 variables:
 $ Person: Factor w/ 3 levels "Aditya","Akshay",..: 1 3 2
 $ Age   : num  26 26 27
 $ Weight: num  81 85 90
 $ Height: num  6 5.8 6.2
 $ Salary: num  5e+04 8e+04 1e+05

Giờ hãy xem hàm summary(), rất hữu ích khi bạn muốn hiểu thống kê của tập dữ liệu. Như bên dưới, nó chia dữ liệu thành ba tứ phân vị, dựa vào đó bạn có thể có trực giác về phân phối dữ liệu. Nó cũng cho biết liệu có giá trị thiếu trong tập dữ liệu không.

summary(dataset)
    Person       Age            Weight          Height        Salary      
 Aditya:1   Min.   :26.00   Min.   :81.00   Min.   :5.8   Min.   : 50000  
 Akshay:1   1st Qu.:26.00   1st Qu.:83.00   1st Qu.:5.9   1st Qu.: 65000  
 Ayush :1   Median :26.00   Median :85.00   Median :6.0   Median : 80000  
            Mean   :26.33   Mean   :85.33   Mean   :6.0   Mean   : 76667  
            3rd Qu.:26.50   3rd Qu.:87.50   3rd Qu.:6.1   3rd Qu.: 90000  
            Max.   :27.00   Max.   :90.00   Max.   :6.2   Max.   :100000  

Kết luận

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

Hướng dẫn này là một điểm khởi đầu tốt cho người mới bắt đầu muốn học ngôn ngữ lập trình R. Như một bài luyện tập hay, bạn có thể tìm hiểu thêm các hàm trợ giúp liên quan đến từng kiểu dữ liệu.

Còn rất nhiều nội dung về R chưa được khám phá như Cấu trúc điều kiện và Luồng điều khiển trong R, Tiện ích trong R, và phần hấp dẫn nhất là Học máy bằng R, sẽ được đề cập trong các hướng dẫn tương lai, hãy đón xem!

Vui lòng đặt 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 Giới thiệu về Data frame trong R.

Chủ đề