Exercícios

Gráfico de Dispersão

ggplot(data = mtcars) +
  aes(x = wt, y = mpg, color = factor(cyl)) +
  geom_point(size = 3, alpha = 0.8) +
  labs(
    title = "Relação entre Peso e Consumo de Combustível",
    x = "Peso do Carro (milhares de libras)",
    y = "Milhas por Galão (mpg)",
    color = "Número de Cilindros"
  ) +
  scale_color_manual(
    values = c("4" = "#E41A1C", "6" = "#377EB8", "8" = "#4DAF4A"),
    labels = c("4 cilindros", "6 cilindros", "8 cilindros")
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
    axis.title = element_text(face = "bold"),
    legend.title = element_text(face = "bold"),
    panel.grid.minor = element_blank()
  )

# Estatísticas descritivas por número de cilindros
estatisticas <- aggregate(cbind(mpg, wt) ~ cyl, 
                         data = mtcars, 
                         FUN = function(x) c(mean = mean(x), sd = sd(x)))

# Formatando a tabela para melhor apresentação
tabela_estatisticas <- data.frame(
  Cilindros = estatisticas$cyl,
  MPG_Média = round(estatisticas$mpg[, "mean"], 2),
  MPG_Desvio_Padrão = round(estatisticas$mpg[, "sd"], 2),
  Peso_Médio = round(estatisticas$wt[, "mean"], 2),
  Peso_Desvio_Padrão = round(estatisticas$wt[, "sd"], 2)
)

kable(tabela_estatisticas, 
      caption = "Estatísticas Descritivas por Número de Cilindros",
      align = "c")
Estatísticas Descritivas por Número de Cilindros
Cilindros MPG_Média MPG_Desvio_Padrão Peso_Médio Peso_Desvio_Padrão
4 26.66 4.51 2.29 0.57
6 19.74 1.45 3.12 0.36
8 15.10 2.56 4.00 0.76

Gráfico de Barras

diamonds_count <- diamonds %>%
  group_by(cut) %>%
  summarise(count = n()) %>%
  arrange(desc(count)) %>%
  mutate(cut = factor(cut, levels = cut))

print(diamonds_count)
## # A tibble: 5 × 2
##   cut       count
##   <ord>     <int>
## 1 Ideal     21551
## 2 Premium   13791
## 3 Very Good 12082
## 4 Good       4906
## 5 Fair       1610
# Estatísticas resumidas por número de cilindros
cat("Média de mpg por número de cilindros:\n")
## Média de mpg por número de cilindros:
tapply(mtcars$mpg, mtcars$cyl, mean)
##        4        6        8 
## 26.66364 19.74286 15.10000
cat("\nMédia de peso por número de cilindros:\n")
## 
## Média de peso por número de cilindros:
tapply(mtcars$wt, mtcars$cyl, mean)
##        4        6        8 
## 2.285727 3.117143 3.999214
# Correlação entre peso e consumo
correlacao <- cor(mtcars$wt, mtcars$mpg)
cat(sprintf("\nCorrelação entre peso e consumo: %.3f", correlacao))
## 
## Correlação entre peso e consumo: -0.868
ggplot(diamonds_count, aes(x = reorder(cut, -count), y = count, fill = cut)) +
  geom_bar(stat = "identity", width = 0.7) +
  geom_text(
    aes(label = format(count, big.mark = ".", decimal.mark = ",")),
    position = position_stack(vjust = 0.5),
    size = 4,
    fontface = "bold",
    color = "white"  
  ) +
  scale_fill_brewer(
    palette = "Spectral",
    name = "Qualidade do Corte"
  ) +
  labs(
    title = "Contagem de Diamantes por Corte (Rótulos Internos)",
    x = "Qualidade do Corte",
    y = "Contagem"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold"),
    legend.position = "none"
  )

Gráfico Boxplot

cores_personalizadas <- c(
  "Ideal" = "#2E8B57",        # Verde marinho
  "Premium" = "#4169E1",      # Azul real
  "Very Good" = "#9370DB",    # Roxo médio
  "Good" = "#FFA500",         # Laranja
  "Fair" = "#DC143C"          # Vermelho carmesim
)

ggplot(diamonds, aes(x = cut, y = price, fill = cut)) +
  geom_boxplot(
    alpha = 0.8,
    outlier.color = "#333333",
    outlier.size = 1.5,
    outlier.alpha = 0.5,
    width = 0.7
  ) +
  
  scale_fill_manual(values = cores_personalizadas) +
  labs(
    title = "Distribuição de Preços dos Diamantes por Qualidade de Corte",
    subtitle = "Análise comparativa dos valores por categoria",
    x = "Qualidade do Corte do Diamante",
    y = "Preço (US$)",
  ) +
  
  scale_y_continuous(
    labels = scales::dollar_format(prefix = "US$ ", big.mark = ".", decimal.mark = ","),
    breaks = seq(0, 20000, 2500)
  ) +
  theme_minimal() +
  theme(
    
    plot.title = element_text(
      hjust = 0.5, 
      face = "bold", 
      size = 16,
      margin = margin(b = 10)
    ),
    plot.subtitle = element_text(
      hjust = 0.5, 
      size = 12, 
      color = "gray40",
      margin = margin(b = 15)
    ),
    plot.caption = element_text(
      hjust = 1,
      size = 9,
      color = "gray50",
      margin = margin(t = 10)
    ),
    
    axis.title.x = element_text(
      face = "bold", 
      size = 12,
      margin = margin(t = 10)
    ),
    axis.title.y = element_text(
      face = "bold", 
      size = 12,
      margin = margin(r = 10)
    ),
    
    axis.text.x = element_text(
      angle = 45,          
      hjust = 1,           
      vjust = 1,           
      size = 11,
      face = "bold",
      color = "gray30"
    ),
    
    axis.text.y = element_text(
      size = 10,
      color = "gray40"
    ),
    
    legend.position = "none",
    
    panel.grid.major.x = element_blank(),
    panel.grid.minor.y = element_blank(),
    panel.grid.major.y = element_line(color = "gray90", linewidth = 0.5),
    
    plot.margin = margin(20, 20, 20, 20)
  )

# Calcular porcentagens
diamonds_count <- diamonds_count %>%
  mutate(
    porcentagem = round((count / sum(count)) * 100, 2),
    porcentagem_acumulada = round(cumsum(porcentagem), 2)
  )

cat("Tabela com estatísticas detalhadas:\n\n")
## Tabela com estatísticas detalhadas:
print(diamonds_count)
## # A tibble: 5 × 4
##   cut       count porcentagem porcentagem_acumulada
##   <ord>     <int>       <dbl>                 <dbl>
## 1 Ideal     21551       40.0                   40.0
## 2 Premium   13791       25.6                   65.5
## 3 Very Good 12082       22.4                   87.9
## 4 Good       4906        9.1                   97.0
## 5 Fair       1610        2.98                 100
cat("\n\nPrincipais conclusões:\n")
## 
## 
## Principais conclusões:
cat("1. O corte 'Ideal' é o mais comum, representando", diamonds_count$porcentagem[1], "% do total\n")
## 1. O corte 'Ideal' é o mais comum, representando 39.95 % do total
cat("2. O corte 'Regular' é o menos frequente, com apenas", diamonds_count$porcentagem[5], "%\n")
## 2. O corte 'Regular' é o menos frequente, com apenas 2.98 %
cat("3. Os 3 cortes de maior qualidade (Ideal, Premium, Muito Bom) representam", 
    sum(diamonds_count$porcentagem[1:3]), "% do total\n")
## 3. Os 3 cortes de maior qualidade (Ideal, Premium, Muito Bom) representam 87.92 % do total

Conceitos fundamentais

Questão 1

Explique a diferença entre os geoms geom_point() e geom_jitter(). Em que situação cada um é mais apropriado?

Resposta: O geom_point() plota os pontos exatamente nas coordenadas dos dados, enquanto o geom_jitter() adiciona um pequeno ruído aleatório para evitar sobreposição de pontos. O uso do geom_point() deve ser realizado quando os dados estiverem bem distribuídos e o geom_jitter() quando houver muitos pontos nas mesmas coordenadas.

Questão 2

Descreva o conceito de ”Gramática dos Gráficos”e como ele é implementado no ggplot2.

Resposta: Trata-se de um framework teórico desenvolvido por Leland Wilkinson que descreve a construção de gráficos estatísticos como uma linguagem formal. Assim como a gramática de uma língua define como combinar palavras para formar frases significativas, a Gramática dos Gráficos define como combinar elementos visuais para criar visualizações de dados significativas.

O pacote ggplot2 do R implementa fielmente a Gramática dos Gráficos através de uma sintaxe consistente e modular:

1. Estrutura Básica

```r

ggplot(data = dados) + # 1. Dados

aes(x = variavel_x, y = variavel_y) + # 2. Estética

geom_point() # 3. Geometria

Essa abordagem transforma a criação de gráficos de uma tarefa artesanal em um processo de engenharia de software, onde gráficos complexos podem ser construídos, modificados e reproduzidos de maneira confiável e eficiente. O sucesso do ggplot2 demonstra a utilidade prática da Gramática dos Gráficos como framework para visualização de dados estatísticos.