Introdução e Objetivos

O Globoplay + Canais é uma plataforma de streaming oferecida pela Globo, uma das maiores emissoras de televisão do Brasil. Esse serviço combina a assinatura do Globoplay, que é o serviço de streaming da Globo, com a inclusão de alguns canais ao vivo, proporcionando aos assinantes uma experiência mais completa e diversificada.

Globoplay:

Canais Ao Vivo:

Já o Sportv é um canal brasileiro dedicado exclusivamente à transmissão de eventos esportivos. Ele oferece uma programação diversificada que inclui cobertura de competições nacionais e internacionais, programas de debate esportivo, notícias, entrevistas e análises. O canal é conhecido por transmitir eventos esportivos ao vivo, como partidas de futebol, campeonatos de basquete, vôlei, UFC, entre outros. Para assistí-lo no Globoplay, o assinante deve ter a assinatura do Globoplay + Canais. Assim como os outros diversos canais conhecidos como Multishow, GNT, Viva, Canal Brasil e entre outros.

Semanalmente há milhares de assinantes consumindo conteúdos ao vivos nas plataformas disponíveis, porém, com um catálogo grande de canais disponíveis, torna-se interessante o estudo focado nisso. Através disso, nesse trabalho iremos avaliar a probabilidade de consumo do canal Sportv num período semanal e avaliar as possíveis influências: sejam por fatores estáticos como informações demográficas, como também através de influências temporais.

Metodologia

Para isso, seguiremos o estudo através de 4 etapas:

Ativando Pacotes e Acessando os Dados

Através de uma base de dados interna da Globo, com 28 mil usuários consumidores do canal Sportv das semanas de agosto de 2023, temos as seguintes informações:

Variaveis Descricoes Tipo
ID_USUARIO Identificador do assinante. STRING
IDADE Idade do assinante. INTEIRO
GENERO Gênero do assinante. STRING
CONSUMIU_SEMANA32 Se o assinante consumiu na 1a semana de agosto. FATOR
CONSUMIU_SEMANA33 Se o assinante consumiu na 2a semana de agosto. FATOR
CONSUMIU_SEMANA34 Se o usuário consumiu na 3a semana de agosto. FATOR

Inicialmente iremos acionar todos os pacotes que serão utilizados ao longo da análise:

library(readr)
library(tidyverse)
library(readr)
library(bigrquery)
library(gridExtra)
library(eulerr)
library(e1071)
library(dgof)

Após ativar os pacotes, iremos rodar nossa base de dados que se encontra no formato .csv. O código abaixo acessa o arquivo csv utilizando o pacote “readr”. Além disso, é feito um tratamento nos dados, transformando variáveis binárias em fatores e utilizando apenas os assinantes maiores de 18 anos cuja informação de gênero é conhecida.

BASE <- read_csv("BASE.csv", 
                 col_types = cols(CONS_SEMANA32 = col_factor(levels = c("0", "1")),
                                  CONS_SEMANA33 = col_factor(levels = c("0","1")),
                                  CONS_SEMANA34 = col_factor(levels = c("0", "1"))))

base_geral = BASE %>% filter(!is.na(IDADE) & IDADE >= 18 & IDADE <= 100 & GENERO != "Desconhecido") 

Resultados

Parte 1: Processos de Bernoulli - Experimento Aleatório

Primeiramente, vamos supor que o consumo do canal durante as semanas seja um experimento aleatório totalmente independente. Ou seja, há uma mesma probabilidade p de consumir o Sportv durante a semana.

Para estimar o parâmetro p, usaremos os dados disponíveis da semana do dia 14 a 20 de agosto. Ou seja, iremos verificar, nessa semana de agosto, qual foi a probabilidade de sucesso do evento de “assistir ao canal sportv”.

(Semana = data.frame(prop.table(table(base_geral$CONS_SEMANA34)))[2,2])
## [1] 0.4465249

Utilizando então um estimador para o parâmetro p, podemos assumir, para esse experimento, que o evento de assistir ao canal Sportv numa semana segue uma bernoulli de parâmetro p = 0.4465.

O processo estocástico \(X = \{ X_{n};n = 1,2,... \}\) é chamado de processo de Bernoulli com probabilidade de sucesso p se:

  • A1,A2,… sao eventos independentes;
  • \(P(A_{n}) = p, P(A¯_{n}) = 1− p, ∀n = 1,2,....\)

Como foi realizada a premissa que o consumo de uma semana é independente do outro, podemos então definir como 45% a probabilidade de um assinante vir a consumir na semana seguinte.

E nas próximas duas semanas?

Tendo a sequência \((X_{1},X_{2})\) e sabendo que \(X_{i}\) segue uma bernoulli com p = \(0.4467\), podemos calcular essa probabilidade.

\(P(X1 = X2 = 1) = 0.4467^{2} = 0,1995\)

Portato, tem-se que a probabilidade de um usuário vir a consumir o Sportv nas próximas 2 semanas será de 0,1995, ou seja, aproximadamente 20%.

Dado isso, montou-se um programa para que seja calculada a probabilidade de sucesso de sequências de tamanho n, para avaliar a probabilidade de vir a consumir o canal em um certo período de tempo.

Consumir_Sportv_Bern = function(p = 0.4467,
                           n = 3,
                           sucessos,
                           fracassos = n-sucessos){
  
  if(n != (sucessos + fracassos)){
    print("O número de fracassos e sucessos devem somar 'n'.")
  }
  prob = (p^(sucessos))*((1-p)^(fracassos))
  paste0("A probabilidade de ocorrência dessa sequência é de ",round(prob*100,2),"%.")
}

E se quiséssemos calcular a seguinte probabilidade:

\(P(X_{1} = 0, X_{2} = 1, X_{3} = 1, X_{4} = 1) = ?\)

Consumir_Sportv_Bern(p = 0.4467,
               n = 4,
               sucessos = 3)
## [1] "A probabilidade de ocorrência dessa sequência é de 4.93%."

Além disso, também podemos estudar o processo estocástico \(N_{i}\). Seja X um processo de Bernoulli com probabilidade de sucesso p. Os números de sucesso \({Nn,n ∈ N}\) são definidos pela soma das sequências \(X1(w) +X2(w) +...+Xn(w) \ se \ n = 1,2,..\).

Com isso, dado que N é o número de sucessos em k tentativas, N tem distribuição binomial com parâmetros n e p. Como sabemos, p = 0.4467, logo podemos calcular algumas probabilidades através de outro programa construído a seguir:

Consumir_Sportv_Bin = function(p = 0.4467,n,sucessos){
  
  if(n < sucessos){
    print("O número de fracassos e sucessos devem somar 'n'.")
  }
  prob = choose(n,sucessos)*(p^(sucessos))*((1-p)^(n-sucessos))
  paste0("A probabilidade do assinante consumir sportv em ",sucessos," das ",n," semanas é de ",round(prob*100,2),"%.")
}

Através do programa, iremos calcular a probabilidade de que um assinante venha consumir em 3 das próximas 9 semanas. Lembrando que agora, a ordem importa.

\(P(N = 3 | n = 9 ) = ?\)

Consumir_Sportv_Bin(n=9,sucessos=3)
## [1] "A probabilidade do assinante consumir sportv em 3 das 9 semanas é de 21.48%."

Dado que temos informações de consumo na semana anterior, podemos avaliar probabilidades condicionais.

Parte 2: Estudando Probabilidades - Probabilidades Gerais e Condicionais

Já sabemos que na semana do dia 14 a 20 de agosto, a probabilidade de vir consumir Sportv foi de 0.4467. Porém, se o assinante já tiver consumido na semana anterior, essa probabilidade tende a ser maior? Para saber, será calculada a probabilidade condicional \(P(X_{2} = 1| X_{1} = 1)\).

Ao avaliar a semana anterior, houve uma probabilidade de 59% de vir assistir ao Sportv. Para melhor visualização, será construído um diagrama de Veen para melhor cálculo de probabilidade.

#### Diagrama de Venn semana 33 e 34
s2 <- c(Semana1 =16759 , Semana2 =12496 , `Semana1&Semana2` = 10045)
plot(euler(s2), quantities = TRUE, fill = c("blue","red"))

Dado que temos no total 27.985 assinantes, temos que a probabilidade \(P(X_{2} = 1| X_{1} = 1)\) pode ser calculada da seguinte forma:

\[\begin{equation} $P(Semana2 = 1 | Semana1 = 1) = P(Semana 1 \cap Semana2)/P(Semana1)$ \end{equation}\]

#### Diagrama de Venn semana 33 e 34
Semana1 = 16759/27985
Semana1e2 = 10045/27985
Semana1e2/Semana1
## [1] 0.5993794

Logo, tem-se a probabilidade de 60% de que o usuário realize seu consumo na semana do dia 14, dado que consumiu na semana anterior. Ou seja, há uma certa relação de consumo temporal e podemos utilizar isso mais a frente para realizar previsões.

Parte 3: Teste de Hipóteses e Análise Exploratória - Análise de Perfil dos Consumidores Sportv

Idade

Como já mencionado anteriormente, temos as informações de gênero e idade dos nossos assinantes que consomem Sportv. É importante entender quem são os consumidores do canal Sportv e avaliar se eles se diferem dos demais. Inicialmente iremos avaliar a distribuição das idades entre os consumidores. Os gráficos abaixo apresentam respectivamente as distribuições das idades dos consumidores e dos não consumidores do Sportv.

A1 = ggplot(base_geral %>% filter(CONS_SEMANA34=="1"), aes(x = IDADE)) +
  geom_histogram(color = "blue") + ggtitle("Consumidores Sportv")
A2 = ggplot(base_geral %>% filter(CONS_SEMANA34=="1"), aes(x = IDADE)) +
  geom_density(fill = "blue", alpha = 0.5) + ggtitle("Consumidores Sportv")

B1 = ggplot(base_geral %>% filter(CONS_SEMANA34=="0"), aes(x = IDADE)) +
  geom_histogram(color = "red") + ggtitle("Não Consumidores Sportv")

B2 = ggplot(base_geral %>% filter(CONS_SEMANA34=="0"), aes(x = IDADE)) +
  geom_density(fill = "red", alpha = 0.5) + ggtitle("Não Consumidores Sportv")

grid.arrange(A1,A2,B1,B2) 

Podemos também calcular algumas estatísticas como Média, Mediana, Variância, Desvio Padrão e Curtose.

  • Consumidores Sportv
data.frame(Media = mean(base_geral$IDADE[base_geral$CONS_SEMANA34=="1"], na.rm = TRUE),
           Mediana = median(base_geral$IDADE[base_geral$CONS_SEMANA34=="1"], na.rm = TRUE),
           Variancia = var(base_geral$IDADE[base_geral$CONS_SEMANA34=="1"], na.rm = TRUE),
           Desvio_Padrao = sd(base_geral$IDADE[base_geral$CONS_SEMANA34=="1"], na.rm = TRUE),
           Curtose = kurtosis(base_geral$IDADE[base_geral$CONS_SEMANA34=="1"], na.rm = TRUE)) %>%  knitr::kable()
Media Mediana Variancia Desvio_Padrao Curtose
45.13188 44 176.0537 13.26852 -0.4576504
  • Não Consumidores Sportv
data.frame(Media = mean(base_geral$IDADE[base_geral$CONS_SEMANA34=="0"], na.rm = TRUE),
           Mediana = median(base_geral$IDADE[base_geral$CONS_SEMANA34=="0"], na.rm = TRUE),
           Variancia = var(base_geral$IDADE[base_geral$CONS_SEMANA34=="0"], na.rm = TRUE),
           Desvio_Padrao = sd(base_geral$IDADE[base_geral$CONS_SEMANA34=="0"], na.rm = TRUE),
           Curtose = kurtosis(base_geral$IDADE[base_geral$CONS_SEMANA34=="0"], na.rm = TRUE)) %>%  knitr::kable()
Media Mediana Variancia Desvio_Padrao Curtose
39.15256 36 172.358 13.12852 0.0851004

Ao avaliar as métricas, notou-se uma pequena diferença na distribuição das idades entre os dois grupos. Para avaliar se a idade média dos consumidores sportv é superior à idade média dos não consumidores, iremos aplicar um teste de hipótese. Para a aplicação de teste de hipótese ideal, foi construído o seguinte programa.

teste_media = function(x,
                       y,
                       tipo = "two.sided", #PODE SER "two.sided", "less" ou "greater".
                        alfa = 0.05){
  
  #verificar se os dados seguem uma distribuição normal
  p_valuex = ks.test(x,"pnorm",mean(x),sd(x))$p.value
  p_valuey = ks.test(y,"pnorm",mean(y),sd(y))$p.value
  if(p_valuex < alfa | p_valuey < alfa){
    # São dados não paramétricos, utilizar teste de wilcoxon
    
    final  = wilcox.test(x,y, alternative = tipo)$p.value
    
    
  }else{
    
    #Verificar Variâncias Iguais ou Diferentes
    var_pvalue = var.test(x,y)$p.value
    if(var_pvalue > alfa){
    final = t.test(x,y, alternative=tipo,var.equal = TRUE)$p.value
    }else{
    final = t.test(x,y, alternative=tipo,var.equal = FALSE)$p.value
    }
    
  }
  if(final <= alfa & tipo == "two.sided"){
    print("As médias são diferentes.")}
  if(final <= alfa & tipo == "less"){
    print("A média do primeiro grupo é menor que a média do segundo grupo.")  }
  if(final <= alfa & tipo == "greater"){
    print("A média do primeiro grupo é maior que a média do segundo grupo.")  }
  if(final > alfa){
    print("As médias de ambos os grupos são iguais.") 
  }
  }

Através desse programa, o processe é realizado em etapas. Inicialmente é realizado um teste de aderência para avaliar se a distribuição dos dados segue uma distribuição normal. Caso não siga, será aplicado o teste de wilcoxon, teste o qual avalia a diferença das médias sem o pressuposto de normalidade. Caso sigam uma distribuição normal, é realizado o teste para verificar se as variâncias são iguais ou diferentes para assim ser realizado o teste T adequado.

  teste_media(base_geral$IDADE[base_geral$CONS_SEMANA34=="1"],base_geral$IDADE[base_geral$CONS_SEMANA34=="0"], tipo = "greater", alfa = 0.05)
## [1] "A média do primeiro grupo é maior que a média do segundo grupo."

Conforme retornado pelo programa, temos que os consumidores Sportv são, em média, mais velhos. Esse é um fator que poderá ser utilizado para fazer futuras previsões

Gênero

Já em relação ao Gênero podemos avaliar a proporção dos Generos entre os consumidores. No gráfico abaixo nota-se que há uma presença do público masculino muito alta entre os consumidores Sportv e uma presença bem alta do público feminino entre os não consumidores. Com isso fica claro um perfil já definido para esses consumidores.

ggplot(base_geral,aes(CONS_SEMANA34)) + geom_bar(aes(fill = GENERO)) + xlab("Consumidor Sportv") + ylab("Assinantes")

Porém para garantir de fato essa relação, iremos avaliar aplicando um teste de proporção.

prop.test(x=c(8997,1999),n=c(12496,15489),alternative="greater")
## 
##  2-sample test for equality of proportions with continuity correction
## 
## data:  c(8997, 1999) out of c(12496, 15489)
## X-squared = 10122, df = 1, p-value < 2.2e-16
## alternative hypothesis: greater
## 95 percent confidence interval:
##  0.5829037 1.0000000
## sample estimates:
##    prop 1    prop 2 
## 0.7199904 0.1290593

Com p-valor < 0.05, podemos afirmar que a proporção de homens dentre os consumidores sportv é superior à proporção de homens entre os não consumidores do canal.

Parte 4: Modelagem / Inferência Estatística - Qual a probabilidade de um assinante vir a consumir Sportv na semana seguinte?

Conforme já avalido anteriormente, temos possíveis relações temporais, ou seja, quem consumiu na semana anterior tem maior probabilidade de consumir na semana seguinte. E os consumidores sportv são mais velhos e predominantemente do sexo masculino.

Com essas informações iremos construir um modelo logístico para realizar previsões para diversos assinantes.

A Regressão Logística é um método estatístico utilizado para modelar a probabilidade de uma variável categórica binária, ou seja, uma variável que possui apenas duas categorias, como sim/não, 0/1, verdadeiro/falso, ou seja, \(Y_{i} \sim Bern\left ( \pi_{i} \right )\) através de um conjunto de variáveis explicativas numéricas e categóricas. O modelo de regressão logístico explica a relação entre as \(p\) variáveis explicativas e a chance (em escala logarítmica) em favor da ocorrência de um certo evento de interesse, e é dado pela equação:

\[\begin{equation} ln( \frac{\pi_{i}}{1-\pi_{i}}) = x^{T}_{i}\beta; \ i=1,2,\ldots,n. \end{equation}\]

Aplicando a função inversa, o modelo pode-se ser reescrito da forma:

\[\begin{equation} \hat{\pi_{i}} = \frac{1}{1 + e^{-\mbox{$x^{T}_{i}$}\mbox{$\hat{\beta}$}}}; \ i = 1,2,...,n \end{equation}\]

Para isso, usaremos a função glm() e montaremos um programa que retornará a probabilidade de consumir na semana seguinte dadas as informações.

modelo = glm(CONS_SEMANA34 ~ IDADE+GENERO+CONS_SEMANA33, data=base_geral, family=binomial(link = "logit"))
summary(modelo)
## 
## Call:
## glm(formula = CONS_SEMANA34 ~ IDADE + GENERO + CONS_SEMANA33, 
##     family = binomial(link = "logit"), data = base_geral)
## 
## Coefficients:
##                  Estimate Std. Error z value Pr(>|z|)    
## (Intercept)     -3.771815   0.064140  -58.81   <2e-16 ***
## IDADE            0.032756   0.001222   26.81   <2e-16 ***
## GENEROMasculino  2.807242   0.034110   82.30   <2e-16 ***
## GENEROOutros     1.512567   0.071832   21.06   <2e-16 ***
## CONS_SEMANA331   1.573606   0.034589   45.49   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 38475  on 27984  degrees of freedom
## Residual deviance: 24385  on 27980  degrees of freedom
## AIC: 24395
## 
## Number of Fisher Scoring iterations: 5

Através dos resultados obtidos, temos que todos os coeficientes foram significativos para o modelo. Através disso, podemos ver a influência de cada uma das variáveis na probabilidade de vir a consumir o Sportv, aplicando a função exponencial nos coeficientes.

  • Idade: a cada 1 ano de idade a mais, o assinante aumenta 3% as chances de vir a consumir o canal Sportv.
  • Gênero Masculino: o fato do assinante ser do sexo masculino, aumenta-se em 16 vezes as chances dele vir a consumir o canal Sportv se comparado a se ele fosse do sexo Feminino.
  • Consumo_Semana_Anterior: o fato do assinante ter consumido o canal na semana anterior, aumenta-se em quase 5 vezes as chances dele vir a consumir o canal Sportv na semana seguinte.

Após a criação do modelo, foi construído o seguinte programa para retornar a probabilidade de um assinante vir a consumir na semana seguinte de acordo com as informações prévias determinadas pelos argumentos de entrada.

probabilidade_consumo_semana_seguinte = function( Idade, # Idade completa (inteiro)
                                                  Genero, # Masculino, Feminino ou Outros,
                                                  Consumiu_Semana_Anterior # Sim ou Não
                                                  )
                                                  {
  
  base = data.frame(IDADE = Idade, GENERO = Genero, CONS_SEMANA33 = ifelse(Consumiu_Semana_Anterior=="Sim","1","0"))
  predicao = predict(modelo,base, type="response")
  
  return(as.numeric(predicao))
}

Como exemplo, iremos calcular a probabilidade de eu, um assinante do Globoplay + Canais, com 24 anos, do sexo masculino e que consumiu na semana anterior, vir a consumir na semana que vem.

probabilidade_consumo_semana_seguinte( Idade = 24,Genero = "Masculino",Consumiu_Semana_Anterior = "Sim" )
## [1] 0.8014163

Com isso, chegamos a uma probabilidade de 80%. Esse programa também aceita vetores com informações de diferentes assinantes. No exemplo a seguir serão calculadas as probabilidades de consumo do canal para os meus pais.

probabilidade_consumo_semana_seguinte( Idade = c(52,50) ,Genero = c("Masculino","Feminino"),Consumiu_Semana_Anterior = c("Sim","Não"))
## [1] 0.9098930 0.1058329

Portanto, temos que meu pai, dentre nós 3, seria o assinante mais provável a consumir o canal ao vivo do sportv na semana que vem.

Referências