matrix(data = NA,
nrow = 1,
ncol = 1,
byrow = FALSE,
dimnames = NULL)Álgebra Linear Computacional
Operações com Matrizes
1 Introdução
Como vimos, uma matriz em matemática é apenas um array bi-dimensional de números. Em R, a noção de matriz é extendida a elementos de qualquer tipo, então, dessa forma, você pode ter uma matriz de strings, por exemplo.. Podemos criar matrizes em R utilizando a função matrix:
onde:
dataé um vetor de dados;nrowé o número de linhas;ncolé o número de colunas;byrowé um argumento lógico, ondeTRUEindica que a matriz deve ser preenchida por linhas, eFALSEindica que a matriz deve ser preenchida por colunas. Por padrão, a matriz é preenchida por colunas;dimnamesé um argumento opcional utilizado para definir os nomes da s linhas e das colunas através de uma lista.
Exemplo:
A <- matrix(c(3,-1,2,
4,1,0,
-2,0,3),
nrow = 3,
byrow = TRUE)
A [,1] [,2] [,3]
[1,] 3 -1 2
[2,] 4 1 0
[3,] -2 0 3
B <- matrix(c(2,1,3,
-1,0,5,
3,-1,1),
ncol = 3,
byrow = TRUE)
B [,1] [,2] [,3]
[1,] 2 1 3
[2,] -1 0 5
[3,] 3 -1 1
Para acessar o elemento \((i,j)\) de uma matrix A, faça A[i,j]. Por exemplo:
A[2,3][1] 0
A[2,][1] 4 1 0
A[,3][1] 2 0 3
A[2,3] <- 1
A [,1] [,2] [,3]
[1,] 3 -1 2
[2,] 4 1 1
[3,] -2 0 3
1.1 Operações ponto a ponto
Os símbolos +, -, *, / e ^ representam, respectivamente, as operações de adição, subtração, multiplicação, divisão e potenciação ponto a ponto. Ou seja, as operações são aplicadas a cada elemento da matriz. Por exemplo:
A+B [,1] [,2] [,3]
[1,] 5 0 5
[2,] 3 1 6
[3,] 1 -1 4
A-B [,1] [,2] [,3]
[1,] 1 -2 -1
[2,] 5 1 -4
[3,] -5 1 2
A*B [,1] [,2] [,3]
[1,] 6 -1 6
[2,] -4 0 5
[3,] -6 0 3
A/B [,1] [,2] [,3]
[1,] 1.5000000 -1 0.6666667
[2,] -4.0000000 Inf 0.2000000
[3,] -0.6666667 0 3.0000000
A^4 [,1] [,2] [,3]
[1,] 81 1 16
[2,] 256 1 1
[3,] 16 0 81
Em geral, funções matemáticas como log, exp, sin, cos e etc., quando aplicadas a matrizes numéricas, correspondem à aplicação dessas funções a cada elemeneto da matriz.
1.2 Obtendo outras informações de uma matriz
As funções dim, nrow e ncol retornam, respectivamente, um vetor com o número de linhas e o número de colunas de uma matriz, o número de linhas de uma matriz, e o número de colunas de uma matriz. Exemplo:
dim(A)[1] 3 3
nrow(A)[1] 3
ncol(A)[1] 3
O determinante de uma matriz quadrada é calculado através da função det. Exemplo:
det(A)[1] 27
det(B)[1] 29
Obtemos a transposta de uma matriz através da função t. Exemplo:
t(A) [,1] [,2] [,3]
[1,] 3 4 -2
[2,] -1 1 0
[3,] 2 1 3
t(B) [,1] [,2] [,3]
[1,] 2 -1 3
[2,] 1 0 -1
[3,] 3 5 1
t(t(A)) [,1] [,2] [,3]
[1,] 3 -1 2
[2,] 4 1 1
[3,] -2 0 3
A função diag pode ser usada para retornar a diagonal de uma matriz quadrada ou para criar uma matriz diagonal a partir de um vetor. Por exemplo:
diag(A)[1] 3 1 3
x <- diag(B)
x[1] 2 0 1
diag(x) [,1] [,2] [,3]
[1,] 2 0 0
[2,] 0 0 0
[3,] 0 0 1
diag(diag(A)) [,1] [,2] [,3]
[1,] 3 0 0
[2,] 0 1 0
[3,] 0 0 3
diag(5) [,1] [,2] [,3] [,4] [,5]
[1,] 1 0 0 0 0
[2,] 0 1 0 0 0
[3,] 0 0 1 0 0
[4,] 0 0 0 1 0
[5,] 0 0 0 0 1
1.3 Dando nomes às linhas e colunas
As funções rownames e colnames são úteis para atribuírmos nomes ou identificadores às linhas e colunas, respectivamente, de matrizes. Exemplo:
rownames(A) <- c("Eq1","Eq2","Eq3")
colnames(A) <- c("x","y","z")
A x y z
Eq1 3 -1 2
Eq2 4 1 1
Eq3 -2 0 3
1.4 Adicionando novas linhas e colunas
As funções cbind e rbind servem para concatenar novas colunas e novas linhas, respectivamente, a matrizes. Exemplo:
C <- rbind(B,c(3,1,-2))
C [,1] [,2] [,3]
[1,] 2 1 3
[2,] -1 0 5
[3,] 3 -1 1
[4,] 3 1 -2
D <- cbind(c(-2,-1,5),B)
D [,1] [,2] [,3] [,4]
[1,] -2 2 1 3
[2,] -1 -1 0 5
[3,] 5 3 -1 1
2 Multiplicação de matrizes
A multiplicação de matrizes é obtida através da função %*%. Vale ressaltar que, se temos duas matrizes \(A\) e \(B\), só é possível obter \(A\times B\) se o número de colunas de \(A\) for igual ao número de linhas de \(B\). Por exemplo:
A x y z
Eq1 3 -1 2
Eq2 4 1 1
Eq3 -2 0 3
B [,1] [,2] [,3]
[1,] 2 1 3
[2,] -1 0 5
[3,] 3 -1 1
A%*%B [,1] [,2] [,3]
Eq1 13 1 6
Eq2 10 3 18
Eq3 5 -5 -3
B%*%A x y z
[1,] 4 -1 14
[2,] -13 1 13
[3,] 3 -4 8
C [,1] [,2] [,3]
[1,] 2 1 3
[2,] -1 0 5
[3,] 3 -1 1
[4,] 3 1 -2
D [,1] [,2] [,3] [,4]
[1,] -2 2 1 3
[2,] -1 -1 0 5
[3,] 5 3 -1 1
C%*%D [,1] [,2] [,3] [,4]
[1,] 10 12 -1 14
[2,] 27 13 -6 2
[3,] 0 10 2 5
[4,] -17 -1 5 12
D%*%C [,1] [,2] [,3]
[1,] 6 0 -1
[2,] 14 4 -18
[3,] 7 7 27
Observe que a operação A%*%C não é possível, visto que \(A\) é de ordem \(3\times 3\) e \(C\) é de ordem \(4\times 3\). Nesse caso, uma mensagem de erro como Error in A %*% C : non-conformable arguments será retornada.
3 Matriz inversa e solução de sistemas de equações lineares
A inversa de uma matriz quadrada pode ser calculada através da função solve. Exemplo:
solve(A) Eq1 Eq2 Eq3
x 0.11111111 0.11111111 -0.1111111
y -0.51851852 0.48148148 0.1851852
z 0.07407407 0.07407407 0.2592593
solve(B) [,1] [,2] [,3]
[1,] 0.17241379 -0.1379310 0.17241379
[2,] 0.55172414 -0.2413793 -0.44827586
[3,] 0.03448276 0.1724138 0.03448276
solve(A)%*%A x y z
x 1.000000e+00 1.387779e-17 0.000000e+00
y 1.110223e-16 1.000000e+00 -5.551115e-17
z 0.000000e+00 0.000000e+00 1.000000e+00
A função solve também pode ser utilizada para obter a solução de uma sistema de equações lineares \(A\mathbf{x}=\mathbf{b}\), onde \(A_{(n\times n)}\) é a matriz de coeficientes, \(\mathbf{x}_{(n\times 1)}\) é o vetor de incógnitas (variáveis desconhecidas), e \(\mathbf{b}_{(n\times 1)}\) é o vetor de termos independentes. Por exemplo, resolver o sistema a seguir: \[\begin{align*}
\begin{cases}
2x + y - z = 3 \\
-x + 3y + 2z = 12 \\
3x + 2y + 4z = 9.
\end{cases}
\end{align*}\]
A solução desse sistema é dada por: \[ \begin{cases} x = \displaystyle -\frac{3}{37} \approx -0{,}0811 \\ y = \displaystyle \frac{135}{37} \approx 3{,}6486 \\ z = \displaystyle \frac{18}{37} \approx 0{,}4865. \end{cases} \]
Em R, fazemos:
A <- matrix(c(2,1,-1,
-1,3,2,
3,2,4), nrow = 3, byrow = TRUE)
A [,1] [,2] [,3]
[1,] 2 1 -1
[2,] -1 3 2
[3,] 3 2 4
b <- c(3,12,9)
b[1] 3 12 9
solve(A,b)[1] -0.08108108 3.64864865 0.48648649
4 Decomposições de matrizes
4.1 Decomposição em valores singulares
A decomposição em valores singulares é útil para a implementação de diversos métodos estatísticos. Por exemplo, ela é o motor por trás da análise de componentes principais, que permite representar dados em um espaço de menor dimensão, retendo a maior parte da variabilidade.
Uma matriz \(A\) de ordem \(n\times p\) pode ser escrita como \[ A=USV^\top, \] em que as matrizes \(U\) e \(V\) são ortogonais (unitárias) e \(S\) é uma matriz diagonal. Por exemplo:
A = matrix(c(2,0,
0,-3,
0,0), ncol=2, byrow=TRUE)
A [,1] [,2]
[1,] 2 0
[2,] 0 -3
[3,] 0 0
# Aplicando a decomposição:
svd.A <- svd(A)
svd.A$d
[1] 3 2
$u
[,1] [,2]
[1,] 0 1
[2,] 1 0
[3,] 0 0
$v
[,1] [,2]
[1,] 0 1
[2,] -1 0
U <- svd.A$u
V <- svd.A$v
S <- diag(svd.A$d)
U [,1] [,2]
[1,] 0 1
[2,] 1 0
[3,] 0 0
V [,1] [,2]
[1,] 0 1
[2,] -1 0
S [,1] [,2]
[1,] 3 0
[2,] 0 2
# Verificando que A = USV':
U%*%S%*%t(V) [,1] [,2]
[1,] 2 0
[2,] 0 -3
[3,] 0 0
4.2 Decomposição Espectral (Ou decomposição em Autovalores e Autovetores)
A decomposição em autovalores e autovetores também é uma importante ferramenta matemática utilizada na implementação de vários métodos estatísticos. Em análise de componentes principais, por exemplo, os autovalores indicam a variância em cada direção (componente principal), e os autovetores, a direção dessas variâncias, enquanto que q análise fatorial utiliza autovalores e autovetores para identificar estruturas latentes nos dados.
Dada uma matriz quadrada \(A\) (ordem \(n\times n\)), um autovetor \(\mathbf{x}\) é um vetor não nulo tal que, para algum escalar \(\lambda\) (real ou complexo), temos: \[ A\mathbf{x}=\mathbf{x}\lambda. \] Em outras palavras, sendo \(Q\) a matriz dos autovetores e \(\Lambda\) a matriz diagonal dos autovalores, temos que: \[ A=Q\Lambda Q^\top. \]
Por exemplo:
A = matrix(c(1,2,2,1), nrow=2, byrow=TRUE)
A [,1] [,2]
[1,] 1 2
[2,] 2 1
auto.vv = eigen(A)
auto.vv$values[1] 3 -1
auto.vv$vectors [,1] [,2]
[1,] 0.7071068 -0.7071068
[2,] 0.7071068 0.7071068
Vamos verificar que \(A\mathbf{x}=\mathbf{x}\lambda\):
x = auto.vv$vectors
lambda = auto.vv$values
A%*%x[,1] [,1]
[1,] 2.12132
[2,] 2.12132
x[,1]*lambda[1][1] 2.12132 2.12132
A%*%x[,2] [,1]
[1,] 0.7071068
[2,] -0.7071068
x[,2]*lambda[2][1] 0.7071068 -0.7071068
A%*%x [,1] [,2]
[1,] 2.12132 0.7071068
[2,] 2.12132 -0.7071068
x%*%diag(lambda) [,1] [,2]
[1,] 2.12132 0.7071068
[2,] 2.12132 -0.7071068
Equivalentemente, vamos verificar que \(A=Q\Lambda Q^\top\):
Q = auto.vv$vectors
Lambda = diag(lambda)
A [,1] [,2]
[1,] 1 2
[2,] 2 1
Q%*%Lambda%*%t(Q) [,1] [,2]
[1,] 1 2
[2,] 2 1
4.3 Decomposição de Cholesky
Outra decomposição importante para a estatística é a decomposição de Cholesky, a qual é utilizada, por exemplo, na geração de vetores de números aleatórios a partir da distribuição normal multivariada com uma matriz de covariância dada, em inferência utilizando Monte Carlo via Cadeias de Markov (MCMC), para amostragem eficiente, e no cálculo de verossimilhanças em modelos GARCH e hierárquicos, dentre outros.
A decomposição de Cholesky procura decompor uma matriz \(A\) na forma \(A = L^\top L\) , onde \(L\) é uma matriz triangular inferior com elementos da diagonal principal estritamente positivos. Para tanto, exige-se que a matriz \(A\) seja positiva definida. Uma matriz \(A\) é dita positiva definida se \(A\) é simétrica e se \(\mathbf{x}^\top A\mathbf{x} > 0\) para todo \(\mathbf{x}\neq 0\).
Exemplo:
A = matrix(c(4,2,0,
2,2,1,
0,1,2), nrow = 3, byrow=TRUE)
A [,1] [,2] [,3]
[1,] 4 2 0
[2,] 2 2 1
[3,] 0 1 2
# Decomposição de Cholesky
L = chol(A)
L [,1] [,2] [,3]
[1,] 2 1 0
[2,] 0 1 1
[3,] 0 0 1
Vamos verificar que \(A=L^\top L\):
A [,1] [,2] [,3]
[1,] 4 2 0
[2,] 2 2 1
[3,] 0 1 2
t(L)%*%L [,1] [,2] [,3]
[1,] 4 2 0
[2,] 2 2 1
[3,] 0 1 2
Vamos verificar também que \(L^{-1}L=I\)
solve(L)%*%L [,1] [,2] [,3]
[1,] 1 0 0
[2,] 0 1 0
[3,] 0 0 1
5 Exercícios
Resolva a lista de exercícios dada utilizando a linguagem R.