rm(list=ls(all=TRUE)) #limpa a memória
Tutorial R Módulo 6. Análise de outliers baseada no desvio padrão do centróide
Disciplina de Ecologia Numérica1
1 Organização básica
Instalando os pacotes necessários para esse módulo
install.packages("openxlsx") #importa arquivos do excel
install.packages("moments") #calcula assimetria e curtose dos dados
install.packages("matrixStats") #fornece funções rápidas para a estatística de matrizes
install.packages("gt") #ferramenta para criação de tabelas bonitas e personalizáveis
library(openxlsx)
Os códigos acima, são usados para instalar e carregar os pacotes necessários para este módulo. Esses códigos são comandos para instalar pacotes no R. Um pacote é uma coleção de funções, dados e documentação que ampliam as capacidades do R (R CRAN e RStudio). No exemplo acima, o pacote openxlsx
permite ler e escrever arquivos Excel no R. Para instalar um pacote no R, você precisa usar a função install.packages()
.
Depois de instalar um pacote, você precisa carregá-lo na sua sessão R com a função library()
. Por exemplo, para carregar o pacote openxlsx
, você precisa executar a função library(openxlsx)
. Isso irá permitir que você use as funções do pacote na sua sessão R. Você precisa carregar um pacote toda vez que iniciar uma nova sessão R e quiser usar um pacote instalado.
Agora vamos definir o diretório de trabalho. Esse código é usado para obter e definir o diretório de trabalho atual no R. O comando getwd()
retorna o caminho do diretório onde o R está lendo e salvando arquivos. O comando setwd()
muda esse diretório de trabalho para o caminho especificado entre aspas. No seu caso, você deve ajustar o caminho para o seu próprio diretório de trabalho. Lembre de usar a barra “/” entre os diretórios. E não a contra-barra “\”.
Definindo o diretório de trabalho e installando os pacotes necessários:
getwd()
setwd("C:/Seu/Diretório/De/Trabalho")
Alternativamente você pode ir na barra de tarefas e escolhes as opções:
SESSION -> SET WORKING DIRECTORY -> CHOOSE DIRECTORY
1.1 Sobre os dados do PPBio
A planilha ppbio
contém os dados de abundância de espécies em diferentes unidades amostrais (UA’s) (Figura 1) (Veja Programa de Pesquisa em Biodiversidade – PPBio). Essa é a matriz bruta de dados, porque os valores ainda não foram ajustados para os valores de Captura Por Unidade de Esforço (CPUE), nem foram relativizados ou transformados (Tabela 1).
Arquivo (.xlsx) | Tipo de matriz | Descrição | Tipo de dados |
---|---|---|---|
ppbio06c | Matriz comunitária | O arquivo ppbio06 traz os dados brutos que serão usados nas análises. A matriz de dados brutos contendo 26 localidades em estações do ano diferentes (objetos) x 35 espécies (atributos), antes de qualquer modificação. | Contagens de indivíduos com alta amplitude de variação, sugerido uso de matriz relativizada. |
ppbio06h | Matriz ambiental | O arquivo ppbio06h traz os dados brutos que serão usados nas análises. A matriz de dados brutos contendo 26 localidades em estações diferentes (objetos) x 35 variáveis ambienteis (atributos) medidas em diferentes escalas espaciais, antes de qualquer modificação. | Unidades de medição diferentes (cm, m, °C, mg/L, etc.), com uma alta amplitude de variação, sugerido uso de matriz transformada e/ou reescalada. |
ppbio06 | Matriz comunitária | O arquivo ppbio06 traz os dados brutos que serão usados nessa análise. A matriz de dados brutos contendo 26 locais/ocasiões (objetos) x 35 espécies (atributos), antes de qualquer modificação. | Contagens de indivíduos com alta amplitude de variação, sugerido uso de matriz relativizada. |
ppbio06cpue | Matriz comunitária | O arquivo ppbio06cpue traz os valores depois de terem sidos ajustados pela Captura Por Unidade de Esforço (CPUE), onde o número de indivíduos de cada espécie em uma determinada UA é dividido pelo esforço de captura daquela UA. Isso significa que os dados foram relativizados pela CPUE. A matriz de dados brutos contendo 26 localidades em estações do ano diferentes (objetos) x 35 espécies (atributos), antes de qualquer modificação. | Densidades de indivíduos (no. de indivíduos por Unidade de Esforço de Captura) com alta amplitude de variação, sugerido uso de matriz relativizada. |
Várias das espécies nessa matriz tem grande importância ecológica, como é o caso de Astyanax bimaculatus 2 (Figura 2), que é muito comum em rios intermitentes e serve de alimento para predadores maiores como a espécie Hoplias malabaricus 3 (Figura 3).
1.2 Importando a planilha de trabalho
Note que o sómbolo #
em programação R significa que o texto que vem depois dele é um comentário e não será executado pelo programa. Isso é útil para explicar o código ou deixar anotações. Ajuste a segunda linha do código abaixo para refletir “C:/Seu/Diretório/De/Trabalho/Planilha.xlsx”.
library(openxlsx)
<- read.xlsx("D:/Elvio/OneDrive/Disciplinas/_EcoNumerica/5.Matrizes/ppbio06.xlsx",
ppbio rowNames = T,
colNames = T,
sheet = "Sheet1")
str(ppbio)
<- as.matrix(ppbio) #lê ppbio como uma matriz
ppbio_ma str(ppbio_ma)
#ppbio
#ppbio_ma
1.3 Reset point
1#ppbio <- (ppbiopart2)
- 1
- Aqui usaremos as matrizes relativizadas/transformadas/particionadas
Podemos exibir a planilha depois de ter sido importada para o ambiente R/RStudio usando as funções View()
, print()
ou head()
. Note que essas funções são case-sensitive. A função ignore.case()
é uma função do pacote stringr que modifica um padrão para que ele não considere o caso das letras nas correspondências. Por exemplo, se você quiser encontrar todas as ocorrências da letra “a” em um vetor de caracteres, independente de ser “A” ou “a”, você pode usar essa função.
#View(ppbio)
print(ppbio)
head(ppbio)
A função head()
no RStudio é uma forma de ver as primeiras (n=6) linhas de um objeto, como um vetor, uma matriz, um data frame ou uma lista. Ela é útil para ter uma ideia do conteúdo e da estrutura do objeto.
Também podemos explorar as características da planilha usando as funções str()
, mode()
, class()
e length()
. O número de observações ou tamanho do vetor depende do tipo de dados, se eles são uma matrix
ou um data.frame
.
str(ppbio)
mode(ppbio)
class(ppbio)
#?str
'data.frame': 26 obs. of 35 variables:
$ ap-davis : num 0 0 0 0 0 0 0 0 0 0 ...
$ as-bimac : num 1 99 194 19 23 142 5 46 206 16 ...
$ as-fasci : num 0 0 55 0 1 3 1 0 64 0 ...
$ ch-bimac : num 0 0 0 0 13 3 0 178 0 0 ...
$ ci-ocela : num 0 0 0 0 0 0 40 0 0 13 ...
$ ci-orien : num 0 0 5 0 0 69 9 0 25 24 ...
$ co-macro : num 0 0 0 0 0 0 0 0 0 0 ...
$ co-heter : num 0 0 1 0 0 0 0 0 0 0 ...
$ cr-menez : num 0 0 14 0 0 4 0 0 8 0 ...
$ cu-lepid : num 0 0 0 0 0 0 0 0 0 0 ...
$ cy-gilbe : num 0 0 0 0 0 0 0 0 0 0 ...
$ ge-brasi : num 0 0 3 0 0 0 0 0 1 0 ...
$ he-margi : num 0 0 0 0 0 1 0 0 0 0 ...
$ ho-malab : num 0 0 1 5 0 17 10 2 31 4 ...
$ hy-pusar : num 0 0 9 2 0 43 2 0 11 0 ...
$ le-melan : num 0 0 0 0 0 0 0 0 0 0 ...
$ le-piau : num 0 0 3 0 0 1 3 0 2 1 ...
$ le-taeni : num 0 0 0 0 0 0 0 0 0 0 ...
$ mo-costa : num 0 0 0 0 0 0 0 0 0 0 ...
$ mo-lepid : num 0 1 39 0 0 1 0 0 0 0 ...
$ or-nilot : num 0 2 36 0 0 77 0 0 138 0 ...
$ pa-manag : num 0 0 0 0 0 0 0 0 0 0 ...
$ pimel-sp : num 0 0 6 0 0 0 0 0 0 0 ...
$ po-retic : num 0 0 0 0 0 20 0 0 5 0 ...
$ po-vivip : num 0 0 47 15 0 221 32 0 326 10 ...
$ pr-brevi : num 9 0 5 0 1 15 5 2 164 0 ...
$ ps-rhomb : num 0 0 0 0 0 0 0 0 1 0 ...
$ ps-genise: num 0 0 0 0 0 0 0 0 1 0 ...
$ se-heter : num 0 0 40 14 4 60 0 0 38 0 ...
$ se-piaba : num 0 0 68 0 0 0 0 0 0 0 ...
$ se-spilo : num 0 0 0 0 0 0 0 0 1 0 ...
$ st-noton : num 0 0 1 0 0 25 0 0 115 0 ...
$ sy-marmo : num 0 0 0 0 0 0 1 0 0 0 ...
$ te-chalc : num 0 0 0 0 0 0 0 0 0 0 ...
$ tr-signa : num 0 0 18 0 0 15 0 0 7 0 ...
[1] "list"
[1] "data.frame"
O símbolo ?
é usado para acessar a documentação de uma função ou um pacote no R. Como mostrado acima você pode saber mais sobre a função str()
, usando o comando ?str
. Isso vai abrir uma página no menu de ajuda com a descrição, os argumentos, os valores de retorno e os exemplos da função str()
. Você também pode usar o símbolo ?
para obter informações sobre um pacote inteiro. Por exemplo, se você quiser saber mais sobre o pacote openxlsx
, você pode digitar ?openxlsx
. Isso vai abrir uma página com a visão geral, a instalação, os recursos e as referências do pacote solicitado.
Podemos agora calcular o número e a proporção de zeros na matriz usando as funções sum()
e length()
(Você pode pesquisar o que faz a função length()
usando o comando ?length
).
2 Tamanho da matriz
range(ppbio) #menor e maior valores
length(ppbio) #no. de colunas
ncol(ppbio) #no. de N colunas
nrow(ppbio) #no. de M linhas
sum(lengths(ppbio)) #soma os nos. de colunas
length(as.matrix(ppbio)) #tamanho da matriz m x n
sum(ppbio == 0) # número de observações igual a zero
sum(ppbio > 0) # número de observações maiores que zero
<- (sum(ppbio == 0)/length(as.matrix(ppbio)))*100 # proporção de zeros na matriz
zeros zeros
[1] 0 511
[1] 35
[1] 35
[1] 26
[1] 910
[1] 910
[1] 716
[1] 194
[1] 78.68132
Tabela que resume as informações geradas (Tabela 2).
<- data.frame(
tamanho = c("range", "lenght", "m cols", "n linhas", "Tamanho", "Tamanho",
Função "Zeros", "Nao zeros", "% Zeros"),
Resultado = c(paste(range(ppbio), collapse = " - "), length(ppbio), ncol(ppbio),
nrow(ppbio), sum(lengths(ppbio)), length(as.matrix(ppbio)), sum(ppbio == 0),
sum(ppbio > 0), round(zeros, 1))
) tamanho
Função Resultado
1 range 0 - 511
2 lenght 35
3 m cols 35
4 n linhas 26
5 Tamanho 910
6 Tamanho 910
7 Zeros 716
8 Nao zeros 194
9 % Zeros 78.7
Função | Resultado |
---|---|
range | 0 - 511 |
lenght | 35 |
m cols | 35 |
n linhas | 26 |
Tamanho | 910 |
Tamanho | 910 |
Zeros | 716 |
Nao zeros | 194 |
% Zeros | 78.7 |
Ou seja, temos uma matriz de tamanho m x n
igual a 26 objetos por 35 atributos, onde 78.68% dos valores da matriz são iguais a zero!
3 Cálculo de matriz de distâncias Euclidiana (euclid
)
Agora vamos calcular a matriz de distâncias euclidianas (Legendre e Legendre 1998, Borcard et al. 2018) entre as UA´s usando a função dist()
(pesquise o que faz essa função usando o comando ?dist
).
<- dist(ppbio, method = "euclidian", diag = TRUE, upper = FALSE)
euclid #?dist
Pronto, calculamos a matriz de distâncias (Euclidiana). Agora podemos visualizar a matriz.
#euclid
str(euclid)
mode(euclid)
class(euclid)
length(as.matrix(euclid))
'dist' num [1:325] 98.4 228.5 29.2 27.1 294.1 ...
- attr(*, "Size")= int 26
- attr(*, "Labels")= chr [1:26] "S-A-ZA1" "S-R-CC1" "S-R-CT1" "S-R-CP1" ...
- attr(*, "Diag")= logi TRUE
- attr(*, "Upper")= logi FALSE
- attr(*, "method")= chr "euclidean"
- attr(*, "call")= language dist(x = ppbio, method = "euclidian", diag = TRUE, upper = FALSE)
[1] "numeric"
[1] "dist"
[1] 676
Uma matriz do tipo dist
no R é um objeto que armazena as distâncias entre as linhas de uma matriz ou um data frame. Ela é criada pela função dist()
, que calcula as distâncias usando diferentes medidas, como “euclidean”, “manhattan”, “canberra”, “binary” ou “minkowski” (Horton e Kleinman 2015) (Tabela 3).
Distância | Descrição |
---|---|
Euclidiana | Mede a distância entre dois pontos no espaço, seguindo o teorema de Pitágoras. É uma medida de distância direta entre dois pontos. |
Manhattan | Também conhecida como distância da cidade, mede a distância como se estivesse dirigindo em uma cidade. A distância é a soma das diferenças absolutas de cada coordenada. |
Canberra | Leva em consideração a proporção de diferenças em relação ao tamanho total das variáveis. |
Binária | Mede a semelhança entre dois objetos. É 0 quando dois valores são iguais e 1 caso contrário. |
Minkowski | É uma generalização da distância euclidiana e da distância de Manhattan. A distância é controlada por um parâmetro P, que determina a ordem da distância. |
Note que a matriz euclid
está como uma classe dist
.
str(euclid)
mode(euclid)
class(euclid)
as.matrix(euclid)[1:6, 1:6] #mostra as 5 primeiras linhas e colunas da matriz
'dist' num [1:325] 98.4 228.5 29.2 27.1 294.1 ...
- attr(*, "Size")= int 26
- attr(*, "Labels")= chr [1:26] "S-A-ZA1" "S-R-CC1" "S-R-CT1" "S-R-CP1" ...
- attr(*, "Diag")= logi TRUE
- attr(*, "Upper")= logi FALSE
- attr(*, "method")= chr "euclidean"
- attr(*, "call")= language dist(x = ppbio, method = "euclidian", diag = TRUE, upper = FALSE)
[1] "numeric"
[1] "dist"
S-A-ZA1 S-R-CC1 S-R-CT1 S-R-CP1 S-A-TA1 S-R-CT2
S-A-ZA1 0.00000 98.43780 228.5235 29.24038 27.09243 294.0629
S-R-CC1 98.43780 0.00000 154.2433 82.79493 77.25283 261.3905
S-R-CT1 228.52352 154.24331 0.0000 208.52338 209.69263 224.9133
S-R-CP1 29.24038 82.79493 208.5234 0.00000 23.25941 271.4922
S-A-TA1 27.09243 77.25283 209.6926 23.25941 0.00000 283.7869
S-R-CT2 294.06292 261.39051 224.9133 271.49217 283.78689 0.0000
Visualizando a matriz de distâncias, observamos que ela é uma matriz quadrada que contém as distâncias entre cada par de elementos do conjuto de dados. A matriz de distâncias terá dimensão m x m (m=linhas, n=colunas), e cada elemento da matriz será a distância entre cada par de observações ou objetos. A matriz de distâncias é simétrica, pois a distância entre i e j é igual à distância entre j e i. A matriz de distâncias também tem diagonal zero, pois a distância entre uma observação e ela mesma é zero.
4 Calculando o centróide da matriz de distâncias euclid
Primeiro algumas informações básicas da matriz
range(ppbio)
range(euclid)
min(euclid)
max(euclid)
mean(euclid) #CENTROIDE!! OU Grand mean
sd(euclid) #Standard deviation
<- mean(euclid)
centroide centroide
[1] 0 511
[1] 16.27882 707.32666
[1] 16.27882
[1] 707.3267
[1] 285.9043
[1] 172.9708
[1] 285.9043
A função mean()
calcula a média de todos os valores da matriz de distâncias, ou seja, a média multivariada, que é o centróide. Nesse caso o centroide assume o valor de 285.9.
Usamos agora a fórmula m*(m-1)/2
, onde m
é o no. de objetos sendo comparados, para calcular quantas distâcias temos na nossa matriz.
length(euclid)
<- nrow(ppbio)
m
m*(m-1)/2
msummary(euclid)
[1] 325
[1] 26
[1] 325
Min. 1st Qu. Median Mean 3rd Qu. Max.
16.28 142.70 242.82 285.90 423.64 707.33
Temos então que m é 26 objetos (ou linhas), e portanto, a matriz de distâncias tem 325 valores.
Fazemos agora um breve sumário do que foi calculado até agora com base na matriz de distâncias euclid
.
<- cbind(min(euclid),
Sumario1 max(euclid),
sd(euclid),
mean(euclid),
length(euclid))
colnames(Sumario1) <- c("Minimo", "Maximo", "Desv.Padr", "Media", "m(m-1)/2")
rownames(Sumario1) <- ("Valores")
Sumario1
Minimo Maximo Desv.Padr Media m(m-1)/2
Valores 16.27882 707.3267 172.9708 285.9043 325
5 Distribuição de frequências da matriz de distâncias euclid
O código abaixo vai plotar um histograma e um boxplot da distribuição de dados armazenada em euclid
. Também é adicionada uma curva normal teórica ao histograma utilizando a média e o desvio padrão dos dados (Figura 4). Atente que o comando par(mfrow=c(2,1))
define o layout dos gráficos, especificando que serão plotados 2 gráficos em uma coluna. As funções floor(min(euclid)), ceiling(max(euclid))
definem os limites dos graficos pelo valores mínimo e máximo do objeto (euclid
).
range(euclid)
[1] 16.27882 707.32666
par(mfrow=c(2,1))
hist(euclid,
breaks = 15, #determina o no. de colunas do histograma
xlim = range(floor(min(euclid)), ceiling(max(euclid))),
xlab = "Distr. de Frequências",
freq = FALSE)
curve(dnorm(x, mean=mean(euclid), sd=sd(euclid)), add=TRUE)
boxplot.default(euclid, horizontal = TRUE, frame = FALSE,
xlab="Distr. de Frequências",
ylim=c(floor(min(euclid)), ceiling(max(euclid)))) #Limites do eixo Y
euclid
O comando abaixo apaga os gráficos, use-o apenas se necessário.
dev.off()
6 Distribuição de frequências da matriz de distâncias as.matrix()
(sem os zeros)
A matriz euclid
está como uma classe dist
, mas podemos transformá-la em uma classe matrix
usando a função as.matrix()
.
<- (as.matrix(euclid))
euclid_ma #View(euclid_ma)
str(euclid_ma)
mode(euclid_ma)
class(euclid_ma)
1:5, 1:5] #mostra as 5 primeiras linhas e colunas da matriz euclid_ma[
num [1:26, 1:26] 0 98.4 228.5 29.2 27.1 ...
- attr(*, "dimnames")=List of 2
..$ : chr [1:26] "S-A-ZA1" "S-R-CC1" "S-R-CT1" "S-R-CP1" ...
..$ : chr [1:26] "S-A-ZA1" "S-R-CC1" "S-R-CT1" "S-R-CP1" ...
[1] "numeric"
[1] "matrix" "array"
S-A-ZA1 S-R-CC1 S-R-CT1 S-R-CP1 S-A-TA1
S-A-ZA1 0.00000 98.43780 228.5235 29.24038 27.09243
S-R-CC1 98.43780 0.00000 154.2433 82.79493 77.25283
S-R-CT1 228.52352 154.24331 0.0000 208.52338 209.69263
S-R-CP1 29.24038 82.79493 208.5234 0.00000 23.25941
S-A-TA1 27.09243 77.25283 209.6926 23.25941 0.00000
Assim como o caso da matriz euclid
, visualizando a matriz de distâncias, observamos que ela:
é uma matriz quadrada que contém as distâncias entre cada par de elementos do conjuto de dados;
terá a dimensão m x m;
e cada elemento da matriz será a distância entre cada par de observações ou objetos.
A matriz de distâncias é simétrica, pois a distância entre i e j é igual à distância entre j e i. A matriz de distâncias também tem diagonal zero, pois a distância entre uma observação e ela mesma é zero.
7 Calculando o centróide da matriz de distâncias as.matrix
Primeiro algumas informações básicas da matriz
range(euclid_ma)
min(euclid_ma)
max(euclid_ma)
mean(euclid_ma) #CENTROIDE!! OU Grand mean
sd(euclid_ma) #Standard deviation
<- mean(euclid_ma)
centroide_ma centroide_ma
[1] 0.0000 707.3267
[1] 0
[1] 707.3267
[1] 274.908
[1] 178.1842
[1] 274.908
A função mean()
calcula a média de todos os valores da matriz de distâncias, ou seja, a média multivariada, que é o centroide. Nesse caso o centróide assume o valor de 274.9.
Usamos agora a fórmula m*(m-1)/2
, onde m
é o no. de objetos sendo comparados, para calcular quantas distâcias temos na nossa matriz.
length(euclid_ma) #tamanho da matriz
<- nrow(ppbio_ma) #no. de linhas em ppbio_ma
m2
m2*(m2-1)/2
m2summary(euclid_ma)
[1] 676
[1] 26
[1] 325
S-A-ZA1 S-R-CC1 S-R-CT1 S-R-CP1
Min. : 0.00 Min. : 0.00 Min. : 0.0 Min. : 0.00
1st Qu.: 60.45 1st Qu.: 98.17 1st Qu.:211.1 1st Qu.: 54.38
Median :135.66 Median :140.77 Median :228.4 Median :125.07
Mean :194.48 Mean :198.07 Mean :256.1 Mean :188.25
3rd Qu.:278.14 3rd Qu.:257.14 3rd Qu.:283.9 3rd Qu.:261.35
Max. :641.28 Max. :612.29 Max. :595.5 Max. :631.37
S-A-TA1 S-R-CT2 S-R-CP2 S-A-TA2
Min. : 0.00 Min. : 0.0 Min. : 0.00 Min. : 0.0
1st Qu.: 62.68 1st Qu.:264.5 1st Qu.: 59.32 1st Qu.:185.9
Median :126.97 Median :292.2 Median :141.65 Median :201.9
Mean :188.32 Mean :304.9 Mean :199.18 Mean :258.2
3rd Qu.:270.46 3rd Qu.:337.5 3rd Qu.:260.74 3rd Qu.:285.5
Max. :633.67 Max. :590.8 Max. :633.81 Max. :651.0
S-R-CT3 S-R-CP3 S-A-TA3 S-R-CT4
Min. : 0.0 Min. : 0.00 Min. : 0.0 Min. : 0.0
1st Qu.:428.1 1st Qu.: 54.13 1st Qu.:310.8 1st Qu.:190.6
Median :457.0 Median :131.50 Median :334.0 Median :216.8
Mean :438.1 Mean :191.53 Mean :333.7 Mean :270.1
3rd Qu.:477.8 3rd Qu.:264.22 3rd Qu.:373.3 3rd Qu.:291.8
Max. :648.0 Max. :634.01 Max. :643.0 Max. :659.9
S-R-CP4 S-A-TA4 B-A-MU1 B-R-ET1
Min. : 0.00 Min. : 0.0 Min. : 0.0 Min. : 0.00
1st Qu.: 86.02 1st Qu.:415.7 1st Qu.:192.6 1st Qu.: 69.93
Median :155.51 Median :472.6 Median :208.0 Median :135.64
Mean :208.99 Mean :441.2 Mean :267.4 Mean :197.43
3rd Qu.:242.71 3rd Qu.:490.5 3rd Qu.:330.9 3rd Qu.:275.38
Max. :626.20 Max. :674.8 Max. :506.3 Max. :627.17
B-A-GU1 B-R-PC2 B-A-MU2 B-A-GU2
Min. : 0.00 Min. : 0.00 Min. : 0.0 Min. : 0.0
1st Qu.: 61.86 1st Qu.: 97.35 1st Qu.:116.4 1st Qu.:117.4
Median :132.50 Median :132.06 Median :147.2 Median :150.7
Mean :192.52 Mean :206.76 Mean :202.8 Mean :220.2
3rd Qu.:276.82 3rd Qu.:272.92 3rd Qu.:260.1 3rd Qu.:255.8
Max. :635.41 Max. :625.57 Max. :550.8 Max. :632.8
B-R-PC3 B-A-MU3 B-A-GU3 B-R-PC4
Min. : 0.0 Min. : 0.0 Min. : 0.0 Min. : 0.00
1st Qu.:148.0 1st Qu.:457.7 1st Qu.:352.8 1st Qu.: 97.15
Median :171.8 Median :518.2 Median :358.7 Median :146.76
Mean :226.2 Mean :480.4 Mean :379.5 Mean :216.44
3rd Qu.:254.2 3rd Qu.:533.7 3rd Qu.:397.0 3rd Qu.:282.36
Max. :619.0 Max. :624.8 Max. :707.3 Max. :641.26
B-A-MU4 B-A-GU4
Min. : 0.0 Min. : 0.0
1st Qu.:614.0 1st Qu.:230.6
Median :633.2 Median :243.5
Mean :600.1 Mean :286.8
3rd Qu.:642.6 3rd Qu.:299.7
Max. :707.3 Max. :669.4
Temos então que m é 26, portanto a matriz de distâncias tem 325 valores.
Fazemos agora um breve sumário do que foi calculado até agora.
<- cbind(min(euclid_ma),
Sumario2 max(euclid_ma),
sd(euclid_ma),
mean(euclid_ma),
length(euclid_ma))
colnames(Sumario2) <- c("Minimo", "Maximo", "Desv.Padr", "Media", "m(m-1)/2")
rownames(Sumario2) <- ("Valores")
Sumario2
Minimo Maximo Desv.Padr Media m(m-1)/2
Valores 0 707.3267 178.1842 274.908 676
7.1 Removendo os zeros da matriz de distâncias
<- as.matrix(euclid)
euclid_ma #euclid_ma
range(euclid_ma)
mean(euclid_ma)
sd(euclid_ma)
is.na(euclid_ma) <- euclid_ma==0 #atribui n.a. aos valores = 0
colMeans(euclid_ma, na.rm=T) #omite valores n.a. do calculo
rowMeans(euclid_ma, na.rm=T) #omite valores n.a. do calculo
[1] 0.0000 707.3267
[1] 274.908
[1] 178.1842
S-A-ZA1 S-R-CC1 S-R-CT1 S-R-CP1 S-A-TA1 S-R-CT2 S-R-CP2 S-A-TA2
202.2608 205.9912 266.3790 195.7828 195.8495 317.0479 207.1435 268.5172
S-R-CT3 S-R-CP3 S-A-TA3 S-R-CT4 S-R-CP4 S-A-TA4 B-A-MU1 B-R-ET1
455.6678 199.1922 347.0119 280.9253 217.3521 458.7988 278.0482 205.3272
B-A-GU1 B-R-PC2 B-A-MU2 B-A-GU2 B-R-PC3 B-A-MU3 B-A-GU3 B-R-PC4
200.2219 215.0274 210.8910 229.0481 235.2979 499.5754 394.6795 225.0953
B-A-MU4 B-A-GU4
624.1237 298.2560
S-A-ZA1 S-R-CC1 S-R-CT1 S-R-CP1 S-A-TA1 S-R-CT2 S-R-CP2 S-A-TA2
202.2608 205.9912 266.3790 195.7828 195.8495 317.0479 207.1435 268.5172
S-R-CT3 S-R-CP3 S-A-TA3 S-R-CT4 S-R-CP4 S-A-TA4 B-A-MU1 B-R-ET1
455.6678 199.1922 347.0119 280.9253 217.3521 458.7988 278.0482 205.3272
B-A-GU1 B-R-PC2 B-A-MU2 B-A-GU2 B-R-PC3 B-A-MU3 B-A-GU3 B-R-PC4
200.2219 215.0274 210.8910 229.0481 235.2979 499.5754 394.6795 225.0953
B-A-MU4 B-A-GU4
624.1237 298.2560
8 Procurando outliers
8.1 Listas de distâncias
Vamos agora crias uma lista com as distâncias em desvio padrão entre cada objeto e o centróide, baseado na matriz euclid_ma
. A distância média do centroide expressa em desvios padrão também podem ser chamadas de z-scores.
library(matrixStats)
library(moments)
<- (as.matrix(colMeans(euclid_ma, na.rm=T)))
av.dist <- (as.matrix(colSds(euclid_ma, na.rm=T)))
av.desvpad <- (av.dist-centroide_ma)/(colSds(av.dist)) #ou z-scores
dp.centroide_ma <- as.matrix(cbind(av.dist, av.desvpad, dp.centroide_ma))
list list
[,1] [,2] [,3]
S-A-ZA1 202.2608 175.36143 -0.64389921
S-R-CC1 205.9912 142.40233 -0.61083578
S-R-CT1 266.3790 93.46194 -0.07559585
S-R-CP1 195.7828 170.97514 -0.70131587
S-A-TA1 195.8495 170.39163 -0.70072510
S-R-CT2 317.0479 82.87727 0.37350168
S-R-CP2 207.1435 167.09006 -0.60062195
S-A-TA2 268.5172 124.64348 -0.05664389
S-R-CT3 455.6678 68.84928 1.60214211
S-R-CP3 199.1922 170.79087 -0.67109728
S-A-TA3 347.0119 92.95522 0.63908396
S-R-CT4 280.9253 131.44373 0.05333414
S-R-CP4 217.3521 157.62618 -0.51013918
S-A-TA4 458.7988 93.50892 1.62989392
B-A-MU1 278.0482 116.17286 0.02783285
B-R-ET1 205.3272 169.74682 -0.61672073
B-A-GU1 200.2219 174.32564 -0.66197044
B-R-PC2 215.0274 152.54520 -0.53074369
B-A-MU2 210.8910 128.79692 -0.56740645
B-A-GU2 229.0481 151.90782 -0.40647373
B-R-PC3 235.2979 130.07777 -0.35107902
B-A-MU3 499.5754 64.70789 1.99131169
B-A-GU3 394.6795 116.02951 1.06158063
B-R-PC4 225.0953 158.58714 -0.44150812
B-A-MU4 624.1237 45.46670 3.09523062
B-A-GU4 298.2560 130.86907 0.20694225
Ordenamos as distâncias da maior para a menor
colnames(list, do.NULL = FALSE)
colnames(list) <- c("Av.Dist", "Av.StDev", "DP.Centroide")
<- list[order(list[,1], decreasing = TRUE),] #[,1] ou o nome da coluna
list2 list2
[1] "col1" "col2" "col3"
Av.Dist Av.StDev DP.Centroide
B-A-MU4 624.1237 45.46670 3.09523062
B-A-MU3 499.5754 64.70789 1.99131169
S-A-TA4 458.7988 93.50892 1.62989392
S-R-CT3 455.6678 68.84928 1.60214211
B-A-GU3 394.6795 116.02951 1.06158063
S-A-TA3 347.0119 92.95522 0.63908396
S-R-CT2 317.0479 82.87727 0.37350168
B-A-GU4 298.2560 130.86907 0.20694225
S-R-CT4 280.9253 131.44373 0.05333414
B-A-MU1 278.0482 116.17286 0.02783285
S-A-TA2 268.5172 124.64348 -0.05664389
S-R-CT1 266.3790 93.46194 -0.07559585
B-R-PC3 235.2979 130.07777 -0.35107902
B-A-GU2 229.0481 151.90782 -0.40647373
B-R-PC4 225.0953 158.58714 -0.44150812
S-R-CP4 217.3521 157.62618 -0.51013918
B-R-PC2 215.0274 152.54520 -0.53074369
B-A-MU2 210.8910 128.79692 -0.56740645
S-R-CP2 207.1435 167.09006 -0.60062195
S-R-CC1 205.9912 142.40233 -0.61083578
B-R-ET1 205.3272 169.74682 -0.61672073
S-A-ZA1 202.2608 175.36143 -0.64389921
B-A-GU1 200.2219 174.32564 -0.66197044
S-R-CP3 199.1922 170.79087 -0.67109728
S-A-TA1 195.8495 170.39163 -0.70072510
S-R-CP1 195.7828 170.97514 -0.70131587
8.2 Distribuição de frequências das distâncias médias para o centróide av.dist
Observe o valor maximo e minimo gerados pela função range()
e substitua nas linhas de código assinaladas com #
. Aqui o menor valor foi 195.7828431 e o maior valor foi 624.1236964. Use valores maiores para facilitar a visualização no gráfico (Figura 5).
par(mfrow=c(3,1))
hist(list2[, "Av.Dist"],
breaks = 15, #determina o no. de colunas do histograma
xlab = "Distr. de Frequências das Distâncias (em dp) para o centroide",
main = "Distribuição de Frequência da distância média para o centroide",
xlim = range(100, 700), #substitua aqui o menor e maior valor do `range()`
freq = T)
hist(list2[, "Av.Dist"],
breaks = 15, #determina o no. de colunas do histograma
xlab = "Distr. de Frequências das Distâncias (em dp) para o centroide",
main = "Curva de normalidade ajustada para a Distribuição de Frequência",
xlim = range(100, 700), #substitua aqui o menor e maior valor do `range()`
freq = F)
curve(dnorm(x, mean=mean(list2[, "Av.Dist"]), sd=sd(list2[, "Av.Dist"])), add=TRUE)
boxplot.default(list2[, "Av.Dist"], horizontal = TRUE, frame = FALSE,
xlab="Distr. de Frequências",
ylim=c(100,700)) #substitua aqui o menor e maior valor do `range()`
Se necessário apague os gráficos
dev.off()
9 Lista final de outliers
Agora fazemos a lista final de distâncias com os outliers baseados em um ‘cutoff’.
<- 2.0 cutoff
Note que o ‘cutoff’ foi estabelecido no código acima no vetor
‘cutoff <-’. Ou seja, o ‘cutoff’ definindo quem serão considerados outliers, foi estabelecido como sendo valores de +2.0 e -2.0 desvios padrões da média multivariada ou centroide. Valores acima ou abaixo do ‘cutoff’ definido recebem o nome “OUT”, na coluna “Outliers”. Criada com o código abaixo.
library(gt)
format(cutoff, nsmall = 1)
<- as.data.frame(list2)
listf $Outliers <- ifelse(listf$DP.Centroide>-cutoff #CUTOFF MENOR QUE -'cutoff
listf& listf$DP.Centroide<cutoff, #CUTOFF MAIOR QUE 'cutoff'
"", "OUT")
listfgt(cbind(Sitios=rownames(listf),listf))
[1] "2.0"
Av.Dist Av.StDev DP.Centroide Outliers
B-A-MU4 624.1237 45.46670 3.09523062 OUT
B-A-MU3 499.5754 64.70789 1.99131169
S-A-TA4 458.7988 93.50892 1.62989392
S-R-CT3 455.6678 68.84928 1.60214211
B-A-GU3 394.6795 116.02951 1.06158063
S-A-TA3 347.0119 92.95522 0.63908396
S-R-CT2 317.0479 82.87727 0.37350168
B-A-GU4 298.2560 130.86907 0.20694225
S-R-CT4 280.9253 131.44373 0.05333414
B-A-MU1 278.0482 116.17286 0.02783285
S-A-TA2 268.5172 124.64348 -0.05664389
S-R-CT1 266.3790 93.46194 -0.07559585
B-R-PC3 235.2979 130.07777 -0.35107902
B-A-GU2 229.0481 151.90782 -0.40647373
B-R-PC4 225.0953 158.58714 -0.44150812
S-R-CP4 217.3521 157.62618 -0.51013918
B-R-PC2 215.0274 152.54520 -0.53074369
B-A-MU2 210.8910 128.79692 -0.56740645
S-R-CP2 207.1435 167.09006 -0.60062195
S-R-CC1 205.9912 142.40233 -0.61083578
B-R-ET1 205.3272 169.74682 -0.61672073
S-A-ZA1 202.2608 175.36143 -0.64389921
B-A-GU1 200.2219 174.32564 -0.66197044
S-R-CP3 199.1922 170.79087 -0.67109728
S-A-TA1 195.8495 170.39163 -0.70072510
S-R-CP1 195.7828 170.97514 -0.70131587
Sitios | Av.Dist | Av.StDev | DP.Centroide | Outliers |
---|---|---|---|---|
B-A-MU4 | 624.1237 | 45.46670 | 3.09523062 | OUT |
B-A-MU3 | 499.5754 | 64.70789 | 1.99131169 | |
S-A-TA4 | 458.7988 | 93.50892 | 1.62989392 | |
S-R-CT3 | 455.6678 | 68.84928 | 1.60214211 | |
B-A-GU3 | 394.6795 | 116.02951 | 1.06158063 | |
S-A-TA3 | 347.0119 | 92.95522 | 0.63908396 | |
S-R-CT2 | 317.0479 | 82.87727 | 0.37350168 | |
B-A-GU4 | 298.2560 | 130.86907 | 0.20694225 | |
S-R-CT4 | 280.9253 | 131.44373 | 0.05333414 | |
B-A-MU1 | 278.0482 | 116.17286 | 0.02783285 | |
S-A-TA2 | 268.5172 | 124.64348 | -0.05664389 | |
S-R-CT1 | 266.3790 | 93.46194 | -0.07559585 | |
B-R-PC3 | 235.2979 | 130.07777 | -0.35107902 | |
B-A-GU2 | 229.0481 | 151.90782 | -0.40647373 | |
B-R-PC4 | 225.0953 | 158.58714 | -0.44150812 | |
S-R-CP4 | 217.3521 | 157.62618 | -0.51013918 | |
B-R-PC2 | 215.0274 | 152.54520 | -0.53074369 | |
B-A-MU2 | 210.8910 | 128.79692 | -0.56740645 | |
S-R-CP2 | 207.1435 | 167.09006 | -0.60062195 | |
S-R-CC1 | 205.9912 | 142.40233 | -0.61083578 | |
B-R-ET1 | 205.3272 | 169.74682 | -0.61672073 | |
S-A-ZA1 | 202.2608 | 175.36143 | -0.64389921 | |
B-A-GU1 | 200.2219 | 174.32564 | -0.66197044 | |
S-R-CP3 | 199.1922 | 170.79087 | -0.67109728 | |
S-A-TA1 | 195.8495 | 170.39163 | -0.70072510 | |
S-R-CP1 | 195.7828 | 170.97514 | -0.70131587 |
10 Particionando a matriz
Talvez seja necessário particionar a matriz bruta para remover os outliers. Isso pode ser feito com os códigos abaixo. Atente para o vetor
part
. Ele define quais objetos ou UA’s serão particionados.
<- c("B-A-MU4", "B-A-MU3", "S-A-TA4", "S-R-CT3")
part part
[1] "B-A-MU4" "B-A-MU3" "S-A-TA4" "S-R-CT3"
<- ppbio[!(row.names(ppbio) %in% c(part)),]
ppbiopart #ppbiopart
Criamos uma nova matriz particionada ppbiopart
sem B-A-MU4, B-A-MU3, S-A-TA4, S-R-CT3, que apresentavam valores acima do cutoff para outliers.
Quando deletamos linhas ou colunas da matriz de dados comunitária, precisamos ver se isso não gerou linhas ou colunas vazias. Observe por exemplo a espécie Apareiodon davisi 4 (Figura 6). Por exemplo, se uma determinada espécie só ocorre em uma UA, e aquela UA foi removida, essa espécie não consta mais em nenhuma UA e por isso a sua soma vai ser igual a zero. Isso aconteceu com a espécie Pseudancistrus genisetiger 5 (Figura 7). Essa espécie precisará ser removida.
Use o a função View(ppbiopart)
e procure linhas ou colunas na matriz ppbiopart
onde todos os valores são zero. Quais espéies você encontrou que deixaram de ocorrer na comunidade depois que as UA’s outliers foram removidas?.
Complicado? Os códigos abaixo resolvem isso, e mostram algumas propriedades da nova matriz ppbiopart2
depois de particionada pela segunda vez para remover linhas/colunas “zeradas”.
<- colSums(ppbiopart)
sum
sum<- names(which(colSums(ppbiopart) == 0))
zero_sum_cols #nomes das espécies zeradas
zero_sum_cols
<- ppbiopart[(colSums(ppbiopart) != 0)] #em != a exclamação inverte o sentido
ppbiopart2
<- names(which(colSums(ppbiopart2) == 0))
zero_sum_cols2 #nomes das espécies zeradas
zero_sum_cols2 <-colSums(ppbiopart2)
sum
sum#ppbiopart2
#ppbiopart2 <- as.matrix(ppbiopart2)
str(ppbiopart2)
length(as.matrix(ppbiopart2))
ap-davis as-bimac as-fasci ch-bimac ci-ocela ci-orien co-macro co-heter
27 1040 94 432 70 118 2 1
cr-menez cu-lepid cy-gilbe ge-brasi he-margi ho-malab hy-pusar le-melan
19 21 131 364 2 69 60 2
le-piau le-taeni mo-costa mo-lepid or-nilot pa-manag pimel-sp po-retic
11 1 1 41 697 554 6 64
po-vivip pr-brevi ps-rhomb ps-genise se-heter se-piaba se-spilo st-noton
441 111 0 0 258 68 0 90
sy-marmo te-chalc tr-signa
1 134 201
[1] "ps-rhomb" "ps-genise" "se-spilo"
character(0)
ap-davis as-bimac as-fasci ch-bimac ci-ocela ci-orien co-macro co-heter
27 1040 94 432 70 118 2 1
cr-menez cu-lepid cy-gilbe ge-brasi he-margi ho-malab hy-pusar le-melan
19 21 131 364 2 69 60 2
le-piau le-taeni mo-costa mo-lepid or-nilot pa-manag pimel-sp po-retic
11 1 1 41 697 554 6 64
po-vivip pr-brevi se-heter se-piaba st-noton sy-marmo te-chalc tr-signa
441 111 258 68 90 1 134 201
'data.frame': 22 obs. of 32 variables:
$ ap-davis: num 0 0 0 0 0 0 0 0 0 0 ...
$ as-bimac: num 1 99 194 19 23 142 5 46 16 234 ...
$ as-fasci: num 0 0 55 0 1 3 1 0 0 7 ...
$ ch-bimac: num 0 0 0 0 13 3 0 178 0 238 ...
$ ci-ocela: num 0 0 0 0 0 0 40 0 13 0 ...
$ ci-orien: num 0 0 5 0 0 69 9 0 24 0 ...
$ co-macro: num 0 0 0 0 0 0 0 0 0 2 ...
$ co-heter: num 0 0 1 0 0 0 0 0 0 0 ...
$ cr-menez: num 0 0 14 0 0 4 0 0 0 0 ...
$ cu-lepid: num 0 0 0 0 0 0 0 0 0 0 ...
$ cy-gilbe: num 0 0 0 0 0 0 0 0 0 0 ...
$ ge-brasi: num 0 0 3 0 0 0 0 0 0 0 ...
$ he-margi: num 0 0 0 0 0 1 0 0 0 0 ...
$ ho-malab: num 0 0 1 5 0 17 10 2 4 20 ...
$ hy-pusar: num 0 0 9 2 0 43 2 0 0 0 ...
$ le-melan: num 0 0 0 0 0 0 0 0 0 0 ...
$ le-piau : num 0 0 3 0 0 1 3 0 1 0 ...
$ le-taeni: num 0 0 0 0 0 0 0 0 0 0 ...
$ mo-costa: num 0 0 0 0 0 0 0 0 0 0 ...
$ mo-lepid: num 0 1 39 0 0 1 0 0 0 0 ...
$ or-nilot: num 0 2 36 0 0 77 0 0 0 0 ...
$ pa-manag: num 0 0 0 0 0 0 0 0 0 0 ...
$ pimel-sp: num 0 0 6 0 0 0 0 0 0 0 ...
$ po-retic: num 0 0 0 0 0 20 0 0 0 0 ...
$ po-vivip: num 0 0 47 15 0 221 32 0 10 0 ...
$ pr-brevi: num 9 0 5 0 1 15 5 2 0 0 ...
$ se-heter: num 0 0 40 14 4 60 0 0 0 0 ...
$ se-piaba: num 0 0 68 0 0 0 0 0 0 0 ...
$ st-noton: num 0 0 1 0 0 25 0 0 0 0 ...
$ sy-marmo: num 0 0 0 0 0 0 1 0 0 0 ...
$ te-chalc: num 0 0 0 0 0 0 0 0 0 0 ...
$ tr-signa: num 0 0 18 0 0 15 0 0 0 0 ...
[1] 704
11 Exportando a matrix final de trabalho
Agora vamos exportar a matrix de trabalho, nesse casso a matrix ppbiopart2
, como um arquivo de valores separados por vírgula (ppbiopart2csv.csv
). Na verdade, separado por ";"
, como definido na funçao sep = ";"
. O arquivo será exportado para o diretório de trabalho. Na mesma sequência de códigos, importamos ppbiopart2csv.csv
como nossa matriz de trabalho m_trab
.
<- data.frame(Sites = rownames(ppbio), ppbio,
df row.names = NULL,
check.names = FALSE) #add titulo a primeira coluna
write.table(ppbiopart2, "m_trabcsv.csv",
sep = ";", dec = ".", #"\t",
row.names = TRUE,
quote = TRUE,
append = FALSE)
<- read.csv("m_trabcsv.csv",
m_trab sep = ";", dec = ".",
row.names = 1,
header = TRUE,
na.strings = NA,
check.names = FALSE, #impede que o R mude os nomes das colunas
col.names = gsub("(^|_)([a-z])", "\\1\\U\\2",
names(m_trab), perl = TRUE))
Agora é com você…Refaça toda a análise com a matriz bruta particionada ppbiopart2
12 Referências
Apêndices
Outras formas de fazer a partição
ppbiopart2 <- ppbiopart[colSums(abs(ppbiopart), na.rm = F) > 0] ppbiopart2 <- subset(ppbiopart, colSums != 0) ppbiopart2 <- ppbiopart[, colSums(ppbiopart != 0) > 0]
Código
range(euclidma) par(mfrow=c(2,1)) hist(euclidma, breaks = 15, #determina o no. de colunas do histograma xlim = range(floor(min(euclidma)), ceiling(max(euclidma))), xlab = “Distr. de Frequências”, freq = FALSE) curve(dnorm(x, mean=mean(euclidma), sd=sd(euclidma)), add=TRUE) boxplot.default(euclidma, horizontal = TRUE, frame = FALSE, xlab=“Distr. de Frequências”, ylim=c(floor(min(euclidma)), ceiling(max(euclidma)))) #Limites do eixo Y
Notas de rodapé
Semestre 2023.1↩︎
A etimologia do gênero Astyanax vem da mitologia Grega. Heitor personagem da “Ilíada”, tinha um filho chamado Astíanax.↩︎
Do Grego, hoplon, arma ou armadura, em referência aos dentes caniniformes muito desenvolvidos, e forte estrutura óssea na cabeça.↩︎
A etimologia do nome Apareiodon vem do Grego, a, sem, pareia, lateral ou bochecha, e odous dentição, em referencia a ausência de tentes laterais no aparato bucal dessa espécie.↩︎
A etimologia do nome Pseudancistrus vem do Grego, pseudes, falso, e agkistron, gancho, em referência a falsos ganchos presentes na cabeça em algumas espécies do gênero.↩︎