Questão 1 - Gráficos com Layout

Questão 1

  1. Definição dos dados Fornecidos
MRT_1F  <- c(517.1468515630205, 85.13094142168089, 30.333207896694553,
             12.694776264558937, 3.3041601673945418, 1.1823111717498882,
             1.1892293502386786)

MRT_3F  <- c(156.68929936163462, 11.540837783562276, 0.4512835621696538,
             0.4509797929766453, 0.4502068233039181, 0.4496185276300172,
             0.4543157082191288)

MRT_5F  <- c(83.90319666471157, 0.3068151086494968, 0.30522314133037304,
             0.3072588968084928, 0.30655265997285697, 0.3055812715727718,
             0.3053297166713006)

MRT_10F <- c(29.55430642951759, 0.19832832665772515, 0.1971923924717474,
             0.19796648905716516, 0.19615594370806338, 0.2034569237883263,
             0.19617420889447737)

MRT_15F <- c(11.317736530583566, 0.167364215666193, 0.16172168266811013,
             0.16701085329580515, 0.1598052657153692, 0.1645934043532696,
             0.16216563797118075)

MRT_sem_F <- c(11.93430909937736, 0.6095414637034009,
               0.6060645101029295, 0.612167181646899, 0.6146761002685637,
               0.6096747087200697, 0.6125810476877268)

clock <- c(0.1, 0.5, 1, 1.5, 2, 2.5, 3)
  1. Organizando o layout
  • Layout() recebe uma matriz que define a posição de cada gráfico na janela gráfica. A matriz abaixo cria 1 linha e 2 colunas: gráfico 1 à esquerda, gráfico 2 à direita
layout(matrix(c(1, 2), nrow = 1, ncol = 2))

# Definindo cores para cada linha
cores <- c("blue", "red", "green", "purple", "orange", "brown")

# Criando o primeiro gráfico com a primeira série
plot(clock, MRT_1F,
     type  = "b",          
     col   = cores[1],    
     pch   = 16,             
     lwd   = 2,             
     xlab  = "Clock (GHz)", 
     ylab  = "MRT (s)",     
     main  = "MRT vs Clock por Frequência",
     ylim  = c(0, max(MRT_1F)))

# Adicionando as demais séries com lines() e legenda
lines(clock, MRT_3F,   type = "b", col = cores[2], pch = 16, lwd = 2)
lines(clock, MRT_5F,   type = "b", col = cores[3], pch = 16, lwd = 2)
lines(clock, MRT_10F,  type = "b", col = cores[4], pch = 16, lwd = 2)
lines(clock, MRT_15F,  type = "b", col = cores[5], pch = 16, lwd = 2)
lines(clock, MRT_sem_F,type = "b", col = cores[6], pch = 16, lwd = 2)

legend("topright",
       legend = c("1F", "3F", "5F", "10F", "15F", "Sem F"),
       col    = cores,
       lwd    = 2,
       pch    = 16,
       bty    = "n") # sem borda na legenda

# Agrupando os valores do primeiro ponto de clock para comparar os MRTs entre frequências
valores_barra <- c(MRT_1F[1], MRT_3F[1], MRT_5F[1],
                   MRT_10F[1], MRT_15F[1], MRT_sem_F[1])

nomes_barra <- c("1F", "3F", "5F", "10F", "15F", "Sem F")

# Alternando as duas cores especificadas
cores_barra <- rep(c("#E6E6E6", "#666666"), length.out = length(valores_barra))

# barplot() com log = "y" aplica escala logarítmica no eixo Y
barplot(valores_barra,
        names.arg = nomes_barra,     
        log       = "y",               
        col       = cores_barra,      
        border    = "black",           
        xlab      = "Frequência",     
        ylab      = "MRT (s) - Escala Log", 
        main      = "MRT por Frequência\n(Escala Logarítmica)")

# Resetando o layout para não afetar gráficos futuros
layout(1)

Questão 2 - Gráfico de Barras Empilhadas

Questão 2

Qualidade de Refeição por Faixa de Preço

  1. Construindo a matriz de dados
  • Cada coluna representa uma faixa de preço
  • Cada linha representa uma categoria de qualidade
  • Os valores são as porcentagens da tabela
dados_refeicao <- matrix(
  c(
    # $10-19  $20-29  $30-39  $40-49
      53.8,   33.9,    2.6,    0.0,   # Good
      43.6,   54.2,   60.5,   21.4,   # Very Good
       2.6,   11.9,   36.8,   78.6    # Excellent
  ),
  nrow  = 3,    
  ncol  = 4,   
  byrow = TRUE  
)
  1. Nomeando linhas e colunas da matriz
  • Isso facilita a leitura e a geração automática
  • dos rótulos no gráfico
rownames(dados_refeicao) <- c("Good", "Very Good", "Excellent")
colnames(dados_refeicao) <- c("$10-19", "$20-29", "$30-39", "$40-49")
  1. Definindo as cores para cada categoria
  • Usamos tons que reflitam a progressão: Good -> amarelo | Very Good -> laranja | Excellent -> verde
cores_qualidade <- c(
  "Good"      = "#F4D03F",  # amarelo
  "Very Good" = "#E67E22",  # laranja
  "Excellent" = "#27AE60"   # verde
)
  1. Gerando o gráfico de barras empilhadas e adicionando linha de grade horizontal para facilitar a leitura dos percentuais
barplot(
  dados_refeicao,
  beside  = FALSE,                        
  col     = cores_qualidade,              
  border  = "white",                      
  ylim    = c(0, 115),                    
  main    = "Qualidade de Refeição por Faixa de Preço", 
  xlab    = "Faixa de Preço (USD)",       
  ylab    = "Percentual (%)",             
  las     = 1,                            
  cex.names = 1.0                         
)

grid(nx = NA, ny = NULL,
     col = "lightgray",
     lty = "dotted",
     lwd = 0.8)

#legenda do topo do gráfico
legend(
  "top",
  legend  = rownames(dados_refeicao),  
  fill    = cores_qualidade,           
  border  = "white",                   
  bty     = "n",                       
  horiz   = TRUE,                      
  cex     = 0.95,                      
  title   = "Qualidade"               
)

Questão 3 - Histograma com curva de densidade

Questão 3

O dataset airquality já vem carregado no R base, vamos filtrar apenas o mês de Maio

  • Conversão de Fahrenheit para Celsius: °C = (°F - 32) / 1.8
  • Para sobrepor a curva de densidade ao histograma, o eixo Y do histograma deve mostrar DENSIDADE e não frequência absoluta. Isso é feito com freq = FALSE (ou probability = TRUE)
  • Adicionando a curva de densidade
    • density() estima a densidade de probabilidade
    • lines() sobrepõe a curva ao gráfico existente
# Filtrando maio do dataset nativo airquality
maio <- subset(airquality, Month == 5)

# Convertendo °F para °C
maio$Temp_C <- (maio$Temp - 32) / 1.8

# Histograma 
hist(maio$Temp_C,
     freq   = FALSE,
     col    = "steelblue",
     border = "white",
     main   = "Distribuição de Temperaturas em Maio",
     xlab   = "Temperatura (°C)",
     ylab   = "Densidade",
     las    = 1)

lines(density(maio$Temp_C),
      col = "red",
      lwd = 2)

legend("topright",
       legend = c("Histograma", "Curva de Densidade"),
       fill   = c("steelblue", NA),
       border = c("white", NA),
       lty    = c(NA, 1),
       col    = c("steelblue", "red"),
       lwd    = c(NA, 2),
       bty    = "n")

Questão 4 - Gráfico de Pizza: Vendas por País

Questão 4

  1. Carregamento
  • Leitura dos dados utilizando read.table com parâmetros de separador e aspas para evitar erros de formatação no arquivo
  1. Limpeza e Identificação
  • Remoção de espaços em branco nos nomes das colunas e identificação dinâmica das variáveis de País e Vendas
  1. Agregação de Dados
  • Consolidação do volume total de vendas agrupado por território geográfico
  1. Preparação Estatística
  • Cálculo do percentual relativo de cada país sobre o faturamento total e ordenação decrescente para facilitar a leitura
  1. Visualização e Legenda
  • Geração do gráfico de setores (pizza) com paleta de cores rainbow, rótulos percentuais diretos e legenda lateral para identificação clara.
sales <- read.table(
  "https://training-course-material.com/images/8/8f/Sales.txt",
  header    = TRUE,
  sep       = "",       
  quote     = "\"",    
  fill      = TRUE,     
  comment.char = ""
)

# Renomeando colunas para padronizar
colnames(sales) <- trimws(colnames(sales)) 

# Verificando se as colunas necessárias existem
col_pais  <- names(sales)[1]  # País é a 1ª coluna
col_sales <- names(sales)[2]  # Vendas é a 2ª coluna

vendas_por_pais <- aggregate(
  sales[[col_sales]] ~ sales[[col_pais]],
  FUN = sum
)

# Renomeando colunas do resultado e ordenando maior para menor
colnames(vendas_por_pais) <- c("Country", "Sales")
vendas_por_pais <- vendas_por_pais[order(-vendas_por_pais$Sales), ]

# Calculando porcentagens
total_geral <- sum(vendas_por_pais$Sales)
vendas_por_pais$Percentual <- round(
  (vendas_por_pais$Sales / total_geral) * 100, 1
)

# Criando rótulos com porcentagem e definindo cores 
rotulos <- paste(vendas_por_pais$Country, "-", vendas_por_pais$Percentual, "%")
cores_pizza <- rainbow(nrow(vendas_por_pais))

# Gerando gráfico e adicionando legenda
pie(vendas_por_pais$Sales,
    labels = rotulos,
    col    = cores_pizza,
    main   = "Distribuição de Vendas por País (%)",
    cex    = 0.9)

legend("bottomleft",
       legend = vendas_por_pais$Country,
       fill   = cores_pizza,
       bty    = "n",
       cex    = 0.8)

Questão 5 - Boxplot sem Outliers - InsectSprays

Questão 5

O dataset InsectSprays já está disponível no R base. Ele contém contagens de insetos (count) para 6 tipos e inseticidas (spray): A, B, C, D, E, F

boxplot(count ~ spray,
        data    = InsectSprays,
        outline = FALSE,       
        col     = "yellow",    
        border  = "darkgray",  
        lwd     = 1.5,         
        main    = "Contagem de Insetos por Tipo de Inseticida\n(sem outliers)",
        xlab    = "Tipo de Inseticida",  
        ylab    = "Contagem de Insetos", 
        las     = 1)           

Questão 6 - Monitoramento de Máquina Virtual

Questão 6

Nesta atividade, analisaremos os dados de monitoramento de recursos de uma máquina virtual sob diferentes cargas de trabalho (workloads): NONE, 0.1, 0.5 e 1.0.

O objetivo é gerar gráficos de linha do tempo mostrando a evolução do uso de memória (em MB) ao longo do tempo (em horas), para cada cenário de carga.

1. As principais etapas são:

  1. Leitura dos dados
  2. Ajuste da coluna currentTime para tempo contínuo em horas
  3. Conversão da coluna usedMemory para megabytes (MB)
  4. Geração dos gráficos organizados com layout()

2. Carregando os Pacotes Necessários

Usaremos principalmente: - readr: para leitura dos arquivos CSV - dplyr: para manipulação dos dados (mutate, select, etc.) - stringr: para manipulação de strings e uso de regex - ggplot2: para visualização (referência, mas usaremos plot base para layout())

library(tidyverse)

3. Leitura dos Dados

# Lemos os 4 arquivos CSV com read_csv() do pacote readr (parte do tidyverse)
df_none <- read_csv("monitoringCloudData_NONE.csv", show_col_types = FALSE)
df_01   <- read_csv("monitoringCloudData_0.1.csv",  show_col_types = FALSE)
df_05   <- read_csv("monitoringCloudData_0.5.csv",  show_col_types = FALSE)
df_1    <- read_csv("monitoringCloudData_1.csv",    show_col_types = FALSE)

4. Funções de Pré-processamento

Antes de processar cada dataset individualmente, vamos criar duas funções reutilizáveis: uma para converter o tempo e outra para converter a memória. Isso segue o princípio DRY (Don’t Repeat Yourself), tornando o código mais limpo e manutenível.

4.1 Função para Converter o Tempo em Horas

#'time_hours' representa o tempo decorrido em horas desde a primeira observação

# Usamos difftime() para calcular a diferença entre cada timestamp e o primeiro timestamp 
# as.POSIXct() é usada para garantir que a coluna currentTime seja interpretada corretamente como data/hora.

converter_tempo <- function(df) {
  df %>%
    mutate(
      currentTime = as.POSIXct(currentTime),

      time_hours = as.numeric(
        difftime(currentTime, first(currentTime), units = "hours")
      )
    )
}

4.2 Função para Converter a Memória para MB

converter_memoria <- function(df) {
  df %>%
    mutate(
      # Extrai somente a parte numérica usando regex
      valor_num = as.numeric(
        str_extract(usedMemory, "[0-9]+\\.?[0-9]*")
      ),
      
      # Extrai somente a unidade (MB, GB ou TB)
      unidade = str_extract(usedMemory, "[A-Za-z]+"),
      
      # Aplica a conversão com base na unidade encontrada
      usedMemory_MB = case_when(
        unidade == "MB" ~ valor_num * 1,          
        unidade == "GB" ~ valor_num * 1024,       
        unidade == "TB" ~ valor_num * 1000000,    
        TRUE            ~ NA_real_                
      )
    )
}

5. Aplicando o Pré-processamento

  • Primeiro convertemos o tempo, depois a memória
  • Por fim, selecionamos apenas as colunas que nos interessam para manter os dados limpos e organizados.
df_none_clean <- df_none %>%
  converter_tempo() %>%
  converter_memoria() %>%
  select(time_hours, usedMemory_MB)

df_01_clean <- df_01 %>%
  converter_tempo() %>%
  converter_memoria() %>%
  select(time_hours, usedMemory_MB)

df_05_clean <- df_05 %>%
  converter_tempo() %>%
  converter_memoria() %>%
  select(time_hours, usedMemory_MB)

df_1_clean <- df_1 %>%
  converter_tempo() %>%
  converter_memoria() %>%
  select(time_hours, usedMemory_MB)

6. Geração dos Gráficos

layout(matrix(c(1, 2,
                3, 4),
              nrow = 2,      
              ncol = 2,      
              byrow = TRUE)) 

# Ajuste das margens para melhor visualização
par(mar = c(5, 5, 4, 2))

#Gráfico 1
plot(
  x    = df_none_clean$time_hours,
  y    = df_none_clean$usedMemory_MB,
  type = "l",                             
  main = "Memory Analysis (None Workload)",
  xlab = "Time (hour)",
  ylab = "Used Memory (MB)",
  col  = "black",
  lwd  = 0.5                              
)

#Gráfico 2
plot(
  x    = df_01_clean$time_hours,
  y    = df_01_clean$usedMemory_MB,
  type = "l",
  main = "Memory Analysis (Workload of 0.1)",
  xlab = "Time (hour)",
  ylab = "Used Memory (MB)",
  col  = "black",
  lwd  = 0.5
)

#Gráfico 3
plot(
  x    = df_05_clean$time_hours,
  y    = df_05_clean$usedMemory_MB,
  type = "l",
  main = "Memory Analysis (Workload of 0.5)",
  xlab = "Time (hour)",
  ylab = "Used Memory (MB)",
  col  = "black",
  lwd  = 0.5
)

#Gráfico 4
plot(
  x    = df_1_clean$time_hours,
  y    = df_1_clean$usedMemory_MB,
  type = "l",
  main = "Memory Analysis (Workload of 1.0)",
  xlab = "Time (hour)",
  ylab = "Used Memory (MB)",
  col  = "black",
  lwd  = 0.5
)

# Restaura o layout padrão após a plotagem
layout(1)

Questão 7 - Gráfico de Pizza: 10 países

Questão 7

  1. Carregamento das bibliotecas necessárias
  • tidyverse: manipulação e transformação de dados
  • plotly: visualizações interativas
library(tidyverse)
library(plotly)
  1. Leitura do dataset Netflix Movies and TV Shows
  • O argumento na.strings garante que campos vazios e “nan” sejam tratados como NA nativamente
netflix <- read_csv(
  "netflix_titles.csv",
  na = c("", "NA", "nan", "NaN")
)
  1. Filtrar registros com apenas UM país de origem

A coluna “country” pode conter múltiplos países separados por vírgula. Utilizamos str_detect() do stringr para excluir registros que contenham vírgula, garantindo que apenas conteúdos com um único país permaneçam.

  1. Contar conteúdos por país
  • Count() já realiza o group_by + summarise(n()) internament
  • Sort=TRUE ordena do maior para o menor automaticamente
top10_paises <- netflix |>
  filter(
    !is.na(country),           
    !str_detect(country, ",") 
  ) |>
  count(country, sort = TRUE) |>

# Selecionando os 10 primeiros
  slice_head(n = 10)
  1. Gráfico de Pizza com Plotly
  • Labels: categorias (países)
  • Values: valores numéricos (contagem)
  • Textinfo: exibe nome + percentual em cada fatia
  • Hoverinfo: informação ao passar o mouse
plot_ly(
  data        = top10_paises,
  labels      = ~country,          
  values      = ~n,                
  type        = "pie",
  textinfo    = "label+percent",   
  hoverinfo   = "label+value+percent", 
  hole        = 0                  
) |>
  layout(
    title = list(
      text = "🎬 Top 10 Países com Mais Conteúdo na Netflix",
      font = list(size = 18)
    ),
    legend = list(title = list(text = "<b>País</b>"))
  )

Questão 8 - Tabela com as colunas “País” e “Total de conteúdos”

Questão 8

Podemos reutilizar o objeto top10_paises criado na questão anterior.A tabela é dividida em dois componentes:

  • header: linha de cabeçalho (definimos cor e estilo)
  • cells: linhas de dados
tabela_q8 <- top10_paises |>
  rename(
    "País"               = country,
    "Total de Conteúdos" = n
  )

plot_ly(
  type = "table",

  # Cabeçalho
  header = list(
    values = list("<b>País</b>", "<b>Total de Conteúdos</b>"), 
    align  = "center",               # centralização exigida pelo enunciado
    fill   = list(color = "gray"),   # fundo cinza conforme enunciado
    font   = list(
      color = "white",               # letra branca conforme enunciado
      size  = 14
    ),
    line   = list(color = "white", width = 1)
  ),

  # Células de dados
  cells = list(
    values = list(
      tabela_q8$`País`,               
      tabela_q8$`Total de Conteúdos`  
    ),
    align  = "center",               # centralização exigida pelo enunciado
    fill   = list(
      color = c("white", "#f0f0f0") 
    ),
    font   = list(color = "black", size = 13),
    line   = list(color = "gray", width = 1),
    height = 30                      
  )
) |>
  layout(
    title = list(
      text = "Top 10 Países com Mais Conteúdo na Netflix",
      font = list(size = 16)
    )
  )

Questão 9 - Gráfico de Linha

Questão 9

  1. Criar a coluna “década”
  • A lógica é: década = floor(release_year / 10) * 10
    • Isso agrupa corretamente anos de XXX0 a XXX9 em uma mesma década
  1. Contar conteúdos por década e tipo
  • group_by() + summarise() nos dá uma linha por combinação
dados_decada <- netflix |>
  filter(!is.na(release_year)) |>          
  mutate(
    decada = floor(release_year / 10) * 10 
  ) |>
  group_by(decada, type) |>
  summarise(
    total = n(),
    .groups = "drop"                      
  )
  1. Separar séries e filmes para o Plotly
  • Filtramos os dois tipos para criar duas traces (linhas) independentes
  1. Gráfico de linha com duas traces
  • add_trace() adiciona cada linha separadamente, permitindo controle total de cor, nome e marcadores por série de dados
series <- dados_decada |> filter(type == "TV Show")
filmes <- dados_decada |> filter(type == "Movie")

plot_ly() |>

  # Linha para TV Shows
  add_trace(
    data       = series,
    x          = ~decada,
    y          = ~total,
    type       = "scatter",
    mode       = "lines+markers",   
    name       = "TV Show",
    line       = list(color = "blue", width = 2),
    marker     = list(color = "blue", size = 6)
  ) |>

  # Linha para Movies
  add_trace(
    data       = filmes,
    x          = ~decada,
    y          = ~total,
    type       = "scatter",
    mode       = "lines+markers",   
    name       = "Movie",
    line       = list(color = "yellow", width = 2),
    marker     = list(color = "orange", size = 6) 
  ) |>

  layout(
    title = list(
      text = "📺 Quantidade de Conteúdo Netflix por Década",
      font = list(size = 18)
    ),
    xaxis = list(
      title      = "Década",
      tickmode   = "linear",        
      dtick      = 10               
    ),
    yaxis = list(title = "Quantidade de Conteúdo"),
    legend = list(title = list(text = "<b>Tipo</b>"))
  )

Questão 10 - Gráfico de Barras: Gêneros 2000-2010

Questão 10

  1. Definir os gêneros + filtrar e transformar os dados
  • A coluna listed_in contém gêneros separados por “,”
  • str_extract() com regex captura tudo antes da primeira vírgula ou o valor inteiro, se não houver vírgula
generos_interesse <- c("Dramas", "Action & Adventure", "Comedies")
dados_q10 <- netflix |>

  # Apenas filmes
  filter(type == "Movie") |>

  # Apenas anos entre 2000 e 2010
  filter(release_year >= 2000, release_year <= 2010) |>

  # Remove registros sem gênero
  filter(!is.na(listed_in)) |>

  # Extrair apenas o primeiro gênero
  mutate(
    primeiro_genero = str_extract(listed_in, "^[^,]+") |> str_trim()
  ) |>

  # Manter apenas os 3 gêneros de interesse
  filter(primeiro_genero %in% generos_interesse) |>

  # Contar por ano e gênero
  group_by(release_year, primeiro_genero) |>
  summarise(
    total    = n(),
    .groups  = "drop"
  ) |>

  # Garantir que release_year seja tratado como texto no eixo X para evitar interpolação numérica no gráfico
  mutate(release_year = as.character(release_year))
  1. Gráfico de barras lado a lado
  • barmode = “group” no layout() define barras lado a lado (grouped)
  • Cada gênero será uma trace (barra) separada
# Separando os dados por gênero
dramas    <- dados_q10 |> filter(primeiro_genero == "Dramas")
action    <- dados_q10 |> filter(primeiro_genero == "Action & Adventure")
comedies  <- dados_q10 |> filter(primeiro_genero == "Comedies")

plot_ly() |>

  # Barra: Dramas
  add_trace(
    data   = dramas,
    x      = ~release_year,
    y      = ~total,
    type   = "bar",
    name   = "Dramas"
  ) |>

  # Barra: Action & Adventure
  add_trace(
    data   = action,
    x      = ~release_year,
    y      = ~total,
    type   = "bar",
    name   = "Action & Adventure"
  ) |>

  # Barra: Comedies
  add_trace(
    data   = comedies,
    x      = ~release_year,
    y      = ~total,
    type   = "bar",
    name   = "Comedies"
  ) |>

  layout(
    barmode = "group",              
    title   = list(
      text  = "🎬 Filmes por Gênero entre 2000 e 2010",
      font  = list(size = 18)
    ),
    xaxis   = list(
      title    = "Ano de Lançamento",
      type     = "category"         
    ),
    yaxis   = list(title = "Quantidade de Filmes"),
    legend  = list(title = list(text = "<b>Gênero</b>"))
  )