A análise exploratória dos dados, baseada na descrição estatística de dados, é uma abordagem que tem como objetivos contribuir para adquirir conhecimento e uma visão mais aprofundada dos dados, de modo a evidenciar padrões e a detectar anomalias.
Apresentam-se neste documento algumas técnicas e ferramentas básicas de análise para atingir estes objetivos, usando a linguagem R.
Iremos usar o ficheiro de dados Iris:
'data.frame': 150 obs. of 5 variables:
$ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
$ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
$ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
$ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
$ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
As variáveis quantitativas referem-se ao comprimento e largura das pétalas e das sépalas, a variável categorica descreve a especie.
head(iris, n = 3)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
Para uma variável numérica, é frequente usar um histograma dos dados observados para descrever a distribuição empírica da variável. A descrição do histograma faz-se em torno da sua forma em termos de dispersão, assimetria ou achatamento.
Um histograma pode ser obtido com a função hist()
:
hist (iris$Sepal.Width, breaks = 10,
main = "Histograma",
xlab = "Comp. pétala (cm)",
ylab = "Freq. absoluta")
Em alternativa ao histograma, pode usar-se a função boxplot()
para construir uma caixa-de-bigodes (boxplot). O box-plot fornece cinco medidas :
O IQR = percentil 75 - percentil 25 (ou amplitude inter-quartil) .
par(oma = rep(0,4)); par(mar= c(1,4,3,0))
boxplot (iris$Sepal.Width,
main = "Caixa-de-bigodes",
xlab = "",
ylab = "Comp. pétala (cm)",
col = c("magenta"))
Um dos pontos fortes dos box-plots será a capacidade de identificar facilmente a presença de valores extremos, muito afastados do centro de gravidade. No gráfico, os pontos que aparecem acima e abaixo dos limites do bigode podem ser vistos como valores extremos ou “anomalos”.
Para variáveis categóricas (ou factor
) é usual calcular frequências absolutas/relativas usando a função table()
ou prop.table()
:
setosa versicolor virginica
50 50 50
trel <- prop.table(tabs)
trel
setosa versicolor virginica
0.3333333 0.3333333 0.3333333
A função table()
constroí uma tabela de contingência (neste caso a tabela tem apenas uma variável, com 3 categorias). O argumento da função prop.table()
é a tabela de contingência.
A função plot()
é uma função genérica do R que produz diferentes gráficos em função do tipo de argumentos. Ex:
Por ex. a função plot()
do comprimento das pétalas e das sépalas (ambas quantitativas) devolve um gráfico de dispersão:
plot (iris$Petal.Length, iris$Sepal.Length,
main = "Gráfico de dispersão",
xlab = "Comprimento pétala (cm)",
ylab = "Comprimento sépala (cm)", type="p")
No caso de uma das variáveis ser numérica e a outra categrorica (factor
), a função plot()
devolve uma caixa-de-bigodes (por categoria):
plot (iris$Species, iris$Petal.Length,
main = "Caixa-de-bigodes",
xlab = "Espécie",
ylab = "Comprimento pétala (cm)",
col = c("white","grey","pink"))
No caso de ambas as variáveis serem quantitativas, e existir uma variável factor
que discrimine as categorias, pode criar-se, com a função plot()
um gráfico de dispersão mais informativo onde se distinguirem as categorias:
# para por legenda fora do plot
par(mar=c(5, 4, 4, 8), xpd=TRUE)
# plot
plot (iris$Petal.Length, iris$Sepal.Length,
main = "Gráfico de dispersão",
xlab = "Comprimento pétala (cm)",
ylab = "Comprimento sepala (cm)",
col = as.numeric(iris$Species))
# legenda
legend ("bottomright", legend = levels(iris$Species),
pch = c(1,1,1), col = unique (as.numeric(iris$Species)),
inset=c(-0.5, 0))
Se quisermos visualizar vários planos formados por pares de vetores numéricos, podemos gerar um painel dos gráficos de dispersão com a função pairs()
:
pairs (iris[,1:4],
col = as.numeric(iris$Species),
oma = c(3,3,3,14))
par (xpd = TRUE)
legend ("bottomright",
pch = c(1,1,1),
col = unique(as.numeric(iris$Species)),
legend = levels(iris$Species))
O package lattice
extende as capacidades gráficas do R que vimos até aqui. Embora venha instalado no R base, é necessário carregar o package dentro da sessão R para beneficiar das funcionalidades:
Com a função xyplot()
também se podem criar gráficos de dispersão para cada categoria:
xyplot(Sepal.Length ~ Petal.Length | Species,
data = iris,
ylab = "Comprimento sépala (cm)",
xlab= "Comprimento pétala (cm)")
Para criar um histograma por categoria, no mesmo gráfico podemos usar a função lattice::histogram()
:
histogram ( ~ Petal.Length | Species, data = iris,
xlab = "Comprimento pétala (cm)",
ylab="%", type = "percent",
nint = 50, layout = c(1,3))
Podem exportar-se gráficos, gravando-os num ficheiro, através do interface RStudio:
ou usando consola:
# cria ficheiro png
png(file="grafico_1.png",
width=1000, height = 1000, res = 600)
# guarda gráfico
histogram ( ~ Petal.Length | Species, data = iris,
xlab = "Comprimento pétala (cm)", ylab="%",
type = "percent", nint = 50, layout = c(1,3))
# fecha ficheiro
dev.off()
A função summary devolve algumas medidas dos dados observados :
summary(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width
Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100
1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300
Median :5.800 Median :3.000 Median :4.350 Median :1.300
Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
Species
setosa :50
versicolor:50
virginica :50
No caso das variáveis quantitativas devolve medidas de localização (minimo, máximo, média e percentis 25,50 e 75), no caso de variáveis categoricas devolve as contagens por categoria.
Os valores das estimativas da média ou do desvio-padrão podem ser obtidas com as funções mean
, sd
:
mean(iris$Petal.Length)
[1] 3.758
sd(iris$Petal.Length)
[1] 1.765298
Para obter estas estatísticas para mais que uma variável podemos usar a função apply()
que aplica uma função a um objeto (data.frame, matriz), em coluna (ou em linha):
apply(iris[,1:4], 2, mean)
Sepal.Length Sepal.Width Petal.Length Petal.Width
5.843333 3.057333 3.758000 1.199333
apply(iris[,1:4], 2, sd)
Sepal.Length Sepal.Width Petal.Length Petal.Width
0.8280661 0.4358663 1.7652982 0.7622377
As medidas de assimetria ou achatamento não estão implementadas no R base. A função moments::skewness
calcula a assimetria de um vetor ou de um conjunto de vetores:
Sepal.Length Sepal.Width Petal.Length Petal.Width
0.3117531 0.3157671 -0.2721277 -0.1019342
Um coeficiente de assimetria positivo tipicamente indica que a distribuição empírica da variável tem uma cauda mais alongada para o lado direito (caso seja negativo, ocorre o oposto). Quanto mais afastado de zero o valor do coeficiente, mais assimétrica é a distribuição.
Para obter estas estatísticas (média,..) por categorias, pode usar-se a função aggregate()
, especificando os argumentos by=
(variável categorica) e FUN
(função):
Group.1 Sepal.Length Sepal.Width Petal.Length Petal.Width
1 setosa 5.006 3.428 1.462 0.246
2 versicolor 5.936 2.770 4.260 1.326
3 virginica 6.588 2.974 5.552 2.026
A função apply()
aceita qualquer função que possa ser aplicada ao objeto. Podemos criar uma função (que não esteja implementada) e usá-la com o apply()
.
Por exemplo, o coeficiente de variação, cv=sd/m (medida de dispersão dada pelo quociente entre desvio-padrão e media) não está implementado no R. Quanto maior o coeficiente de variação maior o grau de dispersão em torno da media.
Vamos criar a função e usar o apply()
para obter o cv das variáveis quantitativas:
calc_cv = function (vetor) {
# calcula a media e desvio padrao
m = mean(vetor)
d = sd (vetor)
# devolve resultado
return(d/m)
}
Agora podemos usar a função apply()
e aplicar a função calc_cv()
ao objecto iris[,1:4]
:
apply(iris[,1:4], 2, calc_cv)
Sepal.Length Sepal.Width Petal.Length Petal.Width
0.1417113 0.1425642 0.4697441 0.6355511
# a sintaxe mais habitual é:
apply(iris[,1:4], 2, function(x) calc_cv(x))
Sepal.Length Sepal.Width Petal.Length Petal.Width
0.1417113 0.1425642 0.4697441 0.6355511
A matriz de variâncias-covariâncias pode ser calculada com a função cov()
:
cov(iris[,1:4])
Sepal.Length Sepal.Width Petal.Length Petal.Width
Sepal.Length 0.6856935 -0.0424340 1.2743154 0.5162707
Sepal.Width -0.0424340 0.1899794 -0.3296564 -0.1216394
Petal.Length 1.2743154 -0.3296564 3.1162779 1.2956094
Petal.Width 0.5162707 -0.1216394 1.2956094 0.5810063
A matriz de correlações dos dados é dada pela função cor()
:
cor_iris <- cor(iris[,1:4])
As matrizes de correlações (ou de variâncias-covariâncias) em cada categoria podem ser obtida com um ciclo cujo indice i indica a especie :
# vetor com 3 especies (categorias)
class <- levels(iris$Species)
# lista
covk <- list()
# ciclo percorre as classes
# filtra observações e calcula cov
for (i in class){
irisk <- iris[iris$Species == i, 1:4]
covk[[i]] <- cor(irisk)
}
Uma forma alternativa de visualizar estas matrizes (especialmente interessante quando há muitas variáveis) é com um heatmap que usa um gradiente de cores para representar os valores dos termos da matriz. A função ggplot2::ggplot()
é uma das que permite obter um heatmap:
library("ggplot2")
# definir as coordenadas em linha/coluna dos termos da matriz
dataXY <- expand.grid(X=colnames(cor_iris), Y=colnames(cor_iris))
# Heatmap
ggplot(dataXY, aes(X, Y, fill= cor_iris)) +
geom_tile()