Capítulo 12.3
Índice
- 1. O que é Ciência de Dados?
- 2. Causalidade e Experimentos
- 3. Progamando em Python
- 4. Tipos de Dados
- 5. Sequências
- 6. Tabelas
- 7. Visualização
- 8. Funções e Tabelas
- 9. Aleatoriedade
- 10. Amostragem e Distribuições Empíricas
- 11. Testando Hipóteses
- 12. Comparando Duas Amostras
- 13. Estimação
- 14. Por que a Média é Importante
- 15. Previsão
from datascience import *
%matplotlib inline
path_data = '../../../assets/data/'
import matplotlib.pyplot as plots
plots.style.use('fivethirtyeight')
import numpy as np
Esvaziar
Em 18 de janeiro de 2015, os Indianapolis Colts e os New England Patriots jogaram o jogo do campeonato da American Football Conference (AFC) para determinar qual dessas equipes jogaria no Super Bowl. Após o jogo, surgiram alegações de que as bolas dos Patriots não haviam sido infladas conforme exigido pelos regulamentos; elas estavam mais macias. Isso poderia ser uma vantagem, já que bolas mais macias podem ser mais fáceis de segurar.
Por várias semanas, o mundo do futebol americano foi consumido por acusações, negações, teorias e suspeitas: a imprensa rotulou o tópico como Deflategate, em referência ao escândalo político Watergate dos anos 1970. A National Football League (NFL) encomendou uma análise independente. Neste exemplo, faremos nossa própria análise dos dados.
A pressão é frequentemente medida em libras por polegada quadrada (psi). As regras da NFL estipulam que as bolas de jogo devem ser infladas para ter pressões na faixa de 12,5 psi a 13,5 psi. Cada equipe joga com 12 bolas. As equipes são responsáveis por manter a pressão em suas próprias bolas, mas os oficiais do jogo inspecionam as bolas. Antes do início do jogo da AFC, todas as bolas dos Patriots estavam com cerca de 12,5 psi. A maioria das bolas dos Colts estava com cerca de 13,0 psi. No entanto, esses dados pré-jogo não foram registrados.
Durante o segundo quarto, os Colts interceptaram uma bola dos Patriots. Nas laterais, eles mediram a pressão da bola e determinaram que estava abaixo do limite de 12,5 psi. Imediatamente, informaram aos oficiais.
No intervalo, todas as bolas do jogo foram coletadas para inspeção. Dois oficiais, Clete Blakeman e Dyrol Prioleau, mediram a pressão em cada uma das bolas.
Aqui estão os dados. Cada linha corresponde a uma bola de futebol. A pressão é medida em psi. A bola dos Patriots que havia sido interceptada pelos Colts não foi inspecionada no intervalo. A maioria das bolas dos Colts também não foi inspecionada – os oficiais simplesmente ficaram sem tempo e tiveram que devolver as bolas para o início do segundo tempo.
football = Table.read_table(path_data + 'deflategate.csv')
football.show()
| Team | Blakeman | Prioleau |
|---|---|---|
| Patriots | 11.5 | 11.8 |
| Patriots | 10.85 | 11.2 |
| Patriots | 11.15 | 11.5 |
| Patriots | 10.7 | 11 |
| Patriots | 11.1 | 11.45 |
| Patriots | 11.6 | 11.95 |
| Patriots | 11.85 | 12.3 |
| Patriots | 11.1 | 11.55 |
| Patriots | 10.95 | 11.35 |
| Patriots | 10.5 | 10.9 |
| Patriots | 10.9 | 11.35 |
| Colts | 12.7 | 12.35 |
| Colts | 12.75 | 12.3 |
| Colts | 12.5 | 12.95 |
| Colts | 12.55 | 12.15 |
Para cada uma das 15 bolas inspecionadas, os dois árbitros obtiveram resultados diferentes. Não é incomum que medições repetidas no mesmo objeto produzam resultados diferentes, especialmente quando as medições são realizadas por pessoas diferentes. Então, atribuiremos a cada bola a média das duas medições feitas naquela bola.
football = football.with_column(
'Combined', (football.column(1)+football.column(2))/2
).drop(1, 2)
football.show()
| Team | Combined |
|---|---|
| Patriots | 11.65 |
| Patriots | 11.025 |
| Patriots | 11.325 |
| Patriots | 10.85 |
| Patriots | 11.275 |
| Patriots | 11.775 |
| Patriots | 12.075 |
| Patriots | 11.325 |
| Patriots | 11.15 |
| Patriots | 10.7 |
| Patriots | 11.125 |
| Colts | 12.525 |
| Colts | 12.525 |
| Colts | 12.725 |
| Colts | 12.35 |
À primeira vista, parece evidente que as bolas de futebol dos Patriots estavam sob pressão mais baixa do que as bolas dos Colts. Como alguma deflação é normal durante o jogo, os analistas independentes decidiram calcular a queda na pressão desde o início do jogo. Lembre-se de que todas as bolas dos Patriots começaram em cerca de 12,5 psi, e as bolas dos Colts em cerca de 13,0 psi. Portanto, a queda na pressão das bolas dos Patriots foi calculada como 12,5 menos a pressão no intervalo, e a queda na pressão das bolas dos Colts foi de 13,0 menos a pressão no intervalo.
Podemos calcular a queda de pressão para cada bola de futebol, definindo primeiro uma matriz de valores iniciais. Para isso, precisaremos de uma matriz composta por 11 valores, cada um dos quais é 12,5, e outro composto por quatro valores, cada um dos quais é todos os 13. Usaremos a função NumPy np.ones, que recebe uma contagem como argumento e retorna uma matriz com tantos elementos, cada um dos quais é 1.
np.ones(11)
| Out[1]: | array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]) |
patriots_start = 12.5 * np.ones(11)
colts_start = 13 * np.ones(4)
start = np.append(patriots_start, colts_start)
start
| Out[2]: | array([12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 12.5, 13. , 13. , 13. , 13. ]) |
A queda de pressão para cada bola de futebol é a diferença entre a pressão inicial e a medição de pressão combinada.
drop = start - football.column('Combined')
football = football.with_column('Pressure Drop', drop)
football.show()
| Team | Combined | Pressure Drop |
|---|---|---|
| Patriots | 11.65 | 0.85 |
| Patriots | 11.025 | 1.475 |
| Patriots | 11.325 | 1.175 |
| Patriots | 10.85 | 1.65 |
| Patriots | 11.275 | 1.225 |
| Patriots | 11.775 | 0.725 |
| Patriots | 12.075 | 0.425 |
| Patriots | 11.325 | 1.175 |
| Patriots | 11.15 | 1.35 |
| Patriots | 10.7 | 1.8 |
| Patriots | 11.125 | 1.375 |
| Colts | 12.525 | 0.475 |
| Colts | 12.525 | 0.475 |
| Colts | 12.725 | 0.275 |
| Colts | 12.35 | 0.65 |
Parece que as quedas dos Patriots foram maiores que as dos Colts. Vejamos a queda média em cada um dos dois grupos. Não precisamos mais das pontuações combinadas.
football = football.drop('Combined')
football.group('Team', np.average)
| Team | Pressure Drop average |
|---|---|
| Colts | 0.46875 |
| Patriots | 1.20227 |
A queda média para os Patriots foi de cerca de 1,2 psi, em comparação com cerca de 0,47 psi para os Colts.
A questão agora é por que as bolas dos Patriots tiveram uma queda maior na pressão, em média, do que as bolas dos Colts. Poderia ser devido ao acaso?
As Hipóteses
Como o acaso entra aqui? Nada estava sendo selecionado aleatoriamente. Mas podemos criar um modelo de acaso hipotetizando que as 11 quedas dos Patriots parecem uma amostra aleatória de 11 de todas as 15 quedas, com as quedas dos Colts sendo as quatro restantes. Esse é um modelo de acaso completamente especificado sob o qual podemos simular dados. Portanto, essa é a hipótese nula.
Para a alternativa, podemos considerar que as quedas dos Patriots são grandes demais, em média, para se assemelhar a uma amostra aleatória extraída de todas as quedas.
Estatística de Teste
Uma estatística natural é a diferença entre as duas quedas médias, que iremos calcular como “queda média para Patriots – queda média para Colts”. Valores altos dessa estatística favorecerão a hipótese alternativa.
observed_means = football.group('Team', np.average).column(1)
observed_difference = observed_means.item(1) - observed_means.item(0)
observed_difference
| Out[3]: | 0.733522727272728 |
Essa diferença positiva reflete o fato de que a queda média na pressão das bolas de futebol dos Patriots foi maior do que a dos Colts.
Assim como fizemos na seção anterior, escreveremos uma função para calcular a diferença entre as quedas médias nos dois grupos. A função difference_of_means leva dois argumentos:
- o nome da tabela de dados
- o rótulo da coluna que contém os dois rótulos de grupo
Ele retorna a diferença entre as quedas médias dos dois grupos. Calcularemos a diferença como as quedas dos Patriots menos as quedas dos Colts, como antes.
def difference_of_means(table, group_label):
reduced = table.select('Pressure Drop', group_label)
means_table = reduced.group(group_label, np.average)
means = means_table.column(1)
return means.item(1) - means.item(0)
difference_of_means(football, 'Team')
| Out[4]: | 0.733522727272728 |
Este é o mesmo valor que encontramos anteriormente como observed_difference.
Prevendo a Estatística sob a Hipótese Nula
Se a hipótese nula fosse verdadeira, então não deveria importar quais bolas de futebol são rotuladas como Patriots e quais são rotuladas como Colts. As distribuições dos dois conjuntos de quedas seriam as mesmas. Podemos simular isso embaralhando aleatoriamente os rótulos dos times.
shuffled_labels = football.sample(with_replacement=False).column(0)
original_and_shuffled = football.with_column('Shuffled Label', shuffled_labels)
original_and_shuffled.show()
| Team | Pressure Drop | Shuffled Label |
|---|---|---|
| Patriots | 0.85 | Patriots |
| Patriots | 1.475 | Patriots |
| Patriots | 1.175 | Patriots |
| Patriots | 1.65 | Colts |
| Patriots | 1.225 | Patriots |
| Patriots | 0.725 | Patriots |
| Patriots | 0.425 | Patriots |
| Patriots | 1.175 | Colts |
| Patriots | 1.35 | Patriots |
| Patriots | 1.8 | Patriots |
| Patriots | 1.375 | Colts |
| Colts | 0.475 | Patriots |
| Colts | 0.475 | Colts |
| Colts | 0.275 | Patriots |
| Colts | 0.65 | Patriots |
Como as médias de todos os grupos se comparam?
difference_of_means(original_and_shuffled, 'Shuffled Label')
| Out[5]: | -0.5619318181818183 |
difference_of_means(original_and_shuffled, 'Team')
| Out[6]: | 0.733522727272728 |
Os valores médios de queda das duas equipes estão mais próximos quando os rótulos das equipes são atribuídos aleatoriamente às bolas do que estavam para os dois grupos realmente usados no jogo.
Teste de Permutação
É hora de um passo que agora é familiar. Vamos simular repetidamente a estatística de teste sob a hipótese nula.
permutações repetidas das bolas e atribuindo conjuntos aleatórios às duas equipes.
Como de costume, começaremos escrevendo uma função one_simulated_difference que retorna um valor simulado da diferença entre as quedas médias de pressão dos grupos rotulados como Patriots e Colts após permutar aleatoriamente os rótulos das equipes das bolas.
def one_simulated_difference():
shuffled_labels = football.sample(with_replacement = False
).column('Team')
shuffled_table = football.select('Pressure Drop').with_column(
'Shuffled Label', shuffled_labels)
return difference_of_means(shuffled_table, 'Shuffled Label')
Agora podemos usar um loop for e esta função para criar um array differences que contém 10.000 valores da estatística de teste simulada sob a hipótese nula.
differences = make_array()
repetitions = 10000
for i in np.arange(repetitions):
new_difference = one_simulated_difference()
differences = np.append(differences, new_difference)
Conclusão do Teste
Para calcular o p-valor empírico, é importante lembrar da hipótese alternativa, que é que as quedas dos Patriots são grandes demais para serem resultado apenas da variação ao acaso.
Quedas maiores para os Patriots favorecem a hipótese alternativa. Portanto, o p-valor é a probabilidade (calculada sob a hipótese nula) de obter uma estatística de teste igual ao nosso valor observado de 0,733522727272728 ou maior.
A figura abaixo visualiza esse cálculo. Ela consiste na distribuição empírica da estatística de teste sob a hipótese nula, com a estatística observada marcada em vermelho no eixo horizontal e a área correspondente ao valor p sombreada em dourado.
Table().with_column(
'Difference Between Group Averages', differences).hist(
left_end = observed_difference
)
plots.ylim(-0.1, 1.4)
plots.scatter(observed_difference, 0, color='red', s=30, zorder=3)
plots.title('Prediction Under the Null Hypothesis')
print('Observed Difference:', observed_difference)
| Out[7]: | Observed Difference: 0.733522727272728 |

A olho nu, o valor p parece bem pequeno. Podemos confirmar isso por meio de um cálculo.
empirical_p = np.count_nonzero(differences >= observed_difference) / 10000
empirical_p
| Out[8]: | 0.0026 |
Como em exemplos anteriores deste teste, a maior parte da distribuição está centrada em torno de 0. Sob a hipótese nula, as deflações dos Patriots são uma amostra aleatória das 15 deflações, e portanto, as dos Colts também são. Portanto, os dois conjuntos de deflações devem ser aproximadamente iguais em média, e, portanto, sua diferença deve ser em torno de 0.
Mas o valor observado da estatística de teste está bastante distante do centro da distribuição. Por qualquer critério razoável para o que é “pequeno”, o p-valor empírico é pequeno. Portanto, acabamos rejeitando a hipótese nula de aleatoriedade e concluímos que as deflações dos Patriots foram grandes demais para refletir apenas variação ao acaso.
A equipe investigativa independente analisou os dados de várias maneiras diferentes, levando em consideração as leis da física. O relatório final disse,
“[A] queda média de pressão das bolas do jogo dos Patriots excedeu a queda média de pressão das bolas dos Colts em 0,45 a 1,02 psi, dependendo de vários pressupostos possíveis sobre os calibradores usados, e assumindo uma pressão inicial de 12,5 psi para as bolas dos Patriots e 13,0 para as bolas dos Colts.”
— Relatório investigativo encomendado pela NFL referente ao jogo do campeonato da AFC em 18 de janeiro de 2015
Nossa análise mostra uma queda média de pressão de cerca de 0,73 psi, o que está próximo do centro do intervalo “0,45 a 1,02 psi” e, portanto, consistente com a análise oficial.
Lembre-se de que nosso teste de hipóteses não estabelece a razão por que a diferença não se deve ao acaso. Estabelecer causalidade geralmente é mais complexo do que realizar um teste de hipóteses.
Mas a pergunta mais importante no mundo do futebol era sobre a causalidade: a questão era se a queda excessiva de pressão nas bolas dos Patriots foi deliberada. Se você estiver curioso sobre a resposta dada pelos investigadores, aqui está o relatório completo.
| ← Capítulo 12.2 – Causalidade | Capítulo 13 – Estimação → |
