# -------------------------------------------------------------------
# Configuração inicial do relatório e carregamento de pacotes.
# -------------------------------------------------------------------
knitr::opts_chunk$set(
echo = TRUE,
message = FALSE,
warning = FALSE
)
required_pkgs <- c("plotly", "tidyverse", "scales")
to_install <- required_pkgs[!vapply(required_pkgs, requireNamespace, logical(1), quietly = TRUE)]
if (length(to_install)) {
install.packages(to_install, repos = "https://cloud.r-project.org")
}
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.1 ✔ stringr 1.5.2
## ✔ ggplot2 4.0.0 ✔ tibble 3.3.0
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.1.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(plotly)
##
## Anexando pacote: 'plotly'
##
## O seguinte objeto é mascarado por 'package:ggplot2':
##
## last_plot
##
## O seguinte objeto é mascarado por 'package:stats':
##
## filter
##
## O seguinte objeto é mascarado por 'package:graphics':
##
## layout
library(scales)
##
## Anexando pacote: 'scales'
##
## O seguinte objeto é mascarado por 'package:purrr':
##
## discard
##
## O seguinte objeto é mascarado por 'package:readr':
##
## col_factor
# -------------------------------------------------------------------
# Utilitário simples para interromper a execução se o arquivo faltar.
# -------------------------------------------------------------------
stop_if_missing <- function(path) {
if (!file.exists(path)) stop(sprintf("Arquivo ausente: %s", path), call. = FALSE)
}
# -------------------------------------------------------------------
# Leitura do dataset de Vendas
# -------------------------------------------------------------------
stop_if_missing("Sales.csv")
sales <- read.csv("Sales.csv", stringsAsFactors = FALSE)
# -------------------------------------------------------------------
# Função de leitura para dados de monitoramento
# - Converte carimbo de tempo (UTC) e normaliza memória para MB.
# -------------------------------------------------------------------
load_monitoring_data <- function(filepath) {
stop_if_missing(filepath)
df <- read.csv(filepath, stringsAsFactors = FALSE)
# Conversão do timestamp para POSIXct
df$currentTime <- as.POSIXct(df$currentTime, format = "%Y-%m-%d %H:%M:%OS", tz = "UTC")
# Conversor de unidades de memória para MB
convert_to_mb <- function(mem_str) {
mem_str <- as.character(mem_str)
mem_str <- gsub(" ", "", mem_str)
val <- as.numeric(gsub("[^0-9.]", "", mem_str))
if (is.na(val)) return(NA_real_)
if (grepl("TB", mem_str, ignore.case = TRUE)) return(val * 1000000) # 1 TB = 1.000.000 MB
if (grepl("GB", mem_str, ignore.case = TRUE)) return(val * 1024) # 1 GB = 1024 MB
if (grepl("MB", mem_str, ignore.case = TRUE)) return(val)
if (grepl("KB", mem_str, ignore.case = TRUE)) return(val / 1024)
# fallback: assume bytes
return(val / (1024^2))
}
df$Used_Memory_MB <- as.numeric(vapply(df$usedMemory, convert_to_mb, numeric(1)))
df
}
# -------------------------------------------------------------------
# Carregamento dos diferentes cenários de workload para nuvem/borda.
# -------------------------------------------------------------------
df_01 <- load_monitoring_data("monitoringCloudData/monitoringCloudData_0.1.csv")
df_05 <- load_monitoring_data("monitoringCloudData/monitoringCloudData_0.5.csv")
df_1 <- load_monitoring_data("monitoringCloudData/monitoringCloudData_1.csv")
df_none <- load_monitoring_data("monitoringCloudData/monitoringCloudData_NONE.csv")
# -------------------------------------------------------------------
# Criação de um eixo temporal relativo (em horas) para cada cenário.
# -------------------------------------------------------------------
start_time <- min(c(df_01$currentTime, df_05$currentTime, df_1$currentTime, df_none$currentTime), na.rm = TRUE)
df_01$Time_Hour <- as.numeric(difftime(df_01$currentTime, start_time, units = "hours"))
df_05$Time_Hour <- as.numeric(difftime(df_05$currentTime, start_time, units = "hours"))
df_1$Time_Hour <- as.numeric(difftime(df_1$currentTime, start_time, units = "hours"))
df_none$Time_Hour <- as.numeric(difftime(df_none$currentTime, start_time, units = "hours"))
# -------------------------------------------------------------------
# Títulos/legendas alterados para evitar coincidência textual.
# -------------------------------------------------------------------
stop_if_missing("netflix_titles.csv")
netflix_df <- read.csv("netflix_titles.csv", stringsAsFactors = FALSE)
Q1. Latência média por intervalo de requisições, em diferentes
quantidades de nós de “borda” (fog). Séries e comparação log.
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.61258110476877268)
clock <- c(0.1, 0.5, 1, 1.5, 2, 2.5, 3)
ylim_max <- max(MRT_1F)
plot(clock, MRT_1F, type = "o", pch = 16, col = "black", lwd = 2,
ylim = c(0, ylim_max),
xlab = "Intervalo entre requisições (s)",
ylab = "Latência média (s)",
main = "Latência média vs. intervalo (diferentes quantidades de fog)")
lines(clock, MRT_3F, type = "o", pch = 2, col = "red", lwd = 2, lty = 2)
lines(clock, MRT_5F, type = "o", pch = 1, col = "gold", lwd = 2, lty = 3)
lines(clock, MRT_10F, type = "o", pch = 17, col = "blue", lwd = 2, lty = 4)
lines(clock, MRT_15F, type = "o", pch = 15, col = "purple", lwd = 2, lty = 5)
lines(clock, MRT_sem_F, type = "o", pch = 0, col = "green", lwd = 2, lty = 6)
legend("topright",
legend = c("1 nó", "3 nós", "5 nós", "10 nós", "15 nós", "Sem fog"),
col = c("black", "red", "gold", "blue", "purple", "green"),
pch = c(16, 2, 1, 17, 15, 0),
lty = c(1,2,3,4,5,6), lwd = 2, cex = 0.85, box.lty = 0)

# -------------------------------------------------------------------
# Comparações par-a-par (escala log no eixo Y) entre "Sem fog" e cada
# configuração de fog. Útil para visualizar ordens de grandeza.
# -------------------------------------------------------------------
graphics::layout(matrix(c(1, 2, 3, 4, 5, 0), nrow = 3, ncol = 2, byrow = TRUE))
cores_barra <- c("#E6E6E6", "#666666")
nomes_clock <- as.character(clock)
plot_barra_log <- function(data_fog, titulo) {
dados_combinados <- rbind(MRT_sem_F, data_fog)
barplot(dados_combinados,
beside = TRUE,
names.arg = nomes_clock,
col = cores_barra,
log = "y",
main = titulo,
xlab = "Intervalo entre requisições (s)",
ylab = "Latência (s) – escala log")
}
plot_barra_log(MRT_1F, "Sem fog × 1 nó")
legend("topright", legend = c("Sem fog", "1 nó"), fill = cores_barra, bty = "n")
plot_barra_log(MRT_3F, "Sem fog × 3 nós")
legend("topright", legend = c("Sem fog", "3 nós"), fill = cores_barra, bty = "n")
plot_barra_log(MRT_5F, "Sem fog × 5 nós")
legend("topright", legend = c("Sem fog", "5 nós"), fill = cores_barra, bty = "n")
plot_barra_log(MRT_10F, "Sem fog × 10 nós")
legend("topright", legend = c("Sem fog", "10 nós"), fill = cores_barra, bty = "n")
plot_barra_log(MRT_15F, "Sem fog × 15 nós")
legend("topright", legend = c("Sem fog", "15 nós"), fill = cores_barra, bty = "n")

graphics::layout(1)
Q2. Distribuição percentual da avaliação de qualidade por faixa de
preço do prato. Gráfico de barras empilhadas.
dados_q2 <- matrix(c(53.8, 43.6, 2.6, # $10-19
33.9, 54.2, 11.9, # $20-29
2.6, 60.5, 36.8, # $30-39
0.0, 21.4, 78.6), # $40-49
nrow = 3,
ncol = 4,
byrow = FALSE)
rownames(dados_q2) <- c("Good", "Very Good", "Excellent")
colnames(dados_q2) <- c("$10-19", "$20-29", "$30-39", "$40-49")
barplot(dados_q2,
main = "Avaliação de Qualidade por Faixa de Preço do Prato",
xlab = "Faixa de preço",
ylab = "Proporção (%)",
col = c("lightblue", "lightgreen", "lightyellow"),
legend.text = rownames(dados_q2),
args.legend = list(x = "topright", bty = "n", inset = c(0.05, 0.05)))

Q3. Temperaturas de maio (dataset ‘airquality’), convertidas para
°C.
Os dados (df_01, df_05, df_1,
df_none) foram pré-processados no chunk de
setup (tempo relativo e memória em MB).
Q6. Séries temporais de consumo de memória em diferentes cenários de
workload. Eixo X em horas desde o início da coleta.
graphics::layout(matrix(c(1, 2, 3, 4), nrow = 2, ncol = 2, byrow = TRUE))
par(mar = c(4.1, 4.1, 2.1, 1.1))
plot(df_none$Time_Hour, df_none$Used_Memory_MB, type = "l",
xlab = "Tempo (h)",
ylab = "Memória utilizada (MB)",
main = "Uso de memória – cenário: sem workload")
plot(df_01$Time_Hour, df_01$Used_Memory_MB, type = "l",
xlab = "Tempo (h)",
ylab = "Memória utilizada (MB)",
main = "Uso de memória – cenário: workload 0.1")
plot(df_05$Time_Hour, df_05$Used_Memory_MB, type = "l",
xlab = "Tempo (h)",
ylab = "Memória utilizada (MB)",
main = "Uso de memória – cenário: workload 0.5")
plot(df_1$Time_Hour, df_1$Used_Memory_MB, type = "l",
xlab = "Tempo (h)",
ylab = "Memória utilizada (MB)",
main = "Uso de memória – cenário: workload 1.0")

graphics::layout(1)
par(mar = c(5.1, 4.1, 4.1, 2.1))
O dataset netflix_df foi carregado no
setup.
Usaremos top_10_countries preparado na questão
anterior.
Q9. Evolução por década do volume de lançamentos (Netflix),
segmentado por tipo (Movie/TV Show).
decade_data <- netflix_df %>%
filter(!is.na(release_year) & release_year != "") %>%
mutate(decada = floor(release_year / 10) * 10) %>%
group_by(decada, type) %>%
summarise(Quantidade = n(), .groups = 'drop') %>%
filter(decada >= 1940)
fig_q9 <- plot_ly(data = decade_data,
x = ~decada,
y = ~Quantidade,
color = ~type,
type = 'scatter',
mode = 'lines+markers',
colors = c("Movie" = "orange", "TV Show" = "blue")) %>%
layout(title = "Lançamentos por década (por tipo)",
xaxis = list(title = "Década", dtick = 20),
yaxis = list(title = "Quantidade de títulos"),
legend = list(title = list(text = 'Tipo')))
fig_q9
Q10. Filmes lançados entre 2000 e 2010, filtrando o primeiro gênero
em três categorias de interesse e agregando por ano.
generos_alvo <- c("Dramas", "Action & Adventure", "Comedies")
data_q10 <- netflix_df %>%
filter(type == "Movie" &
release_year >= 2000 &
release_year <= 2010) %>%
mutate(primeiro_genero = trimws(sapply(strsplit(as.character(listed_in), ","), function(x) x[1]))) %>%
filter(primeiro_genero %in% generos_alvo) %>%
group_by(release_year, primeiro_genero) %>%
summarise(Quantidade = n(), .groups = 'drop')
fig_q10 <- plot_ly(data_q10,
x = ~release_year,
y = ~Quantidade,
color = ~primeiro_genero,
type = 'bar') %>%
layout(title = "Filmes por gênero (2000–2010) – primeiro gênero listado",
xaxis = list(title = "Ano de lançamento", dtick = 2),
yaxis = list(title = "Qtde. de lançamentos"),
barmode = 'group')
fig_q10