Sumário

  • 1  Conceito
  • 2  Valor médio de uma Variável Aleatória (Esperança matemática)
  • 3  Função de distribuição acumulada
  • 4  Distribuições discretas de probabilidade
    • 4.1  Distribuição uniforme discreta
    • 4.2  Distribuição de Bernoulli
    • 4.3  Distribuição Binomial
    • 4.4  Distribuição Hipergeométrica
    • 4.5  Distribuição de Poisson
  • 5  Referências
In [1]:
import pandas as pd
import numpy as np
from scipy import stats
import seaborn as sns
import matplotlib.pyplot as plt
from decimal import Decimal

import warnings  
warnings.filterwarnings('ignore')
In [2]:
df_salarios = pd.read_csv('dados/dados_tratados.csv').drop('Unnamed: 0', axis=1)
df_b3 = pd.read_csv('dados/b3_stocks_1994_2020.csv')
df_b3['datetime'] = pd.to_datetime(df_b3['datetime'])

Conceito¶

Vamos a um exemplo para ficar fácil a compreensão. Vamos criar uma tabela de contingência de tamanho da companhia por tipo de trabalho.

In [3]:
dcf = pd.crosstab(df_salarios['tamanho_companhia'], df_salarios['tipo_trabalho'])
dcf_total = dcf.copy()
dcf_total['Total'] = dcf.sum(axis=1, numeric_only=True)
dcf2 = pd.DataFrame({dcf_total.columns[0]: dcf_total['Hibrido'].sum(),
                     dcf_total.columns[1]: dcf_total['Home office'].sum(),
                     dcf_total.columns[2]: dcf_total['Presencial'].sum(),
                     dcf_total.columns[3]: dcf_total['Total'].sum()}, index=['Total'])
dcf_total = dcf_total.append(dcf2)
dcf_total
Out[3]:
Hibrido Home office Presencial Total
Grande 110 220 124 454
Medio 47 1332 1774 3153
Pequeno 32 91 25 148
Total 189 1643 1923 3755

Digamos que um profissional está vendo opções para um novo emprego e esse profissional está fazendo isso por um critério de pontos. Esses pontos seguem uma lógica:

  • Tamanho da empresa:
    • Grande: 3 pontos
    • Média: 2 pontos
    • Pequena: 1 ponto
  • Tipo de trabalho:
    • Home office: 3 pontos
    • Hibrido: 2 pontos
    • Presencial: 1 ponto

Também sabemos o percentual de cada empresa e tipo de trabalho baseado na pesquisa.

  • Tamanho da empresa:
    • Grande: 12%
    • Média: 84%
    • Pequena: 4%
  • Tipo de trabalho:
    • Home office: 44%
    • Hibrido: 5%
    • Presencial: 51%

Logo nós podemos ter as seguintes combinações:

Combinação Probabilidade Pontos
Grande - Home office 0,0528 6
Grande - Híbrido 0,006 5
Grande - Presencial 0,0612 4
Media - Home office 0,3696 5
Media - Híbrido 0,042 4
Media - Presencial 0,4284 3
Pequena - Home office 0,0176 4
Pequena - Híbrido 0,002 3
Pequena - Presencial 0,0204 2

Com isso, podemos presumir que:

  • 6 pontos se ocorrer o evento $A_1 =$ {Grande - Home office}
  • 5 pontos se ocorrer o evento $A_2 =$ {Grande - Híbrido; Media - Home office}
  • 4 pontos se ocorrer o evento $A_3 =$ {Grande - Presencial; Media - Híbrido; Pequena - Home office}
  • 3 pontos se ocorrer o evento $A_4 =$ {Media - Presencial; Pequena - Híbrido}
  • 2 pontos se ocorrer o evento $A_5 =$ {Pequena - Home office}

Cada um desses eventos tem uma probabilidade associada

  • $P(A_1) = 0,0528$
  • $P(A_2) = 0,3756$
  • $P(A_3) = 0,1208$
  • $P(A_4) = 0,4304$
  • $P(A_5) = 0,0204$

com esses valores nós somos capazes de escrever a função $(x, p(x))$, que é um modelo teórico para a distribuição da variável X, que o profissional poderá usar para julgar a viabilidade de ir trabalhar em uma empresa.

x $p(x)$
6 0,0528
5 0,3756
4 0,1208
3 0,4304
2 0,0204

Definição:

Uma variável aleatória discreta ($X$) é uma função que atribui valores numéricos enumeráveis aos resultados de um experimento. Toda variável aleatória discreta tem uma probabilidade atribuída. Essa probabilidade chamamos de função massa de probabilidade por:

$$p(x_i) = P(X = x_i) = p_i$$

Onde:

  • i = 1, 2, 3...

Voltando ao nosso exemplo pra simplificar esses termos. Temos o evento $A_1$ que é a combinação de Empresa Grande - Home office. Esse evento atribuímos um valor numérico $x_1$ que é igual a 6. A partir disso calculamos a probabilidade desse evento ocorrer. Logo:

$$p(x_1) = P(X = x_1) = 0,0528$$

Isso nos mostra que quando nossa variável aleatória discreta for 6, temos essa probabilidade.

Valor médio de uma Variável Aleatória (Esperança matemática)¶

Pegando nosso exemplo anterior, qual será a pontuação média das empresas que o profissional espera conseguir?

Dá tabela de distribuição que criamos, temos que:

x $p(x)$
6 0,0528
5 0,3756
4 0,1208
3 0,4304
2 0,0204

Logo, a pontuação esperada para as empresas é:

$$\text{pontuação média} = (6 \cdot 0,0528) + (5 \cdot 0,3756) + (4 \cdot 0,1208) + (3 \cdot 0,4304) + (2 \cdot 0,0204) = 4,01$$

Isso significa que, dado que as suposições feitas para determinar a distribuição da variável aleatória sejam verdadeiras, o profissional espera que as empresas tenham 4,01 pontos.

Formalizando, temos:

A esperança matemática ou valor médio de X é dado por:

$$E(X) = \sum_{i=1}^{n}x_i \cdot P(X = x_i) = \sum_{i=1}^{n}x_i \cdot p_i$$

Com o valor da esperança matemática, somos capazes de achar o valor da variância da variável aleatória:

$$\text{Var}(X) = \sum_{i=1}^{n}[x_i - E(X)]² \cdot p_i$$

Calculando para nosso caso:

$$\text{Var}(X) = ([6 - 4,01]² \cdot 0,0528) + ([5 - 4,01]² \cdot 0,3756) + ([4 - 4,01]² \cdot 0,1208) + ([3 - 4,01]² \cdot 0,4304) + ([2 - 4,01]² \cdot 0,0204) $$$$\text{Var}(X) = 0,21 + 0,37 + 0,000012 + 0,44 + 0,08 = 1,1$$

Como temos a variância, podemos achar o desvio padrão.

$$\text{DP}(X) = \sqrt{\text{Var}(X)} = \sqrt{\sum_{i=1}^{n}[x_i - E(X)]² \cdot p_i} $$

No nosso caso o desvio padrão é:

$$\text{DP}(X) = \sqrt{1,1} = 1,048$$

Vamos achar esses valores com Python.

In [4]:
x = [2, 3, 4, 5, 6]
p_x = [0.0204, 0.4304, 0.1208, 0.3756, 0.0528]

df_esperanca = pd.DataFrame({'x': x, 'px': p_x})
df_esperanca
Out[4]:
x px
0 2 0.0204
1 3 0.4304
2 4 0.1208
3 5 0.3756
4 6 0.0528
In [5]:
def esperanca_matematica(df, x, px):
    return sum(df[x] * df[px])

esperanca_matematica(df_esperanca, 'x', 'px')
Out[5]:
4.01
In [6]:
def varianca_variavel_aleatoria(df, x, px):
    valor_medio = esperanca_matematica(df, x, px)
    return sum(((df[x] - valor_medio)**2) * df[px])

varianca_variavel_aleatoria(df_esperanca, 'x', 'px')
Out[6]:
1.0987
In [7]:
def desvio_padrao_variavel_aleatoria(df, x, px):
    variancia = varianca_variavel_aleatoria(df_esperanca, x, px)
    return np.sqrt(variancia)

desvio_padrao_variavel_aleatoria(df_esperanca, 'x', 'px')
Out[7]:
1.0481889142707053

Função de distribuição acumulada¶

Voltando no nosso exemplo temos:

x $p(x)$
6 0,0528
5 0,3756
4 0,1208
3 0,4304
2 0,0204

Logo, a função de distribuição acumulada de X será dada por:

$$F(x) = \begin{cases} 0, & \text{se x} < 2 \\ 0,0204, & \text{se 2} \leq x < 3 \\ 0,4508, & \text{se 3} \leq x < 4 \\ 0,5716, & \text{se 4} \leq x < 5 \\ 0,9472, & \text{se 5} \leq x < 6 \\ 1, & \text{se x} \geq 6\\ \end{cases}$$

Formalizando:

$$F(x) = P(X \leq x)$$

Com python temos:

In [8]:
df_acumulado = df_esperanca.copy()
df_acumulado['fda'] = df_acumulado['px'].cumsum()
df_acumulado
Out[8]:
x px fda
0 2 0.0204 0.0204
1 3 0.4304 0.4508
2 4 0.1208 0.5716
3 5 0.3756 0.9472
4 6 0.0528 1.0000
In [9]:
sns.barplot(data=df_acumulado, x="x", y="fda")
Out[9]:
<AxesSubplot:xlabel='x', ylabel='fda'>

Distribuições discretas de probabilidade¶

Distribuição uniforme discreta¶

Uma variável aleatória X é considerada uniforme se todos os valores tiveram os mesmos valores de probabilidade:

$$P(X = x_i) = p(x_i) = p = \frac{1}{k}$$

para todo $i = 1, 2, 3, ..., k$

Exemplo: Seja a variável aleatória X o número de pontos marcados na face de um dado quando o mesmo é lançado. Qual a probabilidade de cada lado aparecer?

Considerando o dado não viciado, temos que a probabilidade é:

$$P(X = x_1) = P(X = x_2) = P(X = x_3) = P(X = x_4) = P(X = x_5) = P(X = x_6) = \frac{1}{6}$$

Sua esperança é dada por:

$$E(X) = \sum_{i=1}^{n}x_i \cdot P(X = x_i) = \sum_{i=1}^{n}x_i \cdot p_i$$

Sabendo que $p_i$ é igual para todos os valores compreendidos, então

$$E(X) =\frac{1}{k} \cdot \sum_{i=1}^{n}x_i = \frac{\sum_{i=1}^{n}x_i}{k} $$

a variância é:

$$\text{Var}(X) = \frac{\sum_{i=1}^{n}[x_i - \frac{\sum_{i=1}^{n}x_i}{k}]²}{k}$$

e a função de distribuição acumulada é dada por:

$$F(X) = \sum_{x_i \leq x}\frac{1}{k} = \frac{n(x)}{k}$$

onde $n(x)$ é o número de $x_1 \leq x$.

In [11]:
def distribuicao_uniforme(k):
    return 1/k

print(f'Cada um dos {6} resultados tem a probabilidade de {distribuicao_uniforme(6)} de ocorrer')
Cada um dos 6 resultados tem a probabilidade de 0.16666666666666666 de ocorrer
In [12]:
# vendo como o aumento de valores muda a probabilidade
lista = []
lista2 = []
for i in range(1, 51):
    lista.append(distribuicao_uniforme(i))
    lista2.append(i)

with sns.axes_style("whitegrid"):
    plt.figure(figsize=(14, 5))
    plt.bar(lista2, lista)
    plt.plot(lista2, lista)
    plt.xlabel('Valores da variável aleatória')
    plt.ylabel('Probabilidade')
    plt.title('Distribuição uniforme')
    plt.show()

Distribuição de Bernoulli¶

Nessa distribuição, a variável aleatória X assume apenas dois valores,chamados de sucesso e fracasso.

Vamos ver novamente nossa tabela de contingência.

In [13]:
dcf
Out[13]:
tipo_trabalho Hibrido Home office Presencial
tamanho_companhia
Grande 110 220 124
Medio 47 1332 1774
Pequeno 32 91 25

Nesse caso, vamos imaginar que escolhemos um funcionário ao acaso entre todos os funcionários listados e vamos verificar se essa funcionário trabalha no regime presencial. Nossa opções seriam:

  • Trabalha no regime presencial (sucesso)
  • Não trabalha no regime presencial (fracasso)

Logo para esse experimento acima, podemos definir uma variável aleatória X, que assume apenas dois valores:

  • 1, se ocorrer sucesso
  • 0, se ocorrer fracasso

Chamaremos de $p$ a probabilidade de sucesso, então temos:

$$p(0) = P(X = 0) = 1 - p$$$$p(1) = P(X = 1) = p$$

Nesse caso, temos 1923 funcionários que trabalham presencialmente, para um total de 3755

então:

$$p(1) = P(X = 1) = \frac{1923}{3755} = 0,51$$$$p(0) = P(X = 1) = 1 - 0,51 = 0,49$$

Temos 51% de probabilidade de ao acaso escolher um trabalhador que trabalhe no regime presencial, e 49% de não conseguir.

a esperança matemática é dada por:

$$E(X) = p$$

a variância:

$$\text{Var}(X) = p-p² = p\cdot(1 - p) $$

e a função de distribuição acumulada:

$$F(x) = \begin{cases} 0, & \text{se x} < 0 \\ 1 - p, & \text{se 0} \leq x < 1 \\ 1, & \text{se x} \geq 1\\ \end{cases}$$

Quando uma variável aleatória tiver a distribuição de Bernoulli, usaremos a seguinte notação:

$$X \sim Ber(p)$$

No Python, podemos escrever como:

In [14]:
def distribuicao_bernoulli(p):
    sucesso = p
    fracasso = 1 - p
    return sucesso, fracasso

distribuicao_bernoulli(0.51)
Out[14]:
(0.51, 0.49)

Essa forma acima é a forma padrão. Porém essa forma não é útil para lidarmos com dataframes do pandas. Vamos ver como seria essa função para um dataframe pandas.

In [15]:
def distribuicao_bernoulli_problema(df, variavel, condicao_sucesso):
    return len(df[df[variavel] == condicao_sucesso]) / len(df)

Feito dessa forma, só precisamos passar nosso dataframe, qual variável que nós queremos e a condição de sucesso que queremos analisar.

In [16]:
distribuicao_bernoulli_problema(df_salarios, 'tipo_trabalho', 'Presencial')
Out[16]:
0.5121171770972037
In [17]:
probabilidade = len(df_salarios[df_salarios['tipo_trabalho'] == 'Presencial'])/len(df_salarios)
stats.bernoulli.pmf(1, probabilidade)
Out[17]:
0.5121171770972037

Vamos analisar outro caso

In [18]:
pleno = distribuicao_bernoulli_problema(df_salarios, 'nivel_experiencia', 'Pleno')

Usando o valor da função criada e passando na função geral, teremos:

In [19]:
distribuicao_bernoulli(pleno)
Out[19]:
(0.21438082556591212, 0.7856191744340879)

Logo, temos que para a variável nível de experiência que a probabilidade de sucesso de retirar um pleno dali é 21%, enquanto o fracasso é de 79%.

In [22]:
# vendo como o aumento da probabilidade de sucesso muda a distribuição
lista_sucesso = []
lista_fracasso = []
lista2 = []
valores = 10
    
for i in list(np.linspace(0, 1, valores)):
    lista_sucesso.append(np.round(distribuicao_bernoulli(i)[0], 2))
    lista_fracasso.append(distribuicao_bernoulli(i)[1])
    lista2.append(i)
    
df_bernoulli = pd.DataFrame({'Sucesso': lista_sucesso, 'Fracasso': lista_fracasso})
    
with sns.axes_style("whitegrid"):
    plt.figure(figsize=(14, 5))
    df_bernoulli.plot(kind='bar')
    plt.xlabel('Probabilidade de sucesso')
    plt.ylabel('Probabilidade de cada evento (Sucesso, Fracasso)')
    plt.title('Distribuição de Bernoulli')
    plt.show()
<Figure size 1400x500 with 0 Axes>

Distribuição Binomial¶

Vamos imaginar que repetimos o experimento que fizemos acima, na distribuição de Bernoulli, n vezes, sendo que essas repetições feitas são independentes uma das outras.

Vamos dizer que em vezes de escolher ao acaso apenas um funcionário que trabalhe no regime presencial, queremos 5 funcionários. Vamos listar as 5 tentativas:

  1. Fracasso
  2. Sucesso
  3. Sucesso
  4. Fracasso
  5. Sucesso

Logo, a probabilidade dessa amostra será:

$$(1 - p)\cdot p \cdot p \cdot (1-p) \cdot p = p³ \cdot (1-p)²$$

Vamos considerar agora situação de uma moeda, qual a probabilidade de em 3 lançamentos, dar duas caras?

Podemos ter os seguintes resultados

  • Sucesso, Sucesso, Fracasso (SSF)
  • Sucesso, Fracasso, Sucesso (SFS)
  • Fracasso, Sucesso, Sucesso (FSS)

Considerando a moeda honesta, temos a probabilidade de $\frac{1}{2}$ para dar cara. Sabendo que a ordem não importa, então temos:

$$P(SSF) = \frac{1}{2} \cdot \frac{1}{2} \cdot \frac{1}{2} = \frac{1}{8}$$$$P(SSF) = P(SFS) = P(FSS)$$$$P(A) = P(SSF) + P(SFS) + P(FSS)$$$$P(A) = \frac{3}{8}$$

Chamando novamente a probabilidade de sucesso de $p$, e probabilidade de fracasso de $1 - p = q$, então

$$P(SSF) = p \cdot p \cdot q = p² \cdot q$$

Substituindo para os outros valores, achamos que:

$$P(A) = 3p²q$$

Generalizando, temos:

$$P(A) = 3p^kq^{n-k}$$

Onde:

  • n é o valor da amostra;
  • k é o número de sucessos.

Nesse caso acima, formamos 3 possíveis sequências, mas e se jogássemos a moeda 30 vezes e buscássemos a probabilidade de dar 20 caras, como faríamos isso. Uma forma saber quantas sequências obteríamos é através da fórmula:

$${n \choose k} = \frac{n!}{k!\cdot(n-k)!}$$

Logo, a fórmula final é:

$$P(X = k) = {n \choose k}p^kq^{n-k}$$

Onde $k = 0, 1, ...., n$

a esperança matemática é:

$$E(X) = n\cdot p$$

variância

$$\text{Var}(X) = n\cdot p\cdot q$$

Definimos o experimento binomial ao experimento que:

  1. que consiste em n ensaios de Bernoulli;
  2. cujos ensaios são independentes; e
  3. para qual a probabilidade de sucesso varia entre 0 e 1.

Quando uma variável aleatória tiver a distribuição de binomial, usaremos a seguinte notação:

$$X \sim b(n, p)$$

Com python temos:

In [23]:
def fatorial(x):
    valor = 1
    for i in range(1, x+1):
        valor *= i
    return valor
In [24]:
# número de sucessos = k
# tamanho da amostra = n
# probabilidade de sucesso = p
def distribuicao_binomial(numero_sucessos, tamanho_amostra, probabilidade_sucesso):
    possiveis_sequencias = (fatorial(tamanho_amostra)/(fatorial(numero_sucessos) 
                                                       * fatorial(tamanho_amostra-numero_sucessos)))
    nao_sucessos = 1 - probabilidade_sucesso
    return (possiveis_sequencias * (probabilidade_sucesso**numero_sucessos)
            * (nao_sucessos **(tamanho_amostra-numero_sucessos)))
In [25]:
distribuicao_binomial(2, 3, 0.5)
Out[25]:
0.375
In [26]:
# validando com scipy
stats.binom.pmf(2, 3, 0.5)
Out[26]:
0.3750000000000001
In [27]:
def distribuicao_binomial_problema(df, variavel, condicao_sucesso, numero_sucessos):
    tamanho_amostra = len(df)
    probabilidade_sucesso = len(df[df[variavel] == condicao_sucesso]) / tamanho_amostra
    possiveis_sequencias = Decimal((fatorial(tamanho_amostra)//(fatorial(numero_sucessos) 
                                                       * fatorial(tamanho_amostra-numero_sucessos))))
    nao_sucessos = 1 - probabilidade_sucesso
    
    return float((possiveis_sequencias * Decimal((probabilidade_sucesso**numero_sucessos)
            * (nao_sucessos **(tamanho_amostra - numero_sucessos)))))
In [28]:
(fatorial(3755) / fatorial(3730)) / fatorial(25)
Out[28]:
1.3798435560850842e+64
In [29]:
distribuicao_binomial_problema(df_salarios, 'tipo_trabalho', 'Presencial', 1923)
Out[29]:
0.0

Nesse caso, temos uma distribuição grande, fazendo com que nossa distribuição dê a probabilidade 0. Vamos pegar 50 valores aleatórios do dataframe para testar.

In [30]:
df_amostra = df_salarios.sample(n=50, random_state=42)
distribuicao_binomial_problema(df_amostra, 'tipo_trabalho', 'Presencial', 25)
Out[30]:
0.058710477669917716

Agora temos que a probabilidade de pegar aleatoriamente 25 funcionários que trabalham no modo presencial é de 5,8%.

In [31]:
lista = []
lista2 = []
for i in range(0, 51):
    lista.append(distribuicao_binomial_problema(df_amostra, 'tipo_trabalho', 'Presencial', i))
    lista2.append(i)
    
with sns.axes_style("whitegrid"):
    plt.figure(figsize=(14, 5))
    plt.bar(lista2, lista)
    plt.plot(lista2, lista)
    plt.xlabel('Número de sucessos')
    plt.ylabel('Probabilidade')
    plt.title('Distribuição Binomial')
    plt.show()

Temos no gráfico acima que o número de sucessos que nos dá a probabilidade mais alta é 21 casos, logo é mais provável retirarmos 21 funcionários que trabalham no modo presencial uma amostra aleatória de 50.

In [32]:
lista = []
lista2 = []
for i in range(0, 3756):
    lista.append(distribuicao_binomial_problema(df_salarios, 'tipo_trabalho', 'Presencial', i))
    lista2.append(i)
    
with sns.axes_style("whitegrid"):
    plt.figure(figsize=(14, 5))
    plt.bar(lista2, lista)
    plt.plot(lista2, lista)
    plt.xlabel('Número de sucessos')
    plt.ylabel('Probabilidade')
    plt.title('Distribuição Binomial')
    plt.show()

Já no caso da amostra com todos os dados, temos que em todos os casos de número de sucesso, a probabilidade é 0.

Distribuição Hipergeométrica¶

Essa distribuição é adequada quando consideramos extrações casuais feitas sem reposição de uma população dividida segundo dois atributos.

Sua fórmula é:

$$P(X=x) = {r \choose k}{N - r \choose n - k}/{N \choose n}$$$$= \frac{\frac{r!}{k!\cdot(r-k)!}\cdot\frac{(N-r)!}{(n-k)!\cdot[(N-r)- (n-k)]!}}{\frac{N!}{n!\cdot(N-n)!}}$$

Onde:

  • N é a população total;
  • r é a população do atributo desejado;
  • n é o número extraído; e
  • k é a quantidade de sucessos.

Vamos exemplificar, considerando que temos uma população de 100 pessoas, onde 30 são homens, vamos escolher 10 ao acaso. Qual a probabilidade de 5 dessas pessoas serem homens?

$$P(X=x) = {30 \choose 5}{100 - 30 \choose 10 - 5}/{100 \choose 10}$$$$= \frac{\frac{30!}{5!\cdot 25!}\cdot\frac{(70)!}{(5)!\cdot65!}}{\frac{100!}{10!\cdot(90)!}}$$$$= \frac{142506\cdot 12103014}{17310309460000} = 0,099$$

Logo, a probabilidade de 5 dessas pessoas tiradas ao acaso serem homens é de 9,9%. E a probabilidade de pelo menos uma dessas 5 pessoas ser mulher é:

$$1 - p = 0,9$$

a esperança matemática é:

$$E(X) = np $$

a variância é:

$$\text{Var}(X) = np(1 - p)\frac{N - n}{N - 1}$$

Quando uma variável aleatória tiver a distribuição de hipergeométrica, usaremos a seguinte notação:

$$X \sim hip(N, r, n)$$

no Python:

In [33]:
def fatorial(x):
    valor = 1
    for i in range(1, x+1):
        valor *= i
    return valor
In [34]:
def distribuicao_hipergeometrica(populacao_atributo_desejado, qtd_sucessos,
                                 populacao_total, numero_extraido_populacao):
    
    passo1 = (fatorial(populacao_atributo_desejado) / 
              (fatorial(qtd_sucessos) * 
               fatorial((populacao_atributo_desejado - qtd_sucessos))))
    
    passo2 = (fatorial((populacao_total-populacao_atributo_desejado)) /
             (fatorial((numero_extraido_populacao - qtd_sucessos)) * 
              fatorial(((populacao_total-populacao_atributo_desejado) - 
                        (numero_extraido_populacao - qtd_sucessos)))))
    
    passo3 = (fatorial(populacao_total) /
             (fatorial(numero_extraido_populacao) * 
                                           fatorial((populacao_total - 
                                                     numero_extraido_populacao))))
    
    return ((passo1 * passo2) / passo3)
In [35]:
distribuicao_hipergeometrica(30, 5, 100, 10)
Out[35]:
0.09963727785596206
In [36]:
# validando com scipy
stats.hypergeom.pmf(5, 100, 30, 10)
Out[36]:
0.09963727785596206
In [37]:
lista = []
lista2 = []
for i in range(1, 21):
    lista.append(distribuicao_hipergeometrica(30, i, 100, 10))
    lista2.append(i)
In [38]:
plt.bar(lista2, lista)
plt.plot(lista2, lista)
plt.show()
In [39]:
def distribuicao_hipergeometrica_problema(df, variavel, condicao_sucesso,
                                          qtd_sucessos, numero_extraido_populacao):
    populacao_total = len(df)

    populacao_atributo_desejado = len(df[df[variavel] == condicao_sucesso])

    passo1 = Decimal(fatorial(populacao_atributo_desejado) // 
              (fatorial(qtd_sucessos) * 
               fatorial((populacao_atributo_desejado - qtd_sucessos))))

    passo2 = Decimal(fatorial((populacao_total-populacao_atributo_desejado)) //
             (fatorial((numero_extraido_populacao - qtd_sucessos)) * 
              fatorial(((populacao_total-populacao_atributo_desejado) - 
                        (numero_extraido_populacao - qtd_sucessos)))))
    
    passo3 = Decimal(fatorial(populacao_total) //
             (fatorial(numero_extraido_populacao) * 
                                           fatorial((populacao_total - 
                                                     numero_extraido_populacao))))

    return float((passo1 * passo2) / passo3)
In [40]:
distribuicao_hipergeometrica_problema(df_salarios, 'tipo_trabalho', 'Presencial', 25, 50)
Out[40]:
0.11136100027569679

Logo, considerando uma amostra total de 3755, retirando 50 valores aleatórios, temos a probabilidade de 11% de retirar 25 pessoas que trabalham no padrão presencial.

In [41]:
lista = []
lista2 = []
for i in range(1, 1924):
    lista.append(distribuicao_hipergeometrica_problema(df_salarios, 'tipo_trabalho',
                                                       'Presencial', i, 3000))
    lista2.append(i)
    
with sns.axes_style("whitegrid"):
    plt.figure(figsize=(14, 5))
    plt.bar(lista2, lista)
    plt.plot(lista2, lista)
    plt.xlabel('Número de sucessos')
    plt.ylabel('Probabilidade')
    plt.title('Distribuição Hipergeométrica')
    plt.show()

Distribuição de Poisson¶

A distribuição de Poisson é normalmente utilizada quando queremos contar eventos de certo tipo que ocorrem em um intervalo de tempo. Os eventos podem ser:

  • acidentes automotivos em um dia;
  • erros de digitação em uma hora;
  • chegada de um cliente em um banco em algumas horas;
  • Números de falhas em um computador em um minuto.

Sua fórmula é:

$$P(N = k) = \frac{e^{-\lambda} \lambda^{k}}{k!}$$

onde:

  • $\lambda = np$
  • $p$: é a probabilidade do evento acontecer;
  • $n$: é o tamanho da população;
  • $k$: número de sucessos

a esperança matemática é:

$$E(X) = \lambda$$

variância

$$\text{Var}(X) = \lambda$$

A distribuição de Poisson é aplicável quando o número de possíveis ocorrências discretas é muito maior do que o número médio de ocorrências em um determinado intervalo de tempo ou espaço. O número de possíveis ocorrências, muitas vezes não se sabe exatamente. Os resultados devem ocorrer de forma aleatória, ou seja, totalmente por acaso e da probabilidade de ocorrência não deve ser afetado pelos resultados ocorridos anteriormente, de modo que as ocorrências são independentes. Em muitos casos, embora possamos contar as ocorrências, como as quantidade de grãos de coloração diferente em um pacote de arroz, não podemos contar as não ocorrências correspondentes, a quantidade de grãos de coloração não diferente.

Quando uma variável aleatória tiver uma distribuição de Poisson, usaremos a seguinte notação:

$$X \sim Pois(\lambda)$$

Vamos ver um exemplo.

Qual a probabilidade de termos ações com valores de abertura acima 1 milhão de reais em toda a base de ações?

In [42]:
def distribuicao_poisson(probabilidade, tamanho_populacao, numeros_sucessos):
    _lambda = probabilidade * tamanho_populacao
    return (np.exp(-_lambda) * _lambda**numeros_sucessos) / fatorial(numeros_sucessos)
In [43]:
len(df_b3)
Out[43]:
1883203
In [44]:
acoes_acima = len(df_b3[df_b3['open'] > 1000000])
In [45]:
probabilidade = acoes_acima / len(df_b3)
In [46]:
distribuicao_poisson(probabilidade, len(df_b3), 1) 
Out[46]:
0.2706705664732254
In [47]:
# validando com scipy
stats.poisson.pmf(1, 2)
Out[47]:
0.2706705664732254

Logo, vemos que temos uma probabilidade de 27% de termos uma ação acima de 1 milhão de reais em todas as ações que temos.

In [48]:
lista = []
lista2 = []
valores = 10

for i in range(0, 100):
    lista.append(distribuicao_poisson(0.000001, len(df_b3), i))
    lista2.append(i)
    
with sns.axes_style("whitegrid"):
    plt.figure(figsize=(14, 5))
    plt.bar(lista2, lista)
    plt.plot(lista2, lista)
    plt.xlabel('Número de sucessos')
    plt.ylabel('Probabilidade')
    plt.title('Distribuição de Poisson')
    plt.show()
In [49]:
lista_lambda1 = []
lista_lambda4 = []
lista_lambda10 = []
lista2 = []
valores = 10

for i in range(0, 100):
    lista_lambda1.append(distribuicao_poisson(5.31e-7, len(df_b3), i))
    lista_lambda4.append(distribuicao_poisson(4 * 5.31e-7, len(df_b3), i))
    lista_lambda10.append(distribuicao_poisson(10 * 5.31e-7, len(df_b3), i))
    lista2.append(i)
    
with sns.axes_style("whitegrid"):
    plt.figure(figsize=(14, 5))
    #plt.bar(lista2, lista)
    plt.plot(lista2, lista_lambda1, label='$\lambda = 1$')
    plt.plot(lista2, lista_lambda4, label='$\lambda = 4$')
    plt.plot(lista2, lista_lambda10, label='$\lambda = 10$')
    plt.ylabel('Probabilidade')
    plt.title('Distribuição de Poisson')
    plt.legend()
    plt.show()

Referências¶

  1. Morettin, P. A., Bussab, W. O. Estatística Básica, 6. ed. – São Paulo : Saraiva, 2010.
  2. Bruce, P., Bruce, A., Gedeck, P. Pratical Statistics for Data Scientists, 2 ed. O'Reilly, 2020.

In [ ]:
 
$\leftarrow$Ir para artigo anterior Voltar ao site Voltar à página de estatística