Análise de churn

Profª Edneide Ramalho

Pacotes

library(tidyverse)
library(readr)
library(gtsummary)
library(ggpubr)

Pergunta de negócio

❓Clientes que cancelam (Churn = Yes) apresentam tempo de contrato (tenure) diferente dos que permanecem?

Dados

dados <- read_csv("dados/WA_Fn-UseC_-Telco-Customer-Churn.csv")
View(dados)
glimpse(dados)
Rows: 7,043
Columns: 21
$ customerID       <chr> "7590-VHVEG", "5575-GNVDE", "3668-QPYBK", "7795-CFOCW…
$ gender           <chr> "Female", "Male", "Male", "Male", "Female", "Female",…
$ SeniorCitizen    <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
$ Partner          <chr> "Yes", "No", "No", "No", "No", "No", "No", "No", "Yes…
$ 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, 2…
$ PhoneService     <chr> "No", "Yes", "Yes", "No", "Yes", "Yes", "Yes", "No", …
$ MultipleLines    <chr> "No phone service", "No", "No", "No phone service", "…
$ InternetService  <chr> "DSL", "DSL", "DSL", "DSL", "Fiber optic", "Fiber opt…
$ OnlineSecurity   <chr> "No", "Yes", "Yes", "Yes", "No", "No", "No", "Yes", "…
$ OnlineBackup     <chr> "Yes", "No", "Yes", "No", "No", "No", "Yes", "No", "N…
$ DeviceProtection <chr> "No", "Yes", "No", "Yes", "No", "Yes", "No", "No", "Y…
$ TechSupport      <chr> "No", "No", "No", "Yes", "No", "No", "No", "No", "Yes…
$ StreamingTV      <chr> "No", "No", "No", "No", "No", "Yes", "Yes", "No", "Ye…
$ StreamingMovies  <chr> "No", "No", "No", "No", "No", "Yes", "No", "No", "Yes…
$ Contract         <chr> "Month-to-month", "One year", "Month-to-month", "One …
$ PaperlessBilling <chr> "Yes", "No", "Yes", "No", "Yes", "Yes", "Yes", "No", …
$ PaymentMethod    <chr> "Electronic check", "Mailed check", "Mailed check", "…
$ MonthlyCharges   <dbl> 29.85, 56.95, 53.85, 42.30, 70.70, 99.65, 89.10, 29.7…
$ TotalCharges     <dbl> 29.85, 1889.50, 108.15, 1840.75, 151.65, 820.50, 1949…
$ Churn            <chr> "No", "No", "Yes", "No", "Yes", "Yes", "No", "No", "Y…
  • Vamos selecionar, por ora, apenas as variáveis de interesse:
dados_analise <- dados |>
  select(tenure, Churn) |> 
  mutate(Churn = factor(Churn, levels=c("Yes", "No")))

Análise Exploratória

  • Estatísticas descritivas:
dados_analise |> 
  group_by(Churn) |> 
  summarise(
    n = n(),
    proporcao = round(100 * n()/nrow(dados_analise), 2),
    media = mean(tenure, na.rm = TRUE),
    mediana = median(tenure, na.rm = TRUE),
    q1 = quantile(tenure, 0.25),
    q3 = quantile(tenure, 0.75)
  )
# A tibble: 2 × 7
  Churn     n proporcao media mediana    q1    q3
  <fct> <int>     <dbl> <dbl>   <dbl> <dbl> <dbl>
1 Yes    1869      26.5  18.0      10     2    29
2 No     5174      73.5  37.6      38    15    61
  • Visualização dos dados:
ggplot(dados_analise, aes(x = tenure)) +
  geom_histogram(bins = 30, fill = "steelblue", alpha = 0.7) +
  facet_wrap(~ Churn) +
  labs(
    title = "Distribuição do tempo de contrato por status de churn",
    x = "Tempo de contrato (meses)",
    y = "Frequência"
  ) +
  theme_minimal()

  • Comparando os dois grupos:
ggplot(dados_analise, aes(x = Churn, y = tenure, fill = Churn)) +
  geom_boxplot(alpha = 0.7) +
  scale_fill_manual(
    values = c(
      "Yes" = "#E69F00",
      "No"  = "#009E73"   
    )
  ) +
  labs(
    title = "Distribuição do tempo de contrato por status de churn",
    x = "Churn",
    y = "Tempo de contrato (meses)"
  ) +
  theme_minimal()

Parce realmente que os clientes que cancelaram o serviço ficaram menos tempo, 18 meses em média, enquanto os que não cancelaram ficaram uma média de aproximadamente 38 meses. Para avaliar se essa diferença é realmente significativa, precisamos realizar um teste de hipótese.

Teste de Hipótese

\(H_0\): Não há diferença no tempo de assinatura para quem cancelou e não cancalou o serviço.

\(H_1\): Há uma diferença no tempo de assinatura quando comparamos clientes que cancelaram e não cancelaram.

Vimos claranamente na distribuição dos dados de meses de assinatura (tenure) que os dados não seguem uma distribuição normal, sendo assim, vamos usar um teste não paramétrico para testar a nossa hipótese. Usaremos o teste de Wilcoxon-Mann-Whitney.

wilcox.test(tenure ~ Churn, data = dados_analise)

    Wilcoxon rank sum test with continuity correction

data:  tenure by Churn
W = 2515538, p-value < 2.2e-16
alternative hypothesis: true location shift is not equal to 0

O p-valor (p < 0.001) mostra que há uma diferença estatisticamente significativa entre o tempo de assinatura e churn, confirmando nossas suspeitas anteriores.

Preparando o report final

  • Ajustando a tabela final de maneira mais organizada:
dados_analise |> 
  tbl_summary(by = Churn) |> 
  add_p() |> 
  modify_header(label ~ "") %>%
  modify_spanning_header(c("stat_1", "stat_2") ~ "**Churn**")
Churn p-value2
Yes, N = 1,8691 No, N = 5,1741
tenure 10 (2, 29) 38 (15, 61) <0.001
1 Median (IQR)
2 Wilcoxon rank sum test
  • Gráfico final:
compare_means(formula = tenure ~ Churn, data = dados_analise,
              method = "wilcox.test", paired = FALSE)
# A tibble: 1 × 8
  .y.    group1 group2         p     p.adj p.format p.signif method  
  <chr>  <chr>  <chr>      <dbl>     <dbl> <chr>    <chr>    <chr>   
1 tenure Yes    No     2.42e-208 2.40e-208 <2e-16   ****     Wilcoxon
ggboxplot(dados_analise, x = "Churn", y = "tenure", 
          color = "Churn",
          palette = c("#E69F00","#009E73")) +
  stat_compare_means()

Conclusão

A análise exploratória evidenciou diferenças consistentes no tempo de contrato entre clientes que cancelam e aqueles que permanecem na base.

Medidas descritivas e visualizações indicaram que clientes com churn tendem a apresentar menor tempo de permanência (mediana de 10 meses vs. 38 meses dos que permanecem), além de maior concentração nos primeiros meses de contrato.

A aplicação do teste de Wilcoxon-Mann-Whitney forneceu evidência estatística contra a hipótese nula de igualdade entre as distribuições de tempo de contrato, sugerindo que a diferença observada dificilmente pode ser atribuída apenas ao acaso (p < 0,0001).

Embora o resultado seja estatisticamente significativo, sua interpretação deve considerar o contexto do negócio. O p-valor não informa sobre a magnitude ou o impacto prático da diferença observada, mas indica a presença de um padrão consistente nos dados. Assim, os achados desta análise fornecem subsídios para estratégias de retenção focadas nos estágios iniciais do relacionamento com o cliente.

Por fim, esta análise ilustra como métodos estatísticos simples, aliados à exploração visual dos dados, podem gerar evidências relevantes e servir como base para abordagens analíticas mais complexas, como modelos multivariados e preditivos de churn.

Traduzindo para o negócio: clientes tendem a cancelar nos primeiros meses de relacionamento. O que pode ser feito para evitar isso?

  • Investir em ações de onboarding

  • Monitorar clientes com baixo tenure

  • Oferecer incentivos nos primeiros meses de uso da plataforma

  • Criar alertas para clientes novos com comportamento de risco.