“Học, học nữa, học mãi.”
Vectơ, ma trận và mảng rất hữu hiệu và thuận tiện trong việc lưu trữ dữ liệu nhưng chúng chỉ cho phép lưu trữ dữ liệu cùng kiểu. Chương này sẽ trình bày hai cấu trúc dữ liệu mới gọi là list và data frame. Chúng cho phép lưu trữ nhiều kiểu dữ liệu cùng lúc.
List là một dạng cấu trúc dữ liệu cực kỳ hữu ích trong R. List có thể
chứa vectơ, ma trận, mảng, chuỗi ký tự, factor và có thể chứa list khác.
Để tạo list chúng ta dùng hàm list().
lst <- list(matrix(data = 1:4, nrow = 2, ncol = 2), c(T, F, T, T), "hello")
lst
## [[1]]
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
##
## [[2]]
## [1] TRUE FALSE TRUE TRUE
##
## [[3]]
## [1] "hello"
Chúng ta có thể tính độ dài, trích xuất và thay thế các phần tử của list.
length(lst)
## [1] 3
lst[[1]]
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
lst[[3]]
## [1] "hello"
lst[[1]][1,2]
## [1] 3
lst[[1]][2,]
## [1] 2 4
lst[c(2,3)]
## [[1]]
## [1] TRUE FALSE TRUE TRUE
##
## [[2]]
## [1] "hello"
Chúng ta có thể đặt tên cho các phần tử của list bằng cách dùng hàm
names() hoặc đặt tên trực tiếp khi tạo list.
names(lst) <- c("matran", "logic", "chuoi")
lst
## $matran
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
##
## $logic
## [1] TRUE FALSE TRUE TRUE
##
## $chuoi
## [1] "hello"
lst_moi <- list(matran = matrix(data = 1:4, nrow = 2, ncol = 2), logic = c(T, F, T, T), chuoi = "hello")
lst_moi
## $matran
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
##
## $logic
## [1] TRUE FALSE TRUE TRUE
##
## $chuoi
## [1] "hello"
Lúc này chúng ta cũng có thể trích xuất các phần tử của list theo tên của chúng.
lst$matran
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
lst$chuoi
## [1] "hello"
Chúng ta có thể thêm phần tử của list là một list khác bằng cách:
lst$danhsach = list(matran1 = matrix(data = 11:14, nrow = 2, ncol = 2), logic1 = c(F, F, F, F), chuoi1 = "xin chao")
lst
## $matran
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
##
## $logic
## [1] TRUE FALSE TRUE TRUE
##
## $chuoi
## [1] "hello"
##
## $danhsach
## $danhsach$matran1
## [,1] [,2]
## [1,] 11 13
## [2,] 12 14
##
## $danhsach$logic1
## [1] FALSE FALSE FALSE FALSE
##
## $danhsach$chuoi1
## [1] "xin chao"
lst$danhsach$chuoi1
## [1] "xin chao"
Bài tập 5.1.
c(F, T, T, T, F, T, T, F, F) điền theo cột, một vectơ ký tự
gồm 2 chuỗi "vladimir" và "lenin", và một
factor chứa c("Thap", "Vua", "Thap", "Vua", "Vua", "Cao").
Từ list vừa tạo hãy:
Vua của vectơ
factor.sub() để thay thế "vladimir"
và "lenin" thành "Vladimir" và
"Lenin". Sau đó hãy xuất ra màn hình câu nói như sau:Học, học nữa, học mãi!
-\Vladimir Lenin/-
facs, vectơ số c(3,2.1,3.3,4,1.5,4.9) đặt tên
là nums, và một list chứa 3 phần tử đầu của list câu (a)
đặt tên là oldlist. Từ list mới tạo hãy:
facs tương ứng với các phần tử
lớn hơn hoặc bằng 3 của nums.flags. Phần tử
này là vectơ logic có độ dài là 6 thu được từ việc lập lại 2 lần cột thứ
3 của ma trận logic của phần tử oldlist.oldlist bằng chuỗi ký tự
đơn "Vladimir Lenin".data.frame(). Chúng ta sẽ dùng data frame để lưu trữ tập dữ
liệu sau.
| Tên | Giới tính | Tuổi |
|---|---|---|
| Lan | Nữ | 42 |
| Hoa | Nữ | 40 |
| Huệ | Nữ | 17 |
| Tài | Nam | 14 |
| Tâm | Nữ | 1 |
mydf <- data.frame(
Tên = c("Lan", "Hoa", "Huệ", "Tài", "Tâm"),
Giới.tính = factor(c("Nữ", "Nữ", "Nữ", "Nam", "Nữ")),
Tuổi = c(42,40,17,14,1)
)
mydf
## Tên Giới.tính Tuổi
## 1 Lan Nữ 42
## 2 Hoa Nữ 40
## 3 Huệ Nữ 17
## 4 Tài Nam 14
## 5 Tâm Nữ 1
Vì data frame là trường hợp đặc biệt của list nên chúng ta có thể trích xuất các thành phần của data frame tương tự như list.
mydf[[2]]
## [1] Nữ Nữ Nữ Nam Nữ
## Levels: Nam Nữ
mydf$Giới.tính
## [1] Nữ Nữ Nữ Nam Nữ
## Levels: Nam Nữ
mydf$Giới.tính[4]
## [1] Nam
## Levels: Nam Nữ
Mặt khác, vì data frame cũng có dòng và cột khá giống ma trận nên chúng ta có thể trích xuất các thành phần của data frame giống như ma trận.
mydf[, 2]
## [1] Nữ Nữ Nữ Nam Nữ
## Levels: Nam Nữ
mydf[, c(1, 2)]
## Tên Giới.tính
## 1 Lan Nữ
## 2 Hoa Nữ
## 3 Huệ Nữ
## 4 Tài Nam
## 5 Tâm Nữ
mydf[4, 2]
## [1] Nam
## Levels: Nam Nữ
nrow(mydf)
## [1] 5
ncol(mydf)
## [1] 3
dim(mydf)
## [1] 5 3
Đối với data frame, mỗi dòng là dữ liệu của một đối tượng nghiên cứu.
mydf[1,]
## Tên Giới.tính Tuổi
## 1 Lan Nữ 42
mydf[3,]
## Tên Giới.tính Tuổi
## 3 Huệ Nữ 17
Chúng ta có thể thêm dòng (thêm đối tượng nghiên cứu) hoặc thêm cột
(thêm biến) vào data frame bằng cách dùng hàm rbind() và
cbind() tương ứng.
doi.tuong.moi <- data.frame(
Tên = "Tín",
Giới.tính = factor("Nam", levels = levels(mydf$Giới.tính)),
Tuổi = 7
)
doi.tuong.moi
## Tên Giới.tính Tuổi
## 1 Tín Nam 7
mydf <- rbind(mydf,doi.tuong.moi)
mydf
## Tên Giới.tính Tuổi
## 1 Lan Nữ 42
## 2 Hoa Nữ 40
## 3 Huệ Nữ 17
## 4 Tài Nam 14
## 5 Tâm Nữ 1
## 6 Tín Nam 7
Tháng.sinh <- c("Tháng 4", "Tháng 1", "Tháng 1", "Tháng 9", "Tháng 11", "Tháng 7")
Tháng.sinh <- factor(Tháng.sinh, levels = c("Tháng 1", "Tháng 2", "Tháng 3", "Tháng 4", "Tháng 5", "Tháng 6", "Tháng 7", "Tháng 8", "Tháng 9", "Tháng 10", "Tháng 11", "Tháng 12" ), ordered = T)
Tháng.sinh
## [1] Tháng 4 Tháng 1 Tháng 1 Tháng 9 Tháng 11 Tháng 7
## 12 Levels: Tháng 1 < Tháng 2 < Tháng 3 < Tháng 4 < Tháng 5 < ... < Tháng 12
mydf <- cbind(mydf, Tháng.sinh)
mydf
## Tên Giới.tính Tuổi Tháng.sinh
## 1 Lan Nữ 42 Tháng 4
## 2 Hoa Nữ 40 Tháng 1
## 3 Huệ Nữ 17 Tháng 1
## 4 Tài Nam 14 Tháng 9
## 5 Tâm Nữ 1 Tháng 11
## 6 Tín Nam 7 Tháng 7
Chúng ta cũng có thể thêm biến vào data frame giống như thêm thành phần của list như trước đây.
mydf$Sự.hài.hước <- factor(c("Cao", "Cao", "Thấp", "Vừa", "Cao", "Vừa"), levels = c("Thấp", "Vừa", "Cao"), ordered = T)
mydf
## Tên Giới.tính Tuổi Tháng.sinh Sự.hài.hước
## 1 Lan Nữ 42 Tháng 4 Cao
## 2 Hoa Nữ 40 Tháng 1 Cao
## 3 Huệ Nữ 17 Tháng 1 Thấp
## 4 Tài Nam 14 Tháng 9 Vừa
## 5 Tâm Nữ 1 Tháng 11 Cao
## 6 Tín Nam 7 Tháng 7 Vừa
Chúng ta có thể trích xuất các thành phần của data frame thỏa điều kiện cho trước.
mydf[mydf$Giới.tính == "Nam",]
## Tên Giới.tính Tuổi Tháng.sinh Sự.hài.hước
## 4 Tài Nam 14 Tháng 9 Vừa
## 6 Tín Nam 7 Tháng 7 Vừa
mydf[mydf$Giới.tính == "Nam", -3]
## Tên Giới.tính Tháng.sinh Sự.hài.hước
## 4 Tài Nam Tháng 9 Vừa
## 6 Tín Nam Tháng 7 Vừa
mydf[mydf$Giới.tính == "Nam", c("Tên", "Tuổi", "Sự.hài.hước")]
## Tên Tuổi Sự.hài.hước
## 4 Tài 14 Vừa
## 6 Tín 7 Vừa
mydf[mydf$Tuổi > 10 | mydf$Sự.hài.hước == "Cao",]
## Tên Giới.tính Tuổi Tháng.sinh Sự.hài.hước
## 1 Lan Nữ 42 Tháng 4 Cao
## 2 Hoa Nữ 40 Tháng 1 Cao
## 3 Huệ Nữ 17 Tháng 1 Thấp
## 4 Tài Nam 14 Tháng 9 Vừa
## 5 Tâm Nữ 1 Tháng 11 Cao
mydf[mydf$Tuổi > 45,]
## [1] Tên Giới.tính Tuổi Tháng.sinh Sự.hài.hước
## <0 rows> (or 0-length row.names)
Bài tập 5.2.
dframe, trong đó tên
là vectơ chuỗi ký tự, giới tính và sự hài hước là vectơ factor.
| Tên | Giới tính | Sự hài hước |
|---|---|---|
| Tình | Nam | Cao |
| An | Nữ | Vừa |
| Bảo | Nam | Thấp |
| Phúc | Nam | Cao |
| Thảo | Nữ | Vừa |
| Đại | Nam | Vừa |
dframe như sau:
Lan và Hoa 41 tuổi, Huệ 15 tuổi, Tâm 21 tuổi, Tín 60 tuổi, Tài 1600
tuổi.dframe theo thứ tự tên, giới tính,
tuổi và sự hài hước.mydf2 từ
mydf bằng cách loại bỏ biến tháng sinh.dframe và mydf2 thành data frame
mới tên mydframe.mydframe, trích ra thông tin các đối tượng có tên
bắt đầu bằng chữ T. Hướng dẫn: sử dụng hàm substr().| Hàm/Toán tử | Ý nghĩa |
|---|---|
list()
|
Tạo list |
[[ ]]
|
Trích một thành phần của list theo chỉ số vị trí |
[c()]
|
Trích nhiều thành phần của list theo chỉ số vị trí |
$
|
Trích thành phần theo tên |
data.frame()
|
Tạo data frame |
[ , ]
|
Trích data frame theo dòng và cột |