Capítulo 9.2

Índice

  1. 1. O que é Ciência de Dados?
  2. 2. Causalidade e Experimentos
  3. 3. Progamando em Python
  4. 4. Tipos de Dados
  5. 5. Sequências
  6. 6. Tabelas
  7. 7. Visualização
  8. 8. Funções e Tabelas
  9. 9. Aleatoriedade
  10. 10. Amostragem e Distribuições Empíricas
  11. 11. Testando Hipóteses
  12. 12. Comparando Duas Amostras
  13. 13. Estimação
  14. 14. Por que a Média é Importante
  15. 15. Previsão

from datascience import *
path_data = '../../../assets/data/'
import matplotlib
matplotlib.use('Agg')
%matplotlib inline
import matplotlib.pyplot as plots
plots.style.use('fivethirtyeight')
import numpy as np

 

Iteração

É frequentemente o caso na programação – especialmente ao lidar com aleatoriedade – que queremos repetir um processo várias vezes. Por exemplo, lembre-se do jogo de apostar em um lançamento de um dado com as seguintes regras:

  • Se o dado mostrar 1 ou 2 pontos, meu ganho líquido é -1 dólar.
  • Se o dado mostrar 3 ou 4 pontos, meu ganho líquido é 0 dólares.
  • Se o dado mostrar 5 ou 6 pontos, meu ganho líquido é 1 dólar.

A função apostar_em_um_lançamento não recebe argumentos. Cada vez que é chamada, simula um lançamento de um dado justo e retorna o ganho líquido em dólares.

def bet_on_one_roll():
    """Retorna meu ganho líquido em uma aposta"""
    x = np.random.choice(np.arange(1, 7))  # jogue um dado uma vez e registre o número de pontos
    if x <= 2:
        return -1
    elif x <= 4:
        return 0
    elif x <= 6:
        return 1

 

Playing this game once is easy:

bet_on_one_roll()
Out[1]: 0

 

Para ter uma ideia de quão variáveis são os resultados, precisamos jogar o jogo várias vezes. Poderíamos executar a célula repetidamente, mas isso é tedioso, e se quisermos fazer isso mil vezes ou um milhão de vezes, esqueça.

Uma solução mais automatizada é usar uma declaração for para percorrer o conteúdo de uma sequência. Isso é chamado de iteração. Uma declaração for começa com a palavra for, seguida por um nome que queremos dar a cada item na sequência, seguida pela palavra in, e terminando com a própria sequência a ser percorrida. O corpo indentado da declaração for é executado uma vez para cada item nessa sequência.

for animal in make_array('cat', 'dog', 'rabbit'):
    print(animal)
cat
dog
rabbit

 

É útil escrever código que replique exatamente uma declaração for, sem usar a própria declaração for.

Uma declaração for simplesmente replica o código dentro dela, mas antes de cada iteração, ela atribui um novo valor da sequência fornecida ao nome que escolhemos. Por exemplo, aqui está uma versão desenrolada do loop acima.

animal = make_array('cat', 'dog', 'rabbit').item(0)
print(animal)
animal = make_array('cat', 'dog', 'rabbit').item(1)
print(animal)
animal = make_array('cat', 'dog', 'rabbit').item(2)
print(animal)
cat
dog
rabbit

 

Observe que o nome animal é arbitrário, assim como qualquer nome que atribuímos com =.

Aqui usamos uma declaração for de maneira mais realista: imprimimos os resultados de apostar cinco vezes no dado conforme descrito anteriormente. Isso é chamado de simulação dos resultados de cinco apostas. Usamos a palavra simulação para nos lembrar de que não estamos rolando dados e trocando dinheiro fisicamente, mas usando o Python para imitar o processo.

Para repetir um processo n vezes, é comum usar a sequência np.arange(n) na declaração for. Também é comum usar um nome muito curto para cada item. Em nosso código, usaremos o nome i para nos lembrar de que se refere a um item.

for i in np.arange(5):
    print(bet_on_one_roll())
1
-1
-1
1
1

 

Neste caso, simplesmente executamos exatamente a mesma ação (aleatória) várias vezes, de modo que o código no corpo da nossa instrução for na verdade não se refere a i.

Aumentando Arrays

Embora a declaração for acima simule os resultados de cinco apostas, os resultados são simplesmente impressos e não estão em uma forma que podemos usar para cálculos. Qualquer array de resultados seria mais útil. Assim, um uso típico de uma declaração for é criar um array de resultados, aumentando o array a cada vez.

O método append em NumPy nos ajuda a fazer isso. A chamada np.append(array_name, value) retorna um novo array que é array_name acrecido por value. Ao usar append, tenha em mente que todas as entradas de um array devem ser do o mesmo tipo.

pets = make_array('Cat', 'Dog')
np.append(pets, 'Another Pet')
Out[5]: array([‘Cat’, ‘Dog’, ‘Another Pet’], dtype=’
<U11
‘)

 

Isso mantém o array pets inalterado:

pets
Out[6]: array([‘Cat’, ‘Dog’], dtype=’
<U3
‘)

 

Mas muitas vezes, ao usar loops for, será conveniente modificar um array – isto é, alterá-lo – ao aumentá-lo. Isso é feito atribuindo ao array aumentado o mesmo nome do original.

pets = np.append(pets, 'Another Pet')
pets
Out[7]: array([‘Cat’, ‘Dog’, ‘Another Pet’], dtype=’
<U11
‘)

 

Exemplo: Apostando em 5 Rolagens

Agora podemos simular cinco apostas no dado e coletar os resultados em uma matriz que chamaremos de matriz de coleção. Começaremos criando uma matriz vazia para isso e, em seguida, anexaremos o resultado de cada aposta. Observe que o corpo do laço for contém duas declarações. Ambas as declarações são executadas para cada item na sequência fornecida.

outcomes = make_array()

for i in np.arange(5):
    outcome_of_bet = bet_on_one_roll()
    outcomes = np.append(outcomes, outcome_of_bet)
    
outcomes
Out[8]: array([-1., -1., 1., 1., -1.])

 

Vamos reescrever a célula com a instrução for desenrolada:

outcomes = make_array()

i = np.arange(5).item(0)
outcome_of_bet = bet_on_one_roll()
outcomes = np.append(outcomes, outcome_of_bet)

i = np.arange(5).item(1)
outcome_of_bet = bet_on_one_roll()
outcomes = np.append(outcomes, outcome_of_bet)

i = np.arange(5).item(2)
outcome_of_bet = bet_on_one_roll()
outcomes = np.append(outcomes, outcome_of_bet)

i = np.arange(5).item(3)
outcome_of_bet = bet_on_one_roll()
outcomes = np.append(outcomes, outcome_of_bet)

i = np.arange(5).item(4)
outcome_of_bet = bet_on_one_roll()
outcomes = np.append(outcomes, outcome_of_bet)

outcomes
Out[9]: array([ 1., 0., 0., -1., 1.])

 

O conteúdo do array provavelmente será diferente do array que obtivemos ao executar a célula anterior, mas isso se deve à aleatoriedade no lançamento do dado. O processo de criação do array é exatamente o mesmo.

Ao capturar os resultados em um array, demos a nós mesmos a capacidade de usar métodos de array para fazer cálculos. Por exemplo, podemos usar np.count_nonzero para contar o número de vezes que o dinheiro mudou de mãos.

np.count_nonzero(outcomes)
Out[10]: 3

 

Exemplo: Apostando em 300 Rolagens

A iteração é uma técnica poderosa. Por exemplo, podemos ver a variação nos resultados de 300 apostas executando exatamente o mesmo código para 300 apostas em vez de cinco.

outcomes = make_array()

for i in np.arange(300):
    outcome_of_bet = bet_on_one_roll()
    outcomes = np.append(outcomes, outcome_of_bet)

A matriz outcomes contém os resultados de todas as 300 apostas.

len(outcomes)
Out[11]: 300

 

Para ver com que frequência os três diferentes resultados possíveis apareceram, podemos usar os métodos de array outcomes e Table.

outcome_table = Table().with_column('Outcome', outcomes)
outcome_table.group('Outcome').barh(0)

Não surpreendentemente, cada um dos três resultados -1, 0 e 1 apareceu cerca de 100 vezes em 300, com alguma variação. Vamos examinar os valores de “com alguma variação” mais de perto nos capítulos seguintes.

← Capítulo 9.1 – Declarações Condicionais Capítulo 9.3 – Simulação →