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.
Para isso, seguiremos o estudo através de 4 etapas:
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")
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:
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.
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.
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.
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 |
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
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.
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.
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.