class: center, middle, inverse, title-slide .title[ # Métodos em Análise Multivariada (ME731) ] .subtitle[ ## Introdução à Análise Multivariada. ] .author[ ### Prof. Carlos Trucíos
ctruciosm.github.io
ctrucios@unicamp.br
] .institute[ ### Instituto de Matemática, Estatística e Computação Científica, Universidade Estadual de Campinas ] --- layout: true <a class="footer-link" href="http://ctruciosm.github.io">ctruciosm.github.io — Carlos Trucíos (IMECC/UNICAMP)</a> <style type="text/css"> .remark-slide-content { font-size: 26px; padding: 1em 3.5em 1em 3.5em; } </style> ---
<center> <img src="Aula_01_files/figure-html/unnamed-chunk-1-1.png" width="500" height="500" /> </center> --- <center> <img src="Aula_01_files/figure-html/unnamed-chunk-2-1.png" width="500" height="500" /> </center> --- ## Notação Sejam `\(\textbf{x}_1, \cdots, \textbf{x}_n\)` `\(n\)` observações `\(p\)`- dimensionais, ou seja `$$\textbf{x}_i = (x_{i1}, x_{i2}, \cdots, x_{ip})',$$` em que essas observações são realizações do vetor aleatório `\(p\)`-dimensional `\(\textbf{X} \in \mathbb{R}^p\)`, com `$$\textbf{X} = (X_1, X_2, \cdots, X_p)',$$` em que `\(X_1, X_2, \cdots, X_p\)` são variáveis aleatórias. Para todos os fins dessa matéria, vamos assumir que `\(\mathbb{E}(\textbf{X}) = \mu\)` e `\(\mathbb{V}(\textbf{X}) = \Sigma\)` são ambos finitos. --- ## Notação A matriz de dados será uma matriz de dimensão `\(n \times p\)` da forma: `$$\textbf{x} = \left( {\begin{array}{cccc} x_{11} & x_{12} & \cdots & x_{1p} \\ x_{21} & x_{22} & \cdots & x_{2p} \\ \vdots & \vdots & \ddots & \vdots \\ x_{n1} & x_{n2} & \cdots & x_{np} \\ \end{array} } \right) = \left( {\begin{array}{c} \textbf{x}_1^{\prime} \\ \vdots \\ \textbf{x}_n^{\prime} \\ \end{array} } \right) = (\textbf{x}_1, \cdots, \textbf{x}_n)'$$` `\(x_{ij}\)` é o valor da `\(j\)`-éssima coluna para a `\(i\)`-éssima observação. > Esta é a forma como usualmente "recebemos" os dados. --- ## Definição > .blue[**Análise Multivariada:** conjunto de técnicas utilizadas para analisar, entender e sumarizar dados de dimensão] `\(p \geq 2\)`. -- - **Redução de dimensão:** representar o _dataset_ com um menor número de _variáveis_ sem sacrificar informação*. - **Agrupamento:** de observações ou variáveis segundo as caracteristica semelhantes que elas possuem. - **Dependência entre variáveis:** Será que todas as variáveis são independentes? ou será que uma (ou mais) variáveis dependem de outras?. - **Predição:** predizer os valores de uma ou mais variáveis com base nos valores observados de outras variáveis. - **Classificação:** classificar novas observações em grupos pre-definidos com base nos valores de outras observações - **Teste de hipóteses:** formulado em termos dos parâmetros multivariados. --- class: inverse, right, middle # Datasets --- ### Swiss Bank Notes 6 características diferentes foram medidas em 200 notas antigas de 100 francos suíços. O conjunto de dados pode ser descarregado [aqui](https://raw.githubusercontent.com/ctruciosm/ctruciosm.github.io/master/datasets/swiss_bank_notes.csv). -- .pull-left[ - `\(X_1\)`: Comprimento da nota, - `\(X_2\)`: Altura do lado esquerdo da nota, - `\(X_3\)`: Altura do lado direito da nota, - `\(X_4\)`: Distância do quadro interno até a borda inferior - `\(X_5\)`: Distância do quadro interno até a borda superior, - `\(X_6\)`: Comprimento diagonal da nota. - `\(Y:\)` 1(falso) e 0(verdadeiro) ] .pull-right[ ![pensativo](imagens/1000_swiss_francs.png) ] --- ### Swiss Bank Notes ```r library(tidyr) library(dplyr) library(ggplot2) library(GGally) library(plotly) library(aplpack) library(misc3d) ``` -- ```r swiss_notes <- read.csv("./datasets/swiss_bank_notes.csv") head(swiss_notes) ``` ``` ## X1 X2 X3 X4 X5 X6 Y ## 1 214.8 131.0 131.1 9.0 9.7 141.0 0 ## 2 214.6 129.7 129.7 8.1 9.5 141.7 0 ## 3 214.8 129.7 129.7 8.7 9.6 142.2 0 ## 4 214.8 129.7 129.6 7.5 10.4 142.0 0 ## 5 215.0 129.6 129.7 10.4 7.7 141.8 0 ## 6 215.7 130.8 130.5 9.0 10.1 141.4 0 ``` --- ### Dataset: Swiss Bank Notes ```r swiss_notes <- swiss_notes %>% rename("comprimento" = "X1", "alt_esq" = "X2", "alt_dir" = "X3", "borda_inf" = "X4", "borda_sup" = "X5", "diagonal" = "X6") %>% mutate(Y = recode(Y, "0" = "Original", "1" = "Falso")) %>% mutate(Y = factor(Y)) glimpse(swiss_notes) ``` ``` ## Rows: 200 ## Columns: 7 ## $ comprimento <dbl> 214.8, 214.6, 214.8, 214.8, 215.0, 215.7, 215.5, 214.5, 21… ## $ alt_esq <dbl> 131.0, 129.7, 129.7, 129.7, 129.6, 130.8, 129.5, 129.6, 12… ## $ alt_dir <dbl> 131.1, 129.7, 129.7, 129.6, 129.7, 130.5, 129.7, 129.2, 12… ## $ borda_inf <dbl> 9.0, 8.1, 8.7, 7.5, 10.4, 9.0, 7.9, 7.2, 8.2, 9.2, 7.9, 7.… ## $ borda_sup <dbl> 9.7, 9.5, 9.6, 10.4, 7.7, 10.1, 9.6, 10.7, 11.0, 10.0, 11.… ## $ diagonal <dbl> 141.0, 141.7, 142.2, 142.0, 141.8, 141.4, 141.6, 141.7, 14… ## $ Y <fct> Original, Original, Original, Original, Original, Original… ``` --- class: inverse, right, middle # Análise Exploratoria de Dados Multivariados --- ## Análise Exploratoria de Dados .blue[Antes de tentar construir algum modelo, precisamos primeiro fazer uma Análise Exploratória de Dados (EDA).] -- **O que podemos esperar da EDA?** -- - São algumas variáveis mais dispersas do que outras? - Os dados indicam a existencia de sub-grupos? - Temos outliers? - Os dados são Normais? - As variáveis estão correlacionadas? Quanto? - etc --- ## Análise Explotarória de Dados **Quais estatísticas, tabelas ou gráficos seriam interessantes?** -- - Vetor de médias - Matriz de covariância/correlação - 2D/3D Scatterplots - Boxplot - Caras de Chernoff-Flury - Curvas de Andrews - Coordenadas Paralelas - Histogramas - Gráfico de densidades (Kernel) - etc, --- class: inverse, right, middle # Análise Exploratoria de Dados Multivariados: Métodos Gráficos. --- ## EDA: Boxplot .panelset[ .panel[.panel-name[Plot] ![](Aula_01_files/figure-html/unnamed-chunk-7-1.png)<!-- --> ] .panel[.panel-name[R Code] ```r swiss_notes_longer <- swiss_notes %>% pivot_longer(cols = c("comprimento", "alt_esq", "alt_dir", "borda_inf", "borda_sup", "diagonal"), names_to = "variaveis", values_to = "valores") swiss_notes_longer %>% ggplot() + geom_boxplot(aes(y = valores, x = Y, fill = Y)) + facet_wrap(.~ variaveis, scales = "free_y") ``` ]] --- ## EDA: Boxplot **Vantagens:** - Útil para ver locação (mediana), - Útil para ver assimetria (posição da mediana na caixa), - Útil para ver dispersão (comprimento da caixa e dos bigodes), - Útil para ver comprimento das caudas (comprimento dos bigodes) e - Útil para ver pontos discordantes. - **Bastante útil para comparar grupos.** -- **Desvantagens:** - Nos permite comparar apenas uma única variável ao mesmo tempo. - Não nos permite visualizar multimodalidade nem clusters* -- > Possiveis alternativas são [violin plots](https://chartio.com/learn/charts/violin-plot-complete-guide/) ou [bean plots](https://www.jstatsoft.org/article/view/v028c01). --- ## EDA: Densidades por Kernel .panelset[ .panel[.panel-name[Plot] ![](Aula_01_files/figure-html/unnamed-chunk-9-1.png)<!-- --> ] .panel[.panel-name[R Code] ```r swiss_notes_longer %>% ggplot() + geom_density(aes(x = valores, color = Y)) + facet_wrap(.~ variaveis, scales = "free") ``` ] .panel[.panel-name[Plot 2] ![](Aula_01_files/figure-html/unnamed-chunk-11-1.png)<!-- --> ]] --- ## EDA: Densidades por Kernel - Trazem uma ideia a respeito da distribuição dos dados. - Permite observar assimetria, dispersão e possíveis multimodalidades. - Utiliza uma função suavizada em lugar de apenas uma "caixa" (como nos histogramas). -- A forma geral do estimador Kernel é dada por `$$\hat{f}_h (x) = \dfrac{1}{n\times h} \displaystyle \sum_{i = 1}^n K\Big(\dfrac{x-x_i}{h} \Big).$$` -- > Diferentes Kernels ( `\(K(\cdot)\)` ) produzirão diferentes formas da densidade estimada. Ainda precisamos atribuir um valor apropriado para `\(h\)`. --- ## EDA: Densidades por Kernel Alguns dos Kernels mais utilizados são: - Uniforme: `\(K(u) = \frac{1}{2}I(|u| \leq 1)\)`, - Triangular: `\(K(u) = (1 - |u|) I(|u| \leq 1)\)` - Epanechnikov: `\(K(u) = \frac{3}{4} (1 - u^2) I(|u| \leq 1)\)`, - Biweight: `\(K(u) = \frac{15}{16} (1 - u^2)^2 I(|u| \leq 1)\)`, - Gaussiano: `\(K(u) = \frac{1}{\sqrt{2 \pi}} e^{-\frac{u^2}{2}}\)` -- > Existem formas de obter o melhor valor de `\(h\)` (por exemplo por validação-cruzada, embora este método seja demorado). Existem também regras de bolso que costumam funcionar bem na prática. Não nos preocuparemos com isso. --- ## EDA: Densidades por Kernel .panelset[ .panel[.panel-name[Densidades 2D] ![](Aula_01_files/figure-html/unnamed-chunk-12-1.png)<!-- --> ] .panel[.panel-name[Densidades 3D] ![](Aula_01_files/figure-html/unnamed-chunk-13-1.png)<!-- --> ] .panel[.panel-name[R Codes] ```r swiss_notes %>% ggplot(aes(x = borda_sup, y = diagonal)) + geom_density_2d() f <- kde3d(swiss_notes$borda_inf, swiss_notes$borda_sup, swiss_notes$diagonal, n = 15) contour3d(f$d, level = c(0.02, 0.04, 0.06), engine = "grid", fill = c(FALSE, FALSE, TRUE), col.mesh = c("green", "red", "blue")) ``` ]] --- ## EDA: Nuvem de pontos .panelset[ .panel[.panel-name[Plot 2D] ![](Aula_01_files/figure-html/unnamed-chunk-15-1.png)<!-- --> ] .panel[.panel-name[R Code 2D] ```r ggpairs(swiss_notes, columns = c("comprimento", "alt_esq", "alt_dir", "borda_inf", "borda_sup", "diagonal"), upper = list(continuous = "points"), lower = list(continuous = "points"), mapping = aes(color = Y)) ``` ] .panel[.panel-name[Plot 3D]
] .panel[.panel-name[R Code 3D] ```r plot_ly(x = swiss_notes$diagonal, y = swiss_notes$comprimento, z = swiss_notes$borda_inf, type = "scatter3d", mode = "markers", color = swiss_notes$Y) ``` ]] --- ## EDA: Nuvem de pontos - São gráficos bi ou tri variados de uma variável versus outra(s). - Ajudam a entender a relação entre as variáveis no conjunto de dados. - Úteis para identificar outliers ou sub-clusters - São bastante populares e fáceis de entender. -- **Desvantagens:** - Apenas é possível comparar varíaveis 2 a 2 (ou 3 a 3) - A medida que `\(p\)` cresce, sequências de nuvens de pontos são difíceis de interpretar. - Se tivermos várias observações, digamos `\(x = (2, 3)\)`, aparecerão todas como um único ponto sobreposto (embora existam formas de lidar com isso) --- ## EDA: Caras de Chernoff-Flury .panelset[ .panel[.panel-name[Plot] ![](Aula_01_files/figure-html/unnamed-chunk-19-1.png)<!-- --> ``` ## effect of variables: ## modified item Var ## "height of face " "comprimento" ## "width of face " "alt_esq" ## "structure of face" "alt_dir" ## "height of mouth " "borda_inf" ## "width of mouth " "borda_sup" ## "smiling " "diagonal" ## "height of eyes " "comprimento" ## "width of eyes " "alt_esq" ## "height of hair " "alt_dir" ## "width of hair " "borda_inf" ## "style of hair " "borda_sup" ## "height of nose " "diagonal" ## "width of nose " "comprimento" ## "width of ear " "alt_esq" ## "height of ear " "alt_dir" ``` ] .panel[.panel-name[R Code] ```r faces(swiss_notes[1:25, 1:6]) ``` ]] --- ## EDA: Caras de Chernoff-Flury - A medida que `\(p\)` cresce, é mais difícil visualizar as observações em 2D ou mesmo 3D. - Se quisermos visualizar as observações `\(p\)`-dimensionais em 2D, precisamos utilizar procedimentos alternativos, como por exemplo, as caras de Chernoff-Flury. - As caras de Chernoff-Flury ([Chernoff 1973](https://www.tandfonline.com/doi/abs/10.1080/01621459.1973.10482434) e [Flury and Riedwyl 1988](https://www.amazon.com/Multivariate-Statistics-Practical-Bernhard-Flury/dp/9401070415)) permitem representar dados multidimensionais em caras/rostos. - Permite identificar outliers. - Permite identificar sub-clusters. -- **Desvantagens:** - Se tivermos muitas observações, fica bastante difícil diferenciar (ou mesmo visualizar em uma única folha) as caras. - Pode ser utilizado apenas em dimensões moderadas --- ## EDA: Curvas de Andrews .panelset[ .panel[.panel-name[Plot] ![](Aula_01_files/figure-html/unnamed-chunk-21-1.png)<!-- --> ] .panel[.panel-name[R Code] ```r andrews_curve <- function(x){ p <- ncol(x); n <- nrow(x) t <- seq(0, 2*pi, by = 0.01) nt <- length(t) z <- x for (l in 1:p) { z[, l] = (x[, l] - min(x[, l]))/(max(x[, l]) - min(x[, l])) } f <- z[,1]/sqrt(2)*matrix(1, ncol = nt, nrow = n) for (i in seq(2, p, by = 2)) { f <- f + z[,i]*matrix(sin((i/2)*t), ncol = nt, nrow = n, byrow = TRUE) if (i + 1 <= p) f <- f + z[, i + 1]*matrix(cos((i/2)*t), ncol = nt, nrow = n, byrow = TRUE) } r <- data.frame(t(f)) r$t <- t r <- r %>% pivot_longer(cols = 1:n, names_to = "rows", values_to = "values") return(r) } A <- andrews_curve(swiss_notes[,1:6]) ggplot(A, aes(x = t, y = values, color = rows)) + geom_line() + theme(legend.position = "none") ``` ]] --- ## EDA: Curvas de Andrews - Elas permitem representar observações multidimensionais em curvas e não mais em rostos (são uma alternativas às caras de Chernoff-Flury). - As curvas são obtidas da seguinte forma: -- `$$f_i(t)= \frac{X_{i1}}{\sqrt{2}} + X_{i2} \sin(t) + X_{i3} \cos(t) + \cdots + X_{ip} \sin(\frac{p}{2}t)$$` -- > **A ordem das variáveis é importante**, repare que se as últimas variáveis terão uma pequena contribuição na curva (caem na parte de alta frequência da curva). -- [Existem modificações da função apresentada acima](https://rdrr.io/cran/andrews/man/andrews.html). -- > **Obs:** para melhor visualização levar as variáveis para uma escala 0-1 --- ## EDA: Coordenadas paralelas .panelset[ .panel[.panel-name[Plot 1] ![](Aula_01_files/figure-html/unnamed-chunk-23-1.png)<!-- --> ] .panel[.panel-name[R Code] ```r ggparcoord(swiss_notes, columns = 1:6, groupColumn = "Y", scale = "uniminmax") ``` ]] --- ## EDA: Coordenadas paralelas A ideia é olhar todas as variáveis de uma vez em uma plano bidimentional. Para isto, tracejamos retas em coordenadas paralelas da seguinte forma: -- - Cada variável é um eixo (teremos tantos eixos paralelos quanto variáveis disponíveis). - Transformar as variáveis para todas terem `\(max = 1\)` e `\(min = 0\)`. - Na nova escala (0-1), localizar o valor de cada observação (em cada uma das variáveis) em cada eixo. - Unir os pontos com linhas retas. -- > Utilizado para detectar sub-clusters, relações lineares e outliers. --- ## EDA: Coordenadas paralelas .panelset[ .panel[.panel-name[Rel Linear 1] ```r ggparcoord(car_data, columns = c(8, 11), groupColumn = "procedencia", scale = "uniminmax") ``` ![](Aula_01_files/figure-html/unnamed-chunk-25-1.png)<!-- --> ```r cor(car_data[, c(8, 11)])[1,2] ``` ``` ## [1] 0.9006063 ``` ] .panel[.panel-name[Rel Linear 2] ```r ggparcoord(car_data, columns = c(2, 8), groupColumn = "procedencia", scale = "uniminmax") ``` ![](Aula_01_files/figure-html/unnamed-chunk-26-1.png)<!-- --> ```r cor(car_data[, c(2, 8)])[1,2] ``` ``` ## [1] -0.8228964 ``` ] .panel[.panel-name[Outliers] ```r ggparcoord(car_data, columns = 5:7, groupColumn = "procedencia", scale = "uniminmax") ``` ![](Aula_01_files/figure-html/unnamed-chunk-27-1.png)<!-- --> ]] --- class: inverse, right, middle # Análise Exploratoria de Dados Multivariados: Estatísticas Resumo. --- ## Vetor de médias Seja `\(\bar{x}_i = \dfrac{1}{n}\displaystyle \sum_{k = 1}^nx_{ki}\)` a média amostral da `\(i\)`-ésima variável. O vetor de médias amostrais é dado por `$$\bar{\textbf{x}} = (\bar{x}_1, \cdots, \bar{x}_p)' = \dfrac{1}{n} \displaystyle \sum_{i = 1}^n \textbf{x}_i = \dfrac{1}{n} \textbf{x}' \textbf{1},$$` em que `\(\textbf{1}\)` é o vetor coluna de tamanho `\(n\)` com todos os elementos iguais a 1. --- ## Vetor de médias ```r swiss_notes %>% group_by(Y) %>% summarise_if(is.numeric, mean) ``` ``` ## # A tibble: 2 × 7 ## Y comprimento alt_esq alt_dir borda_inf borda_sup diagonal ## <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 Falso 215. 130. 130. 10.5 11.1 139. ## 2 Original 215. 130. 130. 8.30 10.2 142. ``` --- ## Matriz de covariância e correlação As matrizes de covariância e correlação amostral são, respectivamente, `$$S = \dfrac{1}{n} \displaystyle \sum_{i = 1}^n (\textbf{x}_i - \bar{\textbf{x}})(\textbf{x}_i - \bar{\textbf{x}})' \quad \text{e} \quad R = D^{-1/2}SD^{-1/2},$$` em que `\(\textbf{x}_i = (x_{i1}, \cdots, x_{ip})'\)`, `\(\bar{\textbf{x}} = (\bar{x}_1, \cdots, \bar{x}_p)'\)` e `\(D = Diag(S)\)`. -- Pode-se mostrar que, `$$S= \dfrac{1}{n} \textbf{x}' \underbrace{(\textbf{I} - \dfrac{1}{n} \textbf{1}\textbf{1}')}_{\textbf{H}} \textbf{x} = \dfrac{1}{n} \textbf{x}'\textbf{H}\textbf{x}.$$` --- ## Matriz de covariância e correlação ```r swiss_notes %>% select(-Y) %>% cor() %>% round(3) ``` ``` ## comprimento alt_esq alt_dir borda_inf borda_sup diagonal ## comprimento 1.000 0.231 0.152 -0.190 -0.061 0.194 ## alt_esq 0.231 1.000 0.743 0.414 0.362 -0.503 ## alt_dir 0.152 0.743 1.000 0.487 0.401 -0.516 ## borda_inf -0.190 0.414 0.487 1.000 0.142 -0.623 ## borda_sup -0.061 0.362 0.401 0.142 1.000 -0.594 ## diagonal 0.194 -0.503 -0.516 -0.623 -0.594 1.000 ``` --- ## Outras medidas resumo - Variância generalizada `\(|S|\)`. - Variância total `\(Tr(S)\)` - Variância efeitva `\(|S|^{1/p}\)` - Coeficiente de assimetria multivariado `\(A_p = \dfrac{1}{n^2} \displaystyle \sum_{i = 1}^n \sum_{j = 1}^n d_{ij}^3.\)` - Coeficiente de curtose multivariado `\(K_p = \dfrac{1}{n} \displaystyle \sum_{i=1}^n d_{ii}^2.\)` (em que `\(d_{ij} = (\textbf{x}_i - \bar{\textbf{x}})'S^{-1}(\textbf{x}_j - \bar{\textbf{x}})\)` é a distância de Mahalanobis). --- ### Referências - [Härdle, W. K., & Simar, L. (2019). Applied Multivariate Statistical Analysis. Fifth Editon. Springer Nature.](https://link.springer.com/book/10.1007/978-3-030-26006-4) Capítulo 1 - Koch, I. (2013). Analysis of multivariate and high-dimensional data (Vol. 32). Cambridge University Press. Capítulo 1 - Mardia, K. V., Kent, J. T., & Bibby, J, M. (1979). Multivariate Analysis. Academic Press. Capítulo 1 -- > Dica: Faça uma revisão de algebra matricial antes da próxima aula (propriedades de determinante, traço, partição de matrizes, etc.)