Chapter 4 Visualizar os Dados


4.1 Por que visualizar os dados?

O Quarteto de Anscombe (F.J. Anscombe, 1973) talvez seja o exemplo mais conhecido que ilustra o valor da visualização dos dados.

Os quatro conjuntos de dados exibidos abaixo, pares \((x,y)\), apresentam com até 3 casas decimais as mesmas médias e variâncias de \(x\) e \(y\) e correlação de 0.816, levando todos a uma mesma regressão linear.

\[y = 3 + 0.5 x\]

# note, não é necessário você compreender os detalhes deste código aqui, 
# o interesse está no gráfico produzido

require(stats); require(graphics)
summary(anscombe)
##        x1             x2             x3             x4           y1        
##  Min.   : 4.0   Min.   : 4.0   Min.   : 4.0   Min.   : 8   Min.   : 4.260  
##  1st Qu.: 6.5   1st Qu.: 6.5   1st Qu.: 6.5   1st Qu.: 8   1st Qu.: 6.315  
##  Median : 9.0   Median : 9.0   Median : 9.0   Median : 8   Median : 7.580  
##  Mean   : 9.0   Mean   : 9.0   Mean   : 9.0   Mean   : 9   Mean   : 7.501  
##  3rd Qu.:11.5   3rd Qu.:11.5   3rd Qu.:11.5   3rd Qu.: 8   3rd Qu.: 8.570  
##  Max.   :14.0   Max.   :14.0   Max.   :14.0   Max.   :19   Max.   :10.840  
##        y2              y3              y4        
##  Min.   :3.100   Min.   : 5.39   Min.   : 5.250  
##  1st Qu.:6.695   1st Qu.: 6.25   1st Qu.: 6.170  
##  Median :8.140   Median : 7.11   Median : 7.040  
##  Mean   :7.501   Mean   : 7.50   Mean   : 7.501  
##  3rd Qu.:8.950   3rd Qu.: 7.98   3rd Qu.: 8.190  
##  Max.   :9.260   Max.   :12.74   Max.   :12.500
##-- now some "magic" to do the 4 regressions in a loop:
ff <- y ~ x
mods <- setNames(as.list(1:4), paste0("lm", 1:4))
for(i in 1:4) {
  ff[2:3] <- lapply(paste0(c("y","x"), i), as.name)
  ## or   ff[[2]] <- as.name(paste0("y", i))
  ##      ff[[3]] <- as.name(paste0("x", i))
  mods[[i]] <- lmi <- lm(ff, data = anscombe)
  print(anova(lmi))
}
## Analysis of Variance Table
## 
## Response: y1
##           Df Sum Sq Mean Sq F value  Pr(>F)   
## x1         1 27.510 27.5100   17.99 0.00217 **
## Residuals  9 13.763  1.5292                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Analysis of Variance Table
## 
## Response: y2
##           Df Sum Sq Mean Sq F value   Pr(>F)   
## x2         1 27.500 27.5000  17.966 0.002179 **
## Residuals  9 13.776  1.5307                    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Analysis of Variance Table
## 
## Response: y3
##           Df Sum Sq Mean Sq F value   Pr(>F)   
## x3         1 27.470 27.4700  17.972 0.002176 **
## Residuals  9 13.756  1.5285                    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## Analysis of Variance Table
## 
## Response: y4
##           Df Sum Sq Mean Sq F value   Pr(>F)   
## x4         1 27.490 27.4900  18.003 0.002165 **
## Residuals  9 13.742  1.5269                    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## See how close they are (numerically!)
sapply(mods, coef)
##                   lm1      lm2       lm3       lm4
## (Intercept) 3.0000909 3.000909 3.0024545 3.0017273
## x1          0.5000909 0.500000 0.4997273 0.4999091
lapply(mods, function(fm) coef(summary(fm)))
## $lm1
##              Estimate Std. Error  t value    Pr(>|t|)
## (Intercept) 3.0000909  1.1247468 2.667348 0.025734051
## x1          0.5000909  0.1179055 4.241455 0.002169629
## 
## $lm2
##             Estimate Std. Error  t value    Pr(>|t|)
## (Intercept) 3.000909  1.1253024 2.666758 0.025758941
## x2          0.500000  0.1179637 4.238590 0.002178816
## 
## $lm3
##              Estimate Std. Error  t value    Pr(>|t|)
## (Intercept) 3.0024545  1.1244812 2.670080 0.025619109
## x3          0.4997273  0.1178777 4.239372 0.002176305
## 
## $lm4
##              Estimate Std. Error  t value    Pr(>|t|)
## (Intercept) 3.0017273  1.1239211 2.670763 0.025590425
## x4          0.4999091  0.1178189 4.243028 0.002164602
## Now, do what you should have done in the first place: PLOTS
op <- par(mfrow = c(2, 2), mar = 0.1+c(4,4,1,1), oma =  c(0, 0, 2, 0))
for(i in 1:4) {
  ff[2:3] <- lapply(paste0(c("y","x"), i), as.name)
  plot(ff, data = anscombe, col = "red", pch = 21, bg = "orange", cex = 1.2,
       xlim = c(3, 19), ylim = c(3, 13))
  abline(mods[[i]], col = "blue")
}
mtext("Anscombe's 4 Regression data sets", outer = TRUE, cex = 1.5)

par(op)

4.2 Buscando gráficos corretos

As perguntas que podemos fazer sobre os dados podem ser agrupadas em algumas categorias relevantes, cada uma delas tendo gráficos mais adequados para você obter e apresentar respostas à sua questão:

Evolução (ou Tendência dos Dados): gráficos de linha, área, séries múltiplas

Distribuição: histogramas, gráficos de distribuição de densidade, boxplot

Ranking: gráficos de barras, word cloud, spider

Correlação: gráficos de dispersão, heat map, density 2D

Partes de um todo: Tree map, diagramas Venn, pie chart

Havendo ainda gráficos especializados que envolvem para análises geográficas (maps) ou fluxo de dados em redes sociais.

4.3 Evolução

Muitos dados apresentam uma evolução ao longo tempo. Nesses casos, frequentemente queremos saber sobre a tendência dessa evolução, sobre a probabilidade de se alcançar um valor ou ainda comparar a forma de evolução de variáveis que possam ter alguma relação.

Quando essas variáveis são numéricas um gráfico de linhas é frequentemente usado para visualizar a tendência nos dados em intervalos de tempo e responder essas perguntas.

Considere a base.

df = read.csv('http://meusite.mackenzie.br/rogerio/TIC/mystocksn.csv')
head(df)
##         data   IBOV VALE3 PETR4  DOLAR
## 1 2020-01-02 118573 13.45 16.27 4.0163
## 2 2020-01-03 117707 13.29 15.99 4.0234
## 3 2020-01-06 116878 13.14 16.22 4.0570
## 4 2020-01-07 116662 13.23 16.06 4.0604
## 5 2020-01-08 116247 13.22 15.70 4.0662
## 6 2020-01-09 115947 12.99 15.75 4.0628
df$data = factor(df$data) # necessário após atualizaçao do RCloud em Maio.2020

plot dos valores (x,y)

par(mfrow = c(2, 2))
plot(df$data,df$IBOV)
plot(df$data,df$VALE3)
plot(df$data,df$PETR4)
plot(df$data,df$DOLAR)

plot(df$data,df$DOLAR, main='Evolução do Dólar',ylim=c(3,8),ylabel='Dólar')
abline(h=4.3,col='red')

help(plot)
## starting httpd help server ... done

4.4 Distribuição

Os dados a seguir foram obtidos da WHO World Health Organization - Life expectancy and Healthy life expecancy. Eles apresentam indicadores de saúde de diversos países como o índice de massa corpórea médio da população (BMI), a expectativa de vida e índices de mortalidade. Uma pergunta relevante sobre a saúde global poderia ser sobre a distribuição de certos índices entre os países, como por exemplo o caso a seguir.

Considere a base.

df = read.csv('https://meusite.mackenzie.br/rogerio/TIC/Life_Expectancy_Data.csv')
head(df)
##       Country Year     Status Life.expectancy Adult.Mortality infant.deaths
## 1 Afghanistan 2015 Developing            65.0             263            62
## 2 Afghanistan 2014 Developing            59.9             271            64
## 3 Afghanistan 2013 Developing            59.9             268            66
## 4 Afghanistan 2012 Developing            59.5             272            69
## 5 Afghanistan 2011 Developing            59.2             275            71
## 6 Afghanistan 2010 Developing            58.8             279            74
##   Alcohol percentage.expenditure Hepatitis.B Measles  BMI under.five.deaths
## 1    0.01              71.279624          65    1154 19.1                83
## 2    0.01              73.523582          62     492 18.6                86
## 3    0.01              73.219243          64     430 18.1                89
## 4    0.01              78.184215          67    2787 17.6                93
## 5    0.01               7.097109          68    3013 17.2                97
## 6    0.01              79.679367          66    1989 16.7               102
##   Polio Total.expenditure Diphtheria HIV.AIDS       GDP Population
## 1     6              8.16         65      0.1 584.25921   33736494
## 2    58              8.18         62      0.1 612.69651     327582
## 3    62              8.13         64      0.1 631.74498   31731688
## 4    67              8.52         67      0.1 669.95900    3696958
## 5    68              7.87         68      0.1  63.53723    2978599
## 6    66              9.20         66      0.1 553.32894    2883167
##   thinness..1.19.years thinness.5.9.years Income.composition.of.resources
## 1                 17.2               17.3                           0.479
## 2                 17.5               17.5                           0.476
## 3                 17.7               17.7                           0.470
## 4                 17.9               18.0                           0.463
## 5                 18.2               18.2                           0.454
## 6                 18.4               18.4                           0.448
##   Schooling
## 1      10.1
## 2      10.0
## 3       9.9
## 4       9.8
## 5       9.5
## 6       9.2
library(lattice)
par(mfrow = c(2, 1))
hist(df$Life.expectancy, main='Expectativa de Vida dos Países')
hist(df$Life.expectancy, main='Expectativa de Vida dos Países', breaks = 100, col = "lightblue", freq=TRUE)

densityplot(df$Life.expectancy, main='Expectativa de Vida dos Países')

help(plot)
d = density(df$Life.expectancy,na.rm = TRUE)
plot(d, main="Expectativa de Vida")
polygon(d, col="orange", border="black")

par(mfrow = c(1, 3))
boxplot(df$Life.expectancy,main='Expectativa de Vida')
boxplot(df$BMI,main='BMI')
boxplot(Life.expectancy ~ Status,data=df,main="Expectativa de Vida ")

4.5 Correlação

Relações entre os dados são muitas vezes a parte mais importante dentre as descobertas que buscamos nos dados. Essas relações em geral são denominadas de modo geral como correlações. Mas é importante notar que a correlação estatística tem um significado muito mais específico e, em geral, está associada a correlação linear. Graficamente, entretanto, estamos livres para buscar quaisquer relações entre os dados, sejam elas lineares ou não.

Considere a base.

df = read.csv('https://meusite.mackenzie.br/rogerio/TIC/Pokemon.csv')
head(df)
##   X.                  Name Type.1 Type.2 Total HP Attack Defense Sp..Atk
## 1  1             Bulbasaur  Grass Poison   318 45     49      49      65
## 2  2               Ivysaur  Grass Poison   405 60     62      63      80
## 3  3              Venusaur  Grass Poison   525 80     82      83     100
## 4  3 VenusaurMega Venusaur  Grass Poison   625 80    100     123     122
## 5  4            Charmander   Fire          309 39     52      43      60
## 6  5            Charmeleon   Fire          405 58     64      58      80
##   Sp..Def Speed Generation Legendary
## 1      65    45          1     False
## 2      80    60          1     False
## 3     100    80          1     False
## 4     120    80          1     False
## 5      50    65          1     False
## 6      65    80          1     False
pairs(df)

pairs(df[,c(5:8)])

plot(df[,c(5,7)])
abline(lsfit(df[,5],df[,7]),col='red')

boxplot(Total ~ Generation,data=df, main="Total by Generation")

4.6 Ranking

Comparar quantidades de diferentes categorias é uma tarefa frequente e útil. Responde a perguntas de maiores, menores valores, mais e menos presentes.

Considere a base.

help(mtcars)
head(mtcars)
##                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
## Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1
par(mfrow = c(1, 3))
counts = table(mtcars$gear)
barplot(counts, main="Distribuição dos Veículos", xlab="Número de Marchas",
        col='darkblue')
pie(table(mtcars$cyl), main="Distribuição dos Veículos", xlab="Número de Cilindros")
dotchart(mtcars$hp,labels=row.names(mtcars),cex=.7,col='orange',
   main="Potência dos Modelos",
   xlab="hp")

# Grouped Bar Plot
counts <- table(mtcars$cyl, mtcars$gear)
barplot(counts, main="Número de Marchas vs Cilindros",
  xlab="Número de Marchas", col=c("darkblue","orange"),
  legend = rownames(counts), beside=TRUE)

boxplot(mpg~cyl,data=mtcars, main="Consumo vs Cyl",
   xlab="Número de Cilindros", ylab="Milhas por Galão",col='blue')

4.7 Melhores Gráficos

Para os nossos propósitos os gráficos acima serão suficientes. Mas se você se interessa por gráficos com uma apresentação mais profissional pode empregar a biblioteca ggplot2.

# install.packages('ggplot2')
# Loading
# library(ggplot2)

4.8 Exercícios

4.8.1 Exercício

Considere a base.

data(CPS85 , package = "mosaicData")
head(CPS85)
##   wage educ race sex hispanic south married exper union age   sector
## 1  9.0   10    W   M       NH    NS Married    27   Not  43    const
## 2  5.5   12    W   M       NH    NS Married    20   Not  38    sales
## 3  3.8   12    W   F       NH    NS  Single     4   Not  22    sales
## 4 10.5   12    W   F       NH    NS Married    29   Not  47 clerical
## 5 15.0   12    W   M       NH    NS Married    40 Union  58    const
## 6  9.0   16    W   F       NH    NS Married    27   Not  49 clerical

4.8.2 Exercício

Faça um histograma e gráficos de caixa de educ e expr. Existem outliers para que valores?

par(mfrow = c(2, 2))
hist(CPS85$educ)
boxplot(CPS85$educ)

hist(CPS85$exper)
boxplot(CPS85$exper)

4.8.3 Exercício

Faça gráficos para exibir a distribuição (histograma) de valores de educ, exper e wage separadamente para os sexos Masculino e Feminino. Que distribuições concentram valores mais a esquerda (valores menores)?

par(mfrow = c(3, 2))
hist(CPS85[CPS85$sex == 'M',]$educ)
hist(CPS85[CPS85$sex == 'F',]$educ)

hist(CPS85[CPS85$sex == 'M',]$exper)
hist(CPS85[CPS85$sex == 'F',]$exper)

hist(CPS85[CPS85$sex == 'M',]$wage)
hist(CPS85[CPS85$sex == 'F',]$wage)

4.8.4 Exercício

Analise a distribuição dos mesmos dados do problema anterior, mas agora empregue um gráfico de caixa e a função ~ para exibir separadamente os sexos.

par(mfrow = c(1, 3))

boxplot(educ ~ sex, data=CPS85, main='educ',col='orange')
boxplot(exper ~ sex, data=CPS85, main='exper',col='green')
boxplot(wage~ sex, data=CPS85, main='wage',col='blue')

4.8.5 Exercício

Consulte o help do boxplot. Busque uma opção que exiba com maior evidência a mediana e o quanto ela difere dos outros valores. Repita então o exercício anterior com essa opção. Se conseguir (rs) empregue uma opção para colorir diferentemente as caixas para o sexo Feminino e Masculino.

par(mfrow = c(1, 3))

boxplot(educ ~ sex, data=CPS85, main='educ',col=c('pink','blue'),notch=TRUE)
## Warning in bxp(list(stats = structure(c(8, 12, 12, 15, 18, 8, 12, 12, 15, : some
## notches went outside hinges ('box'): maybe set notch=FALSE
boxplot(exper ~ sex, data=CPS85, main='exper',col=c('pink','blue'),notch=TRUE)
boxplot(wage ~ sex, data=CPS85, main='wage',col=c('pink','blue'),notch=TRUE)

4.8.6 Exercício

Empregue um gráfico de barras e outro de pizza para exibir a proporção de do status de casados na base. Dica: para o pie() você precisa fornecer a frequencia dos valores. Empregue em conjunto o table().

par(mfrow = c(1, 2))
barplot(table(CPS85$married),col='green') 
pie(table(CPS85$married)) 

4.8.7 Exercício

Faça um gráfico de densidade e um histogram com breaks=30 para os valores de rendimentos (wage). Compare os gráficos.

par(mfrow = c(1, 2))
hist(CPS85$wage,breaks=30)
densityplot(CPS85$wage)

### Exercício Empregue a função rnorm para gerar valores randomicos. Acesse o help(norm). Mas o seu formato geral é:

                      rnorm( n, valor médio, desvio padrão)

gere 4 séries com 100 valores aleatórios com média 50 e desvio padrão 10, 50, 20 e 5 respectivamente. Em seguida plot os gráficos de densidade e compare.

par(mfrow=c(2,2))
plot(density(rnorm(100,50,10)),xlim=c(0,100),main='plot A')
plot(density(rnorm(100,50,50)),xlim=c(0,100),main='plot B')
plot(density(rnorm(100,50,20)),xlim=c(0,100),main='plot C')
plot(density(rnorm(100,50,5)),xlim=c(0,100),main='plot D')

4.8.8 Exercício RESOLVIDO.

Repita o exercício anterior somente para as séries de desvio padrão 10 e 20, mas compare também os histogramas produzidos. Compare os resultados.

par(mfrow=c(2,2))
hist(rnorm(100,50,10),xlim=c(0,100),main='hist A')
plot(density(rnorm(100,50,10)),xlim=c(0,100),main='density A')
hist(rnorm(100,50,20),xlim=c(0,100),main='hist B')
plot(density(rnorm(100,50,20)),xlim=c(0,100),main='density B')

### Exercício Considere a base.

df = read.csv('http://meusite.mackenzie.br/rogerio/TIC/mystocksn.csv')
head(df)
##         data   IBOV VALE3 PETR4  DOLAR
## 1 2020-01-02 118573 13.45 16.27 4.0163
## 2 2020-01-03 117707 13.29 15.99 4.0234
## 3 2020-01-06 116878 13.14 16.22 4.0570
## 4 2020-01-07 116662 13.23 16.06 4.0604
## 5 2020-01-08 116247 13.22 15.70 4.0662
## 6 2020-01-09 115947 12.99 15.75 4.0628

4.8.9 Exercício

Por quê o gráfico abaixo não exibe os quartis de cada data?

boxplot(DOLAR ~ data, data=df)