Số liệu về ngày tháng rất quan trọng, trong nhiều văn bản và các sách khoa học có nhiều cách để ghi lại ngày tháng năm như 1/2/2003, 01/02/03, 01-02-2003…. Tuy nhiên tất cả những số liệu này cần được chuẩn hóa theo một cách viết thống nhất, quy luật chuẩn là chúng ta dùng tiêu chuẩn ISO 8601, ISO 8601 là một tiêu chuẩn quốc tế, được đưa ra bởi Tổ chức tiêu chuẩn hóa quốc tế (ISO) lần đầu tiên năm 1988, mô tả quy cách viết ngày tháng và thời gian theo cách đơn giản nhất mà máy tính có thể hiểu được theo cách viết: 2003 -02-01 Cách giải thích cho quy luật này đó là chúng ta viết số với đơn vị lớn nhất trước rồi đến các đơn vị nhỏ hơn.
Tiêu chuẩn này dựa trên quy tắc cơ bản là sắp xếp để các đại lượng lớn đứng trước, các đại lượng bé đứng sau. Vì năm thì lớn hơn tháng, tháng thì lớn hơn ngày, nên một ngày theo chuẩn này sẽ được viết theo thứ tự sau: NĂM-THÁNG-NGÀY.
date1 <- as.Date("01/02/06", format = "%d/%m/%y")
date2 <- as.Date("06/03/01", format = "%y/%m/%d")
days <- date2 - date1
days
## Time difference of 28 days
#Tạo dãy số liệu theo tháng
seq(as.Date("2005-01-01"), as.Date("2005-12-31"), by = "month")
## [1] "2005-01-01" "2005-02-01" "2005-03-01" "2005-04-01" "2005-05-01"
## [6] "2005-06-01" "2005-07-01" "2005-08-01" "2005-09-01" "2005-10-01"
## [11] "2005-11-01" "2005-12-01"
R có các hàm như seq, rep và gl có khả năng thiết kế và mô phỏng các dãy số đều nhau. Hàm seq() có hai dạng:
#Tạo ra vector x1 có chiều dài 15 số với hàm seq()
x <- c(1:15)
seq(15)
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
seq(15, 5)
## [1] 15 14 13 12 11 10 9 8 7 6 5
seq(1, 9, by = 2)
## [1] 1 3 5 7 9
seq(1, 25, length.out = 7)
## [1] 1 5 9 13 17 21 25
#Sử dụng hàm rep()
rep(15, 4)
## [1] 15 15 15 15
rep(c(1:4), 2)
## [1] 1 2 3 4 1 2 3 4
Như chúng ta đã biết ma trận - matrix, là dạng dữ liệu được sắp xếp theo dạng dòng (row) và cột (column). Khi chúng ta viết \(A[m,n]\), chúng ta hiểu rằng đây là ma trận \(A\) gồm có \(m\) dòng và \(n\) cột.
\[A= \left[\begin{array}{ccc} 1 & 4 & 7 \\ 2 & 5 & 8 \\ 3 & 6 & 9 \end{array}\right]\]
#Tạo một vectoc y gồm 9 phần tử
y <- c(1,2,3,4,5,6,7,8,9)
#Tạo ma trận A với chỉ định số dòng nrow và số cột ncol, tham số byrow = TRUE, nghĩa là sắp xếp lần lượt theo dòng rồi xuống hàng, nếu không để thì mặc định byrow =FALSE tức là xếp lần lượt theo cột
A <- matrix(y, nrow = 3, ncol = 3, byrow = TRUE)
A
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] 4 5 6
## [3,] 7 8 9
Trong đại số tuyến tính, ma trận chuyển vị (tiếng Anh: transpose) là một ma trận mà ở đó các hàng được thay thế bằng các cột, và ngược lại. Để có được ma trận chuyển vị, chúng ta có thể sử dụng toán tử lật ma trận theo đường chéo chính của nó. Ma trận chuyển vị của ma trận \(A\) được ký hiệu là \(A^{T}\): Nếu A là một ma trận có kích thước \(m * n\) với các giá trị \(a_{ij}\) tại hàng \(i\), cột \(j\), thì ma trận chuyển vị \(B = A^{T}\) là ma trận có kích thước \(n * m\) với các giá trị:
\(b_{ij}=a_{ji}\)#Tạo ma trận chuyển vị, sử dụng hàm t()
y1 <- c(1:12)
A1 <- matrix(y1, nrow =4, byrow = TRUE)
A1_T <- t(A1)
A1_T
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
Ma trận vô hướng là một ma trận vuông (số dòng bằng số cột), tất cả các phần tử ngoài đường chéo (off-diagonal elements) bằng \(0\), và phần các phần tử ở đường chéo bằng \(1\). Chúng ta tạo ra ma trận vô hướng như sau:
#Tạo ra ma trận A(3x3) với các phần tử bằng 0:
A <- matrix(0, 3, 3)
#Cho các phần tử ở đường chéo bằng 1
diag(A) <- 1
#Hiển thị lại ma trận A
A
## [,1] [,2] [,3]
## [1,] 1 0 0
## [2,] 0 1 0
## [3,] 0 0 1
#Trích xuất phần tử của ma trận B
B <- matrix(c(1:9), nrow = 3, byrow = TRUE)
#Hiển thị cột 1 ma trận B và các dòng
B[, 1]
## [1] 1 4 7
#Hiển thị dòng 1, các cột ma trận B
B[1, ]
## [1] 1 2 3
#Hiển thị phần tử ở dòng 2, cột 3
B[2, 3]
## [1] 6
#Hiển thị tất cả các dòng, các cột, trừ dòng 2
B[-2, ]
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] 7 8 9
#Kiểm tra có các phần tử nào lớn hơn 4, giá trị nào lớn hơn trả về TRUE, ngược lại trả về FALSE
B > 4
## [,1] [,2] [,3]
## [1,] FALSE FALSE FALSE
## [2,] FALSE TRUE TRUE
## [3,] TRUE TRUE TRUE
#Cộng, trừ hai ma trận
A <- matrix(1:12, 3, 4)
B <- matrix(-1:-12,3,4)
C <- A + B
D <- A - B
A
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
B
## [,1] [,2] [,3] [,4]
## [1,] -1 -4 -7 -10
## [2,] -2 -5 -8 -11
## [3,] -3 -6 -9 -12
C
## [,1] [,2] [,3] [,4]
## [1,] 0 0 0 0
## [2,] 0 0 0 0
## [3,] 0 0 0 0
D
## [,1] [,2] [,3] [,4]
## [1,] 2 8 14 20
## [2,] 4 10 16 22
## [3,] 6 12 18 24
#Nhân hai ma trận
#Để nhân hai ma trận trong R chúng ta sử dụng toán tử %*%
C <- matrix(1:9, 3, 3)
D <- matrix(1:9, 3, 3, byrow = TRUE) #có thể sử dụng D <- t(C)
CD <- C%*%D
CD
## [,1] [,2] [,3]
## [1,] 66 78 90
## [2,] 78 93 108
## [3,] 90 108 126
Ma trận vuông \(I\) cấp \(n\) được gọi là ma trận đơn vị nếu \(A.I = I.A = A\), với mọi ma trận vuông \(A\) cấp \(n\):
Cho \(A\) là một ma trận vuông cấp \(n\). Ta nói \(A\) là ma trận khả nghịch, nếu tồn tại một ma trận \(B\) vuông cấp \(n\) sao cho: \(A.B = B.A = I_{n}\). Khi đó, \(B\) được gọi là ma trận nghịch đảo của ma trận \(A\), ký hiệu \(A^{-1}\).
Như vậy: \(A.A^{-1}= A^{-1}.A= I_{n}\)
Nhận xét: Ma trận có ít nhất 1 dòng không (hoặc cột không) đều không khả nghịch.
Ma trận \(E\) vuông cấp \(n\) \((n ≥ 2)\) được gọi là ma trận sơ cấp dòng (cột) nếu \(E\) thu được từ ma trận đơn vị \(I_{n}\) bời đúng 1 phép biến đổi sơ cấp dòng (cột). Các ma trận sơ cấp dòng hay cột gọi chung là ma trận sơ cấp.
Phương pháp Gauss-Jordan tìm ma trận nghịch đảo đôi khi còn được gọi là phép khử Gauss-Jordan. Nội dung của phương pháp này về cơ bản là dùng các phép biến đổi dòng và cột từ ma trận vuông ban đầu để đưa về một ma trận đơn vị, ma trận cuối cùng sau phép khử Gauss-Jordan chính là một ma trận nghịch đảo. Chi tiết phương pháp này, cùng xem qua một ví dụ sau:
Bước 1: lập ma trận \(n\) hàng, \(2n\) cột bằng cách ghép thêm ma trận đơn vị cấp \(n\) \(I\) vào bên phải ma trận \(A\)
Bước 2: Dùng các phép biến đổi sơ cấp dòng để đưa \([ A|I ]\) về dạng \([ A’ | B ]\), trong đó A’ là một ma trận bậc thang chính tắc.
– Nếu \(A’ = I_{n}\) thì \(A\) khả nghịch và \(A^{-1} = B\)
– Nếu \(A’ ≠ I_{n}\) thì \(A\) không khả nghịch. Nghĩa là, trong quá trình biến đổi nếu \(A\)’ xuất hiện ít nhất 1 dòng không thì lập tức kết luận \(A\) không khả nghịch (không cần phải đưa \(A’\) về dạng chính tắc) và kết thúc thuật toán.
Ví dụ minh họa: Sử dụng thuật toán Gauss – Jordan để tìm ma trận nghịch đảo của ma trận, từ đó suy ra Từ đó suy ra \(A^{2008}\) :
Ma trận nghịch đảo có thể áp dụng trong ngôn ngữ R để giải hệ phương trình nhiều ẩn. Ví dụ, chúng ta có hệ phương trình sau đây: \[\begin{cases} 3x_{1}+4x_{2}=4 \\ x_{1}+6x_{2}=2 \end{cases}\] Hệ phương trình trên có thể viết bằng ký hiệu ma trận như sau:
\(AX= Y\), trong đó: \(A=\left[\begin{array}{ccc} 3 & 4 \\ 1 & 6\end{array}\right]\) \(X = \left[\begin{array}{ccc} x_{1}\\ x_{2}\end{array}\right]\) và \(Y =\left[\begin{array}{ccc} 4\\2\end{array}\right]\)
Nghiệm của hệ phương trình này là :\(X=A^{-1}Y\), sử dụng trong R:#Sử dụng hàm solve(A) để tìm ma trận nghịch đảo của A
A <- matrix(c(3,1,4,6), nrow =2)
Y <- matrix(c(4, 2), nrow = 2)
X <- solve(A)%*% Y
X
## [,1]
## [1,] 1.1428571
## [2,] 0.1428571
#Kiểm tra nghiệm thu được
3*X[1,1] + 4*X[2,1] # Equal 4 or not
## [1] 4
Trong đại số tuyến tính, một vectơ riêng hay vectơ đặc trưng của một biến đổi tuyến tính là một vectơ khác vectơ không mà được nhân với một hệ số vô hướng khi biến đổi tuyến tính đó được áp dụng lên nó. Hệ số vô hướng tương ứng, thường được ký hiệu là \(\lambda\) được gọi là giá trị riêng.
Nói một cách hình học, một vectơ riêng tương ứng với một giá trị riêng thực khác \(0\) có cùng phương sau khi nó được kéo dài ra bởi phép biến đổi và giá trị riêng là hệ số nhân. Nếu giá trị riêng là âm thì vectơ sẽ đổi chiều. Một cách dễ hiểu, trong một không gian vectơ đa chiều, vectơ riêng không bị quay đi. Ma trận biến đổi \(A\) tác động bằng việc kéo dài vectơ \(x\) mà không làm đổi phương của nó, vì thế \(x\) là một vectơ riêng của \(A\).
Vectơ riêng và giá trị riêng có vai trò nổi bật trong việc phân tích các biến đổi tuyến tính. Trong tiếng Anh, giá trị riêng và vectơ riêng tương ứng được gọi là eigenvalue và eigenvector. Tiền tố eigen- được mượn từ tiếng Đức eigen (cùng gốc với từ tiếng Anh own), nghĩa là “sở hữu”, “đặc trưng”. Ban đầu được sử dụng để nghiên cứu các trục chính của sự quay của các vật rắn, giá trị riêng và vectơ riêng ngày càng có nhiều ứng dụng, ví dụ: trong phân tích ổn định, phân tích rung động, lý thuyết orbital nguyên tử, nghiên cứu băng hà trong địa chất, hệ số lây nhiễm cơ bản, và công nghệ nhận diện khuôn mặt.
Về bản chất, một vectơ riêng \(v\) của một biến đổi tuyến tính \(T\) là một vectơ khác vectơ không sao cho nó vẫn giữ được hướng ban đầu khi \(T\) tác động lên. Tác động của \(T\) lên vectơ riêng chỉ làm kéo dài vectơ riêng, được gấp một giá trị vô hướng \(λ\), gọi là giá trị riêng. Điều kiện này có thể được viết dưới dạng phương trình: $T(v)= \(\lambda\)v$, được gọi là phương trình đặc trưng. Tổng quát, \(\lambda\) có thể là một vô hướng bất kỳ. Chẳng hạn, \(\lambda\) có thể là âm, trong trường hợp này vectơ riêng sẽ đảo chiều khi nó được kéo dài, hoặc giá trị riêng có thể bằng \(0\) hoặc là số phức.
Ví dụ bức vẽ Mona Lisa sau đây là một minh họa đơn giản. Mỗi điểm của hình vẽ có thể được biểu diễn bằng một vectơ từ trung tâm của hình đến điểm đó. Biến đổi tuyến tính trong ví dụ này được gọi là phép ánh xạ trượt. Các điểm ở nửa trên bức vẽ bị dịch sang phải, còn các điểm ở nửa dưới bị dịch sang trái, tỉ lệ thuận với khoảng cách của chúng so với trục hoành ở giữa bức vẽ. Các vectơ tương ứng với mỗi điểm trong bức vẽ ban đầu vì vậy bị trượt sang bên trái hoặc phải, và bị làm cho ngắn vào hoặc dài ra bởi phép biến đổi. Ta cũng có thấy rằng những điểm nằm dọc theo trục hoành không bị di chuyển đi khi phép biến đổi tác động. Vì vậy, mỗi vectơ chỉ trực tiếp sang trái hoặc phải mà không có thành phần thẳng đứng là một vectơ riêng của phép biến đổi này, vì phép biến đổi không ảnh hưởng tới hướng của nó. Hơn nữa, trong ví dụ này các vectơ riêng trên đều có giá trị riêng bằng 1, vì vậy phép biến đổi cũng không làm độ dài của chúng thay đổi.#Tìm trị riêng trong R, sử dụng hàm eigen() để tìm véc tơ riêng cho ma trận K.
K <- c(1,3,4,6)
matrixK <- matrix(K, nrow = 2)
eigen(matrixK)
## eigen() decomposition
## $values
## [1] 7.7720019 -0.7720019
##
## $vectors
## [,1] [,2]
## [1,] -0.5085750 -0.9143009
## [2,] -0.8610177 0.4050357
Định thức (determinant): Định thức, trong đại số tuyến tính, là một hàm cho mỗi ma trận vuông \(A\), tương ứng với số vô hướng, ký hiệu là \(det(A)\). Ý nghĩa hình học của định thức là tỷ lệ xích cho thể tích khi \(A\) được coi là một biến đổi tuyến tính. Định thức được sử dụng để giải (và biện luận) các hệ phương trình đại số tuyến tính
Định thức chỉ được xác định trong các ma trận vuông. Nếu định thức của một ma trận bằng 0, ma trận này được gọi là ma trận suy biến, nếu định thức bằng 1, ma trận này được gọi là ma trận đơn môđula.
Khái niệm định thức xuất hiện đầu tiên gắn với việc giải hệ phương trình đại số tuyến tính có số phương trình bằng số ẩn. Hệ này có một nghiệm duy nhất khi và chỉ khi định thức của ma trận tương ứng với hệ phương trình này khác \(0\). Ví dụ hệ hai phương trình tuyến tính hai ẩn: \[\begin{cases} ax+by=e \\ cx+dy=f \end{cases}\] Có các hệ số tạo thành một ma trận vuông: \[A=\left[\begin{array}{ccc} a &b\\ c & d\end{array}\right]\] Định thức của nó là: \(det(A)=ad-bc\). Nếu $det(A) !=0 $, hệ có nghiệm duy nhất \(x=\frac{ed-bf}{ad-bc}\) và \(y=\frac{af-ce}{ad-bc}\). Nếu \(det(A) =0\), hệ có thể có vô số nghiệm hoặc không có nghiệm nào. Nếu \(e = f = 0\), hệ trên là một hệ phương trình tuyến tính thuần nhất, nó luôn có ít nhất một nghiệm tầm thường là \(x = 0 và y = 0\). Khi đó hệ có nghiệm không tầm thường khi và chỉ khi định thức của hệ bằng không.#Find the determinant, sử dụng det(A)
A <- matrix(c(-2,2,-3,-1,1,3,2,0,-1), nrow = 3, byrow = TRUE)
det(A) # Trùng khớp với kết quả của công thức tính theo Leibniz
## [1] 18
#Ma trận mà có định thức bằng 0 là ma trận suy biến (singular matrix) và không khả nghịch.
#Dùng hàm det() trong R ngoài tìm định thức, còn xét được tính chất khả nghịch của ma trận
B <- matrix((1:9), 3, 3)
det(B) #Ma trận B có determinant = 0, do đó là ma trận suy biến
## [1] 0
#Chúng ta dùng hàm solve() để tìm ma trận nghịch đảo của ma trận A, do det(A) #0
solve(A)
## [,1] [,2] [,3]
## [1,] -0.05555556 0.1111111 0.5
## [2,] 0.27777778 0.4444444 0.5
## [3,] -0.11111111 0.2222222 0.0
Ma trận - Matrix là một khái niệm quan trọng trong nhiều lĩnh vực, không chỉ trong đại số tuyến tính và Toán học nói riêng mà còn ứng dụng nhiều trong các lĩnh vực khác. Một lợi thế với tính toán ma trận khi sử dụng R là phần mềm cho phép tính toán với các phép toán phức tạp với ma trận hoặc cho phép người sử dụng tự tạo ra những phép tính phù hợp với từng vấn đề cụ thể trong từng bài toán khác nhau.
R có một package chuyên dụng có tên Matrix chuyên thiết kế cho tính toán ma trận.
Hy vọng với chút kiến thức này có thể giúp bạn mường tượng lại các khái niệm liên quan đến ma trận, giúp bạn làm quen với các phép toán với ma trận sử dụng ngôn ngữ R. Kết bài, mình hy vọng trong thời gian tới có thể xây dựng và kết nối nhiều hơn nữa với những ai quan tâm tới ngôn ngữ lập trình R, sử dụng trong các ngành như kinh tế lượng, kinh tế quốc tế, phân tích số liệu thống kê, phân tích số liệu trong khoa học xã hội… Cùng chia sẻ kiến thức và kết nối nhé!
Trần Quang Quý - BM Khoa học Máy tính & Công nghệ. Trường Đại học Công nghệ Thông tin & Truyền thông Thái Nguyên.