Este relatório apresenta um exercício prático de R Markdown (Xie, Allaire, and Grolemund 2018) focado na análise exploratória de dados. O objetivo é demonstrar um fluxo de trabalho completo, desde o carregamento e manipulação dos dados até a apresentação de resultados em diferentes formatos.
Para esta análise, utilizaremos o conjunto de dados USArrests, que é nativo da linguagem R (R Core Team 2025), e aplicaremos técnicas de manipulação de dados com o pacote tidyverse (Wickham and Grolemund 2017).
O conteúdo deste documento está dividido nas seções a seguir e pode ser navegado usando as abas:
DT.# 1.1 - Carregar USArrests (dataset interno do R)
data("USArrests") # carrega o dataset
df <- USArrests
# 1.2 - observar estrutura inicial
head(df, 6)
## Murder Assault UrbanPop Rape
## Alabama 13.2 236 58 21.2
## Alaska 10.0 263 48 44.5
## Arizona 8.1 294 80 31.0
## Arkansas 8.8 190 50 19.5
## California 9.0 276 91 40.6
## Colorado 7.9 204 78 38.7
str(df)
## 'data.frame': 50 obs. of 4 variables:
## $ Murder : num 13.2 10 8.1 8.8 9 7.9 3.3 5.9 15.4 17.4 ...
## $ Assault : int 236 263 294 190 276 204 110 238 335 211 ...
## $ UrbanPop: int 58 48 80 50 91 78 77 72 80 60 ...
## $ Rape : num 21.2 44.5 31 19.5 40.6 38.7 11.1 15.8 31.9 25.8 ...
summary(df)
## Murder Assault UrbanPop Rape
## Min. : 0.800 Min. : 45.0 Min. :32.00 Min. : 7.30
## 1st Qu.: 4.075 1st Qu.:109.0 1st Qu.:54.50 1st Qu.:15.07
## Median : 7.250 Median :159.0 Median :66.00 Median :20.10
## Mean : 7.788 Mean :170.8 Mean :65.54 Mean :21.23
## 3rd Qu.:11.250 3rd Qu.:249.0 3rd Qu.:77.75 3rd Qu.:26.18
## Max. :17.400 Max. :337.0 Max. :91.00 Max. :46.00
# 1.3 - transformar rownames em coluna 'state' e tibble para melhor manuseio
df <- df %>%
as_tibble(rownames = "state")
# 1.4 - criar novas variáveis úteis:
# - total_arrests: soma simples das taxas (Murder + Assault + Rape) - útil como medida composta
# - murder_z: padronização (z-score) da taxa de homicídio
# - assault_class: classificação simples por quantis (Low/Medium/High) para Assault
df <- df %>%
mutate(
total_arrests = Murder + Assault + Rape,
murder_z = scale(Murder)[,1], # z-score (média 0, desvio 1)
assault_class = ntile(Assault, 3),
assault_cat = case_when(
assault_class == 1 ~ "Low",
assault_class == 2 ~ "Medium",
assault_class == 3 ~ "High"
)
)
# 1.5 - ordenar por total_arrests (maior -> menor)
df_sorted <- df %>% arrange(desc(total_arrests))
# 1.6 - filtrar exemplo: estados com Murder >= 10 (alto homicídio) e UrbanPop > 60
df_high_murder <- df %>% filter(Murder >= 10, UrbanPop > 60) %>% arrange(desc(Murder))
# 1.7 - resumo por categorias (médias por assault_cat)
summary_by_assault_cat <- df %>%
group_by(assault_cat) %>%
summarise(
n = n(),
murder_mean = mean(Murder),
assault_mean = mean(Assault),
rape_mean = mean(Rape),
urbanpop_mean = mean(UrbanPop),
total_mean = mean(total_arrests)
)
# 1.8 - resultado rápido (mostra os objetos criados)
list(df_head = head(df, 6),
df_sorted_head = head(df_sorted, 6),
df_high_murder = df_high_murder,
summary_by_assault_cat = summary_by_assault_cat)
## $df_head
## # A tibble: 6 × 9
## state Murder Assault UrbanPop Rape total_arrests murder_z assault_class
## <chr> <dbl> <int> <int> <dbl> <dbl> <dbl> <int>
## 1 Alabama 13.2 236 58 21.2 270. 1.24 3
## 2 Alaska 10 263 48 44.5 318. 0.508 3
## 3 Arizona 8.1 294 80 31 333. 0.0716 3
## 4 Arkansas 8.8 190 50 19.5 218. 0.232 2
## 5 California 9 276 91 40.6 326. 0.278 3
## 6 Colorado 7.9 204 78 38.7 251. 0.0257 2
## # ℹ 1 more variable: assault_cat <chr>
##
## $df_sorted_head
## # A tibble: 6 × 9
## state Murder Assault UrbanPop Rape total_arrests murder_z assault_class
## <chr> <dbl> <int> <int> <dbl> <dbl> <dbl> <int>
## 1 Florida 15.4 335 80 31.9 382. 1.75 3
## 2 North Caro… 13 337 45 16.1 366. 1.20 3
## 3 Maryland 11.3 300 67 27.8 339. 0.806 3
## 4 Arizona 8.1 294 80 31 333. 0.0716 3
## 5 New Mexico 11.4 285 70 32.1 328. 0.829 3
## 6 California 9 276 91 40.6 326. 0.278 3
## # ℹ 1 more variable: assault_cat <chr>
##
## $df_high_murder
## # A tibble: 9 × 9
## state Murder Assault UrbanPop Rape total_arrests murder_z assault_class
## <chr> <dbl> <int> <int> <dbl> <dbl> <dbl> <int>
## 1 Florida 15.4 335 80 31.9 382. 1.75 3
## 2 Louisiana 15.4 249 66 22.2 287. 1.75 3
## 3 Texas 12.7 201 80 25.5 239. 1.13 2
## 4 Nevada 12.2 252 81 46 310. 1.01 3
## 5 Michigan 12.1 255 74 35.1 302. 0.990 3
## 6 New Mexico 11.4 285 70 32.1 328. 0.829 3
## 7 Maryland 11.3 300 67 27.8 339. 0.806 3
## 8 New York 11.1 254 86 26.1 291. 0.760 3
## 9 Illinois 10.4 249 83 24 283. 0.600 3
## # ℹ 1 more variable: assault_cat <chr>
##
## $summary_by_assault_cat
## # A tibble: 3 × 7
## assault_cat n murder_mean assault_mean rape_mean urbanpop_mean total_mean
## <chr> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 High 16 11.8 273. 28.4 68.3 313.
## 2 Low 17 4.25 81.8 13.5 58 99.6
## 3 Medium 17 7.54 164. 22.3 70.5 194.
Por que data("USArrests")?
USArrests é um dataset interno do R (R Core Team
2025) que contém, por estado, as taxas (por 100k) de Murder,
Assault, UrbanPop (porcentagem urbana) e Rape. Usamos data() para
garantir que esteja disponível.
Transformar rownames em coluna state:
No dataset original os nomes dos estados são rownames. É melhor ter uma
coluna explícita state para joins com mapas, ordenações e tabelas
interativas: as_tibble(rownames = "state"). Esta abordagem
segue os princípios do “Tidy Data” (Wickham and
Grolemund 2017), que facilitam a manipulação e
visualização.
Criação de variáveis novas:
ntile(., 3). Esta etapa de engenharia de features é
um pilar central na ciência de dados prática (Mount and Zumel 2019).Filtragem e ordenação:
Agrupamento e sumarização:
group_by(assault_cat) %>% summarise(…) produz estatísticas agregadas
por categoria, muito requisitado em relatórios.
Verificações sugeridas:
Sempre usar str(), glimpse(),
summary() e head() para confirmar tipos,
valores NA (não há em USArrests) e se as transformações ocorreram como
esperado.
# preparar tabela - exibir as colunas principais e a categoria
dt_table <- df %>%
select(state, Murder, Assault, UrbanPop, Rape, total_arrests, assault_cat)
DT::datatable(
dt_table,
options = list(
pageLength = 10,
autoWidth = TRUE,
searchHighlight = TRUE,
ordering = TRUE,
dom = 'Bfrtip',
order = list(list(5, 'desc')) # ordenar por total_arrests inicialmente
),
rownames = FALSE,
filter = "top",
caption = htmltools::tags$caption(
style = 'caption-side: top; text-align: left;',
'Tabela 1: ', htmltools::tags$em('Taxas por estado - USArrests (com coluna total_arrests).')
)
)
Breve orientação de uso: utilize o filtro no topo para procurar um estado; clique no cabeçalho das colunas para ordenar. A integração de tabelas interativas como esta em relatórios HTML é uma das grandes vantagens do R Markdown (Xie, Allaire, and Grolemund 2018).
Abaixo cinco equações relevantes para análise de dados e estatística, cujos conceitos são fundamentais em aprendizado de máquina e podem ser aprofundados em referências clássicas como (James et al. 2013):
Regressão linear (OLS) - estimador de mínimos
quadrados \[
\mathbf{y} = \mathbf{X}\beta + \varepsilon, \qquad \hat{\beta} =
(\mathbf{X}^\top \mathbf{X})^{-1}\mathbf{X}^\top \mathbf{y}
\] Significado: y é vetor resposta (ex.:
Murder), X matriz de preditores (ex.: UrbanPop, Assault,
Rape). \(\hat{\beta}\) é a solução
OLS.
PCA - decomposição espectral da matriz de
covariância \[
\mathbf{S} = \mathbf{V}\Lambda \mathbf{V}^\top,\quad \text{onde }
\mathbf{S} = \frac{1}{n-1}\mathbf{X}^\top\mathbf{X}
\] Significado: S é matriz de covariância
das variáveis padronizadas; V autovetores (direções
principais), \(\Lambda\) autovalores
(variâncias explicadas).
Z-score (padronização) \[
z_i = \frac{x_i - \bar{x}}{s_x}
\] Significado: transforma x_i em unidade
de desvios-padrão da média (usado em murder_z).
Objetivo do K-means \[
\underset{C}{\arg\min} \sum_{k=1}^{K} \sum_{x_i \in C_k} \| x_i -
\mu_k\|^2
\] Significado: particionar dados em K
clusters minimizando a soma dos quadrados dentro dos clusters (centróide
\(\mu_k\)).
Correlação de Pearson \[
r_{xy} = \frac{\sum_{i=1}^n (x_i - \bar{x})(y_i -
\bar{y})}{\sqrt{\sum_{i=1}^n (x_i - \bar{x})^2}\sqrt{\sum_{i=1}^n (y_i -
\bar{y})^2}}
\] Significado: mede relação linear entre x
e y (varia de -1 a 1).
Murder vs Assault com
reta de regressão e labelsggplot(df, aes(x = Assault, y = Murder, label = state)) +
geom_point(size = 2) +
geom_smooth(method = "lm", se = TRUE) +
geom_text_repel(size = 3, max.overlaps = 25) +
labs(
title = "Murder vs Assault (USArrests)",
x = "Assault (taxa por 100k)",
y = "Murder (taxa por 100k)",
caption = "Fonte: dataset USArrests (R)"
) +
theme_minimal()
# preparar dados do mapa
states_map <- map_data("state")
# ajuste de nomes: map_data usa nomes em lower-case
df_map <- df %>%
mutate(region = tolower(state))
map_df <- states_map %>%
left_join(df_map, by = c("region" = "region"))
# plot
ggplot(map_df, aes(long, lat, group = group, fill = Murder)) +
geom_polygon(color = "gray90", size = 0.2) +
coord_fixed(1.3) +
scale_fill_continuous(name = "Murder\n(taxa/100k)", low = "white", high = "red", na.value = "grey50") +
labs(title = "Taxa de Homicídio (Murder) por Estado - USArrests") +
theme_void() +
theme(legend.position = "right",
plot.title = element_text(hjust = 0.5))
num_vars <- df %>% select(Murder, Assault, UrbanPop, Rape)
corr_mat <- cor(num_vars)
corrplot::corrplot(corr_mat, method = "number", tl.cex = 0.8)