library(tidyverse)
library(palmerpenguins)
library(ggthemes)
library(nycflights13)
library(skimr)
library(readr)
library(gt)
library(corrplot)
library(GGally)
library(summarytools)
library(gtsummary)
library(rstatix)
library(patchwork)
library(tidyr)Projeto da Disciplina
Estatística para Ciência de Dados
10/March/2026
Pacotes
Dados
Vamos usar os dados de churn de clientes. A base de dados original pode ser encontrada no Kaggle: https://www.kaggle.com/datasets/blastchar/telco-customer-churn
dados <- read_csv("dados/churn_clean.csv")
glimpse(dados)Rows: 7,043
Columns: 21
$ customer_id <chr> "7590-VHVEG", "5575-GNVDE", "3668-QPYBK", "7795-CFOC…
$ gender <chr> "Female", "Male", "Male", "Male", "Female", "Female"…
$ senior_citizen <chr> "No", "No", "No", "No", "No", "No", "No", "No", "No"…
$ partner <chr> "Yes", "No", "No", "No", "No", "No", "No", "No", "Ye…
$ dependents <chr> "No", "No", "No", "No", "No", "No", "Yes", "No", "No…
$ tenure <dbl> 1, 34, 2, 45, 2, 8, 22, 10, 28, 62, 13, 16, 58, 49, …
$ phone_service <chr> "No", "Yes", "Yes", "No", "Yes", "Yes", "Yes", "No",…
$ multiple_lines <chr> "No", "No", "No", "No", "No", "Yes", "Yes", "No", "Y…
$ internet_service <chr> "DSL", "DSL", "DSL", "DSL", "Fiber optic", "Fiber op…
$ online_security <chr> "No", "Yes", "Yes", "Yes", "No", "No", "No", "Yes", …
$ online_backup <chr> "Yes", "No", "Yes", "No", "No", "No", "Yes", "No", "…
$ device_protection <chr> "No", "Yes", "No", "Yes", "No", "Yes", "No", "No", "…
$ tech_support <chr> "No", "No", "No", "Yes", "No", "No", "No", "No", "Ye…
$ streaming_tv <chr> "No", "No", "No", "No", "No", "Yes", "Yes", "No", "Y…
$ streaming_movies <chr> "No", "No", "No", "No", "No", "Yes", "No", "No", "Ye…
$ contract <chr> "Month-to-month", "One year", "Month-to-month", "One…
$ paperless_billing <chr> "Yes", "No", "Yes", "No", "Yes", "Yes", "Yes", "No",…
$ payment_method <chr> "Electronic check", "Mailed check", "Mailed check", …
$ monthly_charges <dbl> 29.85, 56.95, 53.85, 42.30, 70.70, 99.65, 89.10, 29.…
$ total_charges <dbl> 29.85, 1889.50, 108.15, 1840.75, 151.65, 820.50, 194…
$ churn <chr> "No", "No", "Yes", "No", "Yes", "Yes", "No", "No", "…
Justificativa para a escolha dos dados: esses dados foram escolhidos com o objetivo de identificar e explorar os dados sobre cancelamento de serviços em uma empresa de telecomunicações. Queremos observar dados como tempo de uso do serviço, idade dos usuários e valor pago pelo serviço.
Outros pontos
Função útil
- Exemplo 1:
dados |>
summary() customer_id gender senior_citizen partner
Length:7043 Length:7043 Length:7043 Length:7043
Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character
dependents tenure phone_service multiple_lines
Length:7043 Min. : 0.00 Length:7043 Length:7043
Class :character 1st Qu.: 9.00 Class :character Class :character
Mode :character Median :29.00 Mode :character Mode :character
Mean :32.37
3rd Qu.:55.00
Max. :72.00
internet_service online_security online_backup device_protection
Length:7043 Length:7043 Length:7043 Length:7043
Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character
tech_support streaming_tv streaming_movies contract
Length:7043 Length:7043 Length:7043 Length:7043
Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character
paperless_billing payment_method monthly_charges total_charges
Length:7043 Length:7043 Min. : 18.25 Min. : 18.8
Class :character Class :character 1st Qu.: 35.50 1st Qu.: 402.2
Mode :character Mode :character Median : 70.35 Median :1397.5
Mean : 64.76 Mean :2281.9
3rd Qu.: 89.85 3rd Qu.:3786.6
Max. :118.75 Max. :8684.8
churn
Length:7043
Class :character
Mode :character
- Exemplo 2:
dados |>
select(-customer_id) |>
tbl_summary()| Characteristic | N = 7,0431 |
|---|---|
| gender | |
| Female | 3,488 (50%) |
| Male | 3,555 (50%) |
| senior_citizen | 1,142 (16%) |
| partner | 3,402 (48%) |
| dependents | 2,110 (30%) |
| tenure | 29 (9, 55) |
| phone_service | 6,361 (90%) |
| multiple_lines | 2,971 (42%) |
| internet_service | |
| DSL | 2,421 (34%) |
| Fiber optic | 3,096 (44%) |
| No | 1,526 (22%) |
| online_security | 2,019 (29%) |
| online_backup | 2,429 (34%) |
| device_protection | 2,422 (34%) |
| tech_support | 2,044 (29%) |
| streaming_tv | 2,707 (38%) |
| streaming_movies | 2,732 (39%) |
| contract | |
| Month-to-month | 3,875 (55%) |
| One year | 1,473 (21%) |
| Two year | 1,695 (24%) |
| paperless_billing | 4,171 (59%) |
| payment_method | |
| Bank transfer (automatic) | 1,544 (22%) |
| Credit card (automatic) | 1,522 (22%) |
| Electronic check | 2,365 (34%) |
| Mailed check | 1,612 (23%) |
| monthly_charges | 70 (36, 90) |
| total_charges | 1,397 (402, 3,789) |
| churn | 1,869 (27%) |
| 1 n (%); Median (Q1, Q3) | |
Sumário
Para a variável: total_charges, vamos calcular:
a média e mediana para todos os eventos
o desvio padrão
os quantis: 25% e 75%
além disso, vamos calcular o mínimo e o máximo.
# Sumário
dados$total_charges |>
summary() Min. 1st Qu. Median Mean 3rd Qu. Max.
18.8 402.2 1397.5 2281.9 3786.6 8684.8
# Desvio padrão
sd(dados$total_charges)[1] 2265.27
- Para um relatório:
dados |>
summarise(
min = min(total_charges, na.rm = TRUE),
q1 = quantile(total_charges, probs = 0.25, na.rm = TRUE),
mediana = median(total_charges, na.rm = TRUE),
media = mean(total_charges, na.rm = TRUE),
q3 = quantile(total_charges, probs = 0.75, na.rm = TRUE),
max = max(total_charges, na.rm = TRUE),
desvio_padrao = sd(total_charges, na.rm = TRUE)
) |>
gt()| min | q1 | mediana | media | q3 | max | desvio_padrao |
|---|---|---|---|---|---|---|
| 18.8 | 402.225 | 1397.475 | 2281.917 | 3786.6 | 8684.8 | 2265.27 |
- Usando uma outra função:
dados |>
get_summary_stats(total_charges, type = "common") |>
gt()| variable | n | min | max | median | iqr | mean | sd | se | ci |
|---|---|---|---|---|---|---|---|---|---|
| total_charges | 7043 | 18.8 | 8684.8 | 1397.475 | 3384.375 | 2281.917 | 2265.27 | 26.992 | 52.913 |
Usando o summarytools
descr(dados$total_charges)Descriptive Statistics
dados$total_charges
N: 7043
total_charges
----------------- ---------------
Mean 2281.92
Std.Dev 2265.27
Min 18.80
Q1 401.95
Median 1397.47
Q3 3789.20
Max 8684.80
MAD 1810.66
IQR 3384.38
CV 0.99
Skewness 0.96
SE.Skewness 0.03
Kurtosis -0.23
N.Valid 7043.00
N 7043.00
Pct.Valid 100.00
Checando normalidade
dados |>
ggplot(aes(total_charges)) +
geom_histogram(bins = 30, color = "black", fill = "lightblue",
alpha = 0.6) +
theme_minimal()O número de bins utilizado foi o número padrão, ou seja, 30. Esse valor foi escolhido porque consegue mostrar claramente a distribuição dos dados (sem deixar “classes” vazias).
Testando visualmente a normalidade dos dados.
Pelo histograma, já vemos que a variável não é normal, ou seja, ela é assimétrica à direita. A frequência de valores menores é maior do que de valores mais altos.
Ainda assim, vamos checar com os gráficos de densidade e QQplot.
p1 <- dados |>
ggplot(aes(x = total_charges)) +
geom_histogram(
aes(y = after_stat(density)),
bins = 30,
fill = "lightblue",
color = "white",
alpha = 0.6
) +
geom_density(color = "darkblue", linewidth = 1.5) +
theme_minimal() +
labs(
title = paste0("Distribuição - Total Charges"),
x = "Total Charges",
y = "Densidade"
)
# QQ plot
p2 <- dados |>
ggplot(aes(sample = total_charges)) +
stat_qq(size = 2, alpha = 0.6) +
stat_qq_line(color = "red", linewidth = 1) +
theme_minimal() +
labs(
title = paste0("QQ plot - Total Charges"),
x = "Quantis Teóricos (Normais)",
y = "Quantis Amostrais"
)
p1 + p2Correlação
Calcule a correlação entre todas as variáveis dessa base. Quais são as 3 pares de variáveis mais correlacionadas?
num_vars <- dados |>
select(where(is.numeric))- Calculando a matriz de correlação:
# Matriz de correlação
matriz_cor <- cor(num_vars, use = "complete.obs")
# Ordenando as maiores correlações
# Escolhendo somente as 3 maiores
cormat_long <- as.data.frame(as.table(matriz_cor))
cormat_long |>
filter(Freq != 1) |>
rename(r = Freq) |>
distinct(r, .keep_all = TRUE) |>
arrange(desc(r)) |>
gt()| Var1 | Var2 | r |
|---|---|---|
| total_charges | tenure | 0.8254641 |
| total_charges | monthly_charges | 0.6508643 |
| monthly_charges | tenure | 0.2478999 |
# Matriz de correlação - gráfica
corrplot(
matriz_cor,
method = "color",
type = "upper",
addCoef.col = "gray",
tl.col = "black",
tl.srt = 45
)Neste caso os pares mais correlacionados são:
tenure e total_charges (r = 0.83, alta)
monthly_charges e total_charges (r = 0.65, alta)
Gráfico de dispersão
dados |>
ggplot(aes(x = tenure, y = total_charges)) +
geom_point(alpha = 0.5) +
geom_smooth(method = "lm")A correlação entre as variáveis foi alta (r = 0.83) e isso significa que existe uma forte relação linear entre as variáveis. A linha azul mostra esse ajuste.
Gráfico de linhas
dados |>
ggplot(aes(x = tenure, y = total_charges)) +
geom_line() +
theme_minimal() +
labs(
title = "Gráfico de linha",
subtitle = "Dados de Churn",
x = "Tempo na empresa",
y = "Total pago"
)