Os gráficos de 1 a 6 foram elaborados com as funções tradicionais do R. Nas questões de 7 a 10, foi utilizado o pacote plotly. Os dados estão na pasta dados, junto do arquivo do relatório.

Questões

Questão 1 — Tempo de resposta

Os dados abaixo representam tempos de resposta para diferentes quantidades de fogs. O gráfico de linhas compara todos os cenários; os cinco gráficos de barras comparam cada cenário com a configuração sem fog, usando escala logarítmica no eixo vertical.

clock <- c(0.1, 0.5, 1, 1.5, 2, 2.5, 3)

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)

cenarios <- list("1 Fog" = MRT_1F, "3 Fogs" = MRT_3F,
                 "5 Fogs" = MRT_5F, "10 Fogs" = MRT_10F,
                 "15 Fogs" = MRT_15F, "Sem Fog" = MRT_sem_F)
cores_linha <- c("black", "orange", "red", "blue", "purple", "darkgreen")

# O primeiro gráfico ocupa as duas colunas; abaixo ficam cinco comparações.
graphics::layout(matrix(c(1, 1, 2, 3, 4, 5, 6, 0), nrow = 4, byrow = TRUE),
       heights = c(2.5, 1.5, 1.5, 1.5))
par(mar = c(4, 4.6, 3, 1))
plot(clock, MRT_1F, type = "o", col = cores_linha[1], pch = 1,
     xlab = "Intervalo entre requisições (s)",
     ylab = "Tempo de resposta (s)",
     main = "Tempo de resposta por configuração",
     ylim = c(0, max(MRT_1F) * 1.05))
for (i in 2:length(cenarios)) {
  lines(clock, cenarios[[i]], type = "o", col = cores_linha[i], pch = i)
}
legend("topright", legend = names(cenarios), col = cores_linha,
       lty = 1, pch = seq_along(cenarios), cex = 0.85, bty = "n")

# Cada matriz tem duas linhas: sem fog e a configuração escolhida.
nomes <- c("1 Fog", "3 Fogs", "5 Fogs", "10 Fogs", "15 Fogs")
for (i in seq_along(nomes)) {
  valores <- rbind("Sem Fog" = MRT_sem_F, "Com Fog" = cenarios[[i]])
  par(mar = c(4, 4.5, 3, 1))
  barplot(valores, beside = TRUE, log = "y", col = c("#E6E6E6", "#666666"),
          names.arg = clock, ylim = c(0.1, max(valores) * 1.4),
          main = paste("Sem Fog x", nomes[i]),
          xlab = "Intervalo (s)", ylab = "Resposta (s) — log",
          cex.names = 0.75, cex.main = 0.95)
  legend("topright", fill = c("#E6E6E6", "#666666"),
         legend = c("Sem Fog", nomes[i]), bty = "n", cex = 0.7)
}

graphics::layout(1)

Os tempos de resposta diminuem quando o intervalo entre requisições aumenta. A escala logarítmica permite visualizar tanto os valores muito altos quanto os menores.

Questão 2 — Barras empilhadas

A tabela fornecida no enunciado relaciona a avaliação da refeição à faixa de preço. As colunas apresentam percentuais por faixa, e as categorias de avaliação são empilhadas em cada barra.

refeicoes <- matrix(c(53.8, 43.6, 2.6,
                       33.9, 54.2, 11.9,
                       2.6, 60.5, 36.8,
                       0.0, 21.4, 78.6),
                    nrow = 3,
                    dimnames = list(c("Good", "Very Good", "Excellent"),
                                    c("$10–19", "$20–29", "$30–39", "$40–49")))
cores <- c("#C5D9ED", "#6598C8", "#24598A")
par(mar = c(5, 4, 4, 7), xpd = TRUE)
barplot(refeicoes, col = cores, ylim = c(0, 110),
        main = "Qualidade das refeições por faixa de preço",
        xlab = "Faixa de preço", ylab = "Percentual (%)")
legend("topright", inset = c(-0.21, 0),
       legend = rownames(refeicoes), fill = cores, bty = "n")

par(xpd = FALSE)

Nas faixas de preço mais altas, a categoria Excellent representa uma parcela maior das avaliações. Alguns totais podem apresentar diferença de 0,1 ponto percentual devido aos arredondamentos da tabela original.

Questão 3 — Histograma de temperaturas

Selecionam-se as observações do mês de maio (Month == 5) no conjunto airquality. Antes de construir o histograma, converte-se a temperatura de Fahrenheit para Celsius.

data("airquality")
temperaturas_maio <- airquality$Temp[airquality$Month == 5]
temperaturas_celsius <- (temperaturas_maio - 32) / 1.8

hist(temperaturas_celsius, freq = FALSE,
     col = "lightblue", border = "white",
     main = "Temperaturas de maio em Celsius",
     xlab = "Temperatura (°C)", ylab = "Densidade")
lines(density(temperaturas_celsius, na.rm = TRUE),
      col = "red", lwd = 2)
legend("topright", legend = "Curva de densidade",
       col = "red", lwd = 2, bty = "n")

A curva vermelha mostra uma estimativa da distribuição das temperaturas registradas em maio.

Questão 4 — Vendas por país

O gráfico de setores apresenta a participação percentual de cada país nas vendas. Os dados foram carregados do arquivo Sales.txt fornecido com a atividade.

sales <- read.table("dados/Sales.txt", header = TRUE)
percentual <- 100 * sales$SALES / sum(sales$SALES)
cores_paises <- c("#4E79A7", "#F28E2B", "#E15759",
                   "#76B7B2", "#59A14F", "#EDC948")

# O gráfico e a legenda ficam em áreas separadas para evitar cortes.
graphics::layout(matrix(c(1, 2), nrow = 2), heights = c(5, 1))
par(mar = c(0, 2, 3, 2))
pie(sales$SALES,
    labels = paste0(round(percentual, 1), "%"),
    col = cores_paises, main = "Participação nas vendas por país")
par(mar = c(0, 0, 0, 0))
plot.new()
legend("center", legend = sales$COUNTRY,
       fill = cores_paises, ncol = 3, bty = "n", cex = 0.9)

graphics::layout(1)

As porcentagens foram calculadas dividindo as vendas de cada país pelo total de vendas dos seis países.

Questão 5 — Boxplot de inseticidas

O conjunto InsectSprays, disponível no R, registra contagens de insetos para seis tipos de inseticidas. A opção outline = FALSE oculta os pontos considerados valores atípicos no gráfico.

data("InsectSprays")
boxplot(count ~ spray, data = InsectSprays,
        outline = FALSE, col = "yellow",
        main = "Contagem de insetos por inseticida",
        xlab = "Tipo de inseticida", ylab = "Contagem de insetos")

O boxplot permite comparar a mediana e a dispersão das contagens entre os seis grupos. A opção escolhida apenas oculta a representação dos outliers; não remove esses registros dos dados.

Questão 6 — Monitoramento da memória

Os quatro arquivos registram o uso de memória de uma máquina virtual. Como há valores em MB e GB, todos são convertidos para megabytes. O eixo horizontal representa as horas transcorridas a partir da primeira coleta de cada arquivo.

Em parte dos registros do arquivo 0.5, há duas datas concatenadas em currentTime. Para manter a continuidade, a sequência dos dias é reconstruída pelas passagens de 23h para 0h, preservando os horários registrados. As diferenças são calculadas com difftime().

preparar_monitoramento <- function(arquivo) {
  dados <- read.csv(arquivo, stringsAsFactors = FALSE)

  # Extrai apenas o horário (hora, minuto e segundo) de cada registro.
  horario <- sub(".* ([0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]+)$",
                 "\\1", dados$currentTime)

  # Descobre as passagens de um dia para outro usando os horários.
  hora_base <- as.POSIXct(paste("2000-01-01", horario),
                          format = "%Y-%m-%d %H:%M:%OS", tz = "UTC")
  segundos <- as.numeric(difftime(
    hora_base, as.POSIXct("2000-01-01 00:00:00", tz = "UTC"),
    units = "secs"))
  viradas <- c(0, cumsum(diff(segundos) < -12 * 3600))
  data_inicial <- as.Date(substr(dados$currentTime[1], 1, 10))
  datas <- data_inicial + viradas
  instante <- as.POSIXct(paste(datas, horario),
                        format = "%Y-%m-%d %H:%M:%OS", tz = "UTC")
  tempo_horas <- as.numeric(difftime(instante, instante[1], units = "hours"))

  # Separa o número da unidade (MB, GB ou TB).
  valor <- as.numeric(sub("[A-Za-z]+$", "", dados$usedMemory))
  unidade <- toupper(sub("^[0-9.]+", "", dados$usedMemory))
  memoria_mb <- ifelse(unidade == "TB", valor * 1000000,
                       ifelse(unidade == "GB", valor * 1024,
                              ifelse(unidade == "MB", valor, NA_real_)))
  if (anyNA(tempo_horas) || anyNA(memoria_mb)) {
    stop("Há datas ou unidades de memória que não puderam ser convertidas.")
  }
  data.frame(tempo_horas = tempo_horas, memoria_mb = memoria_mb)
}

sem_carga <- preparar_monitoramento("dados/monitoringCloudData_NONE.csv")
carga_01 <- preparar_monitoramento("dados/monitoringCloudData_0.1.csv")
carga_05 <- preparar_monitoramento("dados/monitoringCloudData_0.5.csv")
carga_1 <- preparar_monitoramento("dados/monitoringCloudData_1.csv")

# Organiza os quatro gráficos em duas linhas e duas colunas.
graphics::layout(matrix(1:4, nrow = 2, byrow = TRUE))
par(mar = c(4, 4.6, 3, 1))
plot(sem_carga$tempo_horas, sem_carga$memoria_mb, type = "l",
     col = "black", main = "Memória: sem carga",
     xlab = "Tempo (horas)", ylab = "Memória usada (MB)")
plot(carga_01$tempo_horas, carga_01$memoria_mb, type = "l",
     col = "black", main = "Memória: carga 0.1",
     xlab = "Tempo (horas)", ylab = "Memória usada (MB)")
plot(carga_05$tempo_horas, carga_05$memoria_mb, type = "l",
     col = "black", main = "Memória: carga 0.5",
     xlab = "Tempo (horas)", ylab = "Memória usada (MB)")
plot(carga_1$tempo_horas, carga_1$memoria_mb, type = "l",
     col = "black", main = "Memória: carga 1.0",
     xlab = "Tempo (horas)", ylab = "Memória usada (MB)")

graphics::layout(1)

Os gráficos mostram a evolução do uso de memória durante o monitoramento. Como as faixas de valores variam bastante entre os cenários, cada gráfico utiliza sua própria escala vertical.

Questão 7 — Países com mais conteúdos

Nesta questão, foi considerada apenas uma origem por conteúdo: registros sem país informado e registros com mais de um país (separados por vírgula) foram desconsiderados. A contagem mostra os dez países com mais títulos nessa seleção.

library(plotly)
netflix <- read.csv("dados/netflix_titles.csv", stringsAsFactors = FALSE,
                    fileEncoding = "UTF-8")
netflix$country <- trimws(netflix$country)
origem_unica <- netflix[!is.na(netflix$country) &
                         netflix$country != "" &
                         !grepl(",", netflix$country), ]
contagem <- sort(table(origem_unica$country), decreasing = TRUE)
top_10 <- head(contagem, 10)
paises <- data.frame(Pais = names(top_10), Total = as.integer(top_10))

fig_paises <- plot_ly(data = paises, labels = ~Pais, values = ~Total,
                       type = "pie", textinfo = "percent+label")
plotly::layout(fig_paises,
               title = "10 países com mais conteúdos de origem única")

O gráfico apresenta a distribuição percentual apenas entre os dez países selecionados, não entre todos os títulos da base.

Questão 8 — Tabela dos dez países

A tabela abaixo utiliza os mesmos países e as mesmas contagens da questão 7. O cabeçalho tem fundo cinza e texto branco, e todas as células têm alinhamento centralizado.

plot_ly(type = "table",
  header = list(
    values = list("País", "Total de conteúdos"),
    fill = list(color = "#777777"),
    font = list(color = "white", size = 14),
    align = c("center", "center")
  ),
  cells = list(
    values = list(paises$Pais, paises$Total),
    fill = list(color = "#F5F5F5"),
    align = c("center", "center"),
    height = 28
  )
)

Questão 9 — Conteúdos por década

A década é obtida arredondando o ano de lançamento para baixo até a dezena mais próxima. As duas séries de valores representam os filmes e as séries disponíveis na base.

netflix$decada <- (netflix$release_year %/% 10) * 10
qtd_decadas <- as.data.frame(table(netflix$decada, netflix$type),
                            stringsAsFactors = FALSE)
names(qtd_decadas) <- c("Decada", "Tipo", "Total")
qtd_decadas$Decada <- as.integer(as.character(qtd_decadas$Decada))

series <- subset(qtd_decadas, Tipo == "TV Show")
filmes <- subset(qtd_decadas, Tipo == "Movie")

fig_decadas <- plot_ly()
fig_decadas <- add_trace(fig_decadas, x = series$Decada, y = series$Total,
                         type = "scatter", mode = "lines+markers",
                         name = "Séries", line = list(color = "blue"))
fig_decadas <- add_trace(fig_decadas, x = filmes$Decada, y = filmes$Total,
                         type = "scatter", mode = "lines+markers",
                         name = "Filmes", line = list(color = "#D9AD00"))
fig_decadas <- plotly::layout(fig_decadas,
                      title = "Quantidade de conteúdos por década",
                      xaxis = list(title = "Década", dtick = 10),
                      yaxis = list(title = "Quantidade de conteúdos"))
fig_decadas

Foram incluídos os anos presentes na base. Por exemplo, a década de 2000 corresponde ao período de 2000 a 2009.

Questão 10 — Filmes por gênero e ano

Consideram-se apenas os filmes lançados entre 2000 e 2010, inclusive. Quando um título possui mais de um gênero, somente o primeiro da coluna listed_in é utilizado. As barras são agrupadas por ano.

filmes_2000 <- subset(netflix,
                       type == "Movie" &
                       release_year >= 2000 & release_year <= 2010)
filmes_2000$genero <- trimws(sub(",.*", "", filmes_2000$listed_in))
anos <- 2000:2010
generos <- c("Dramas", "Action & Adventure", "Comedies")

qtd_genero <- table(factor(filmes_2000$release_year, levels = anos),
                    factor(filmes_2000$genero, levels = generos))

fig_generos <- plot_ly()
fig_generos <- add_bars(fig_generos, x = anos,
                        y = as.integer(qtd_genero[, "Dramas"]),
                        name = "Dramas", marker = list(color = "#1F77B4"))
fig_generos <- add_bars(fig_generos, x = anos,
                        y = as.integer(qtd_genero[, "Action & Adventure"]),
                        name = "Action & Adventure",
                        marker = list(color = "#FF7F0E"))
fig_generos <- add_bars(fig_generos, x = anos,
                        y = as.integer(qtd_genero[, "Comedies"]),
                        name = "Comedies", marker = list(color = "#2CA02C"))
fig_generos <- plotly::layout(fig_generos, barmode = "group",
                      title = "Filmes por gênero entre 2000 e 2010",
                      xaxis = list(title = "Ano de lançamento", dtick = 1),
                      yaxis = list(title = "Quantidade de filmes"))
fig_generos

Os três gêneros aparecem lado a lado em cada ano. Títulos de outros gêneros não são contados nesta comparação.