Arrays e cálculo com NumPy

Arrays 1D e 2D, shape, dtype, eixos, broadcasting, cópias e vistas.

Perguntar sobre esta página

ChatGPTClaudePerplexityGeminiCopiar e abrir

Brain rot

A seguirPara ti

@resumos.feup

som original ·

Definições

Leitura

Mudar de trecho
Legendas
Mostrar no vídeo
Vídeos de fundo

O texto, o áudio e os teus vídeos ficam neste dispositivo.

Créditos dos vídeos e da voz

Partilhar página

Uma lista pode guardar objetos diferentes. Um array NumPy guarda elementos de um tipo comum e suporta operações sobre todos eles. Para calcular o total de cada venda, podemos multiplicar um array de quantidades por outro de preços.

Criar e inspecionar

import numpy as np

quantidades = np.array([2, 3, 4])
precos = np.array([1.5, 1.2, 2.0])

quantidades.ndim é 1, quantidades.shape é (3,) e quantidades.size é 3. dtype indica o tipo guardado. Ao criar np.array([1, 2.5]), os elementos passam a reais, para partilhar o mesmo tipo.

Um array de inteiros não passa automaticamente a reais quando lhe atribuis 2.5. Escolhe dtype=float quando o cálculo exige frações. A mistura com strings pode converter todos os elementos para texto e impedir a aritmética esperada.

np.zeros((2, 3)) cria duas linhas e três colunas preenchidas com zero. np.ones preenche com um. np.arange(1, 6, 2) produz 1, 3 e 5. np.linspace(0, 1, 5) produz cinco pontos igualmente espaçados, incluindo normalmente ambos os extremos. np.empty reserva espaço sem inicializar valores úteis; preenche-o antes de ler.

Tipo e memória

O número no nome int8, uint8, float32 ou float64 indica bits por elemento. int8 guarda inteiros de −128 a 127; uint8, sem sinal, guarda 0 a 255. float32 ocupa quatro bytes e float64 oito. complex64 ocupa oito bytes no total, com duas componentes reais de quatro bytes.

a.itemsize dá bytes por elemento e a.nbytes o total de bytes dos dados. Um array (2, 3) de float64 tem seis elementos e ocupa 48 bytes de dados. Isto não inclui todo o custo do objeto Python. .data expõe o buffer; usa índices para aceder aos valores.

a.astype(float) devolve normalmente outro array convertido. Escolhe um tipo que represente os valores e a precisão necessários: inteiros de tamanho fixo podem transbordar e converter reais para inteiros elimina a parte fracionária. np.iinfo(np.int8) mostra limites de um tipo inteiro. O tipo de np.array é inferido dos dados quando omites dtype; não é sempre float64.

Identidade e leitura de dados numéricos

np.eye(3) cria uma matriz identidade 3 × 3, com uns na diagonal e zeros fora dela. Para dados tabulares numéricos, genfromtxt lê um ficheiro ou objeto semelhante a ficheiro, permitindo indicar separador e linhas de cabeçalho.

from io import StringIO
import numpy as np

texto = StringIO("a;b\n2;3\n4;5\n")
a = np.genfromtxt(texto, delimiter=";", skip_header=1)
print(a.shape)       # (2, 2)
print(a.sum(axis=0)) # [6. 8.]

Aqui as colunas são numéricas. Para colunas de tipos diferentes, datas ou categorias, um DataFrame pandas costuma conservar melhor o significado da tabela. Confere a forma e os valores em falta após ler dados externos.

Operar elemento a elemento

Calcular três vendas
import numpy as np
quantidades = np.array([2, 3, 4])
precos = np.array([1.5, 1.2, 2.0])
totais = quantidades * precos
print(totais.round(2))
print(round(totais.sum(), 2))
print(quantidades[quantidades >= 3])
Dados de entrada

Os totais são 3,00, 3,60 e 8,00 euros; a soma é 14,60 euros. A comparação cria uma máscara booleana com False, True, True. Aplicar a máscara seleciona as quantidades 3 e 4.

Com listas, [2, 3] * 2 repete a sequência. Com NumPy, np.array([2, 3]) * 2 multiplica os valores e dá 4 e 6. * não calcula um produto matricial; @ calcula esse produto quando as dimensões são compatíveis.

Duas dimensões e eixos

Vamos guardar duas lojas em linhas e três produtos em colunas:

Ler os eixos
import numpy as np
vendas = np.array([[2, 3, 4], [5, 1, 2]])
print(vendas.shape)
print(vendas[1, 0])
print(vendas[:, 1])
print(vendas.sum(axis=0))
print(vendas.sum(axis=1))
Dados de entrada

A forma é (2, 3). A célula de linha 1, coluna 0 contém 5. A coluna 1 contém 3 e 1. A soma com axis=0 elimina o eixo das linhas e dá os totais por coluna: 7, 4 e 6. Com axis=1, elimina o eixo das colunas e dá os totais por linha: 9 e 8.

O nome do eixo é o que percorres e reduzes. Para evitar trocar os dois, confere o tamanho do resultado: três produtos exigem três totais, duas lojas exigem dois.

reshape(3, 2) reorganiza seis elementos numa forma compatível. Não cria nem elimina elementos. reshape(-1, 2) pede ao NumPy que deduza o número de linhas. .T troca os eixos de um array 2D.

Broadcasting

Ao multiplicar a matriz (2, 3) por preços com forma (3,), NumPy usa o mesmo vetor de preços em cada linha. Este alargamento chama-se broadcasting. Compara as dimensões a partir da direita: devem ser iguais ou uma delas deve ser 1.

(2, 3) e (3,) são compatíveis. (2, 3) e (2,) não são. Para aplicar um desconto diferente por loja, usa um array com forma (2, 1).

Vistas e cópias

Um slice básico pode ser uma vista, que partilha os dados com o array original. Alterar parte = dados[:2] pode alterar dados. dados[:2].copy() cria dados independentes. Seleção por máscara booleana e índices avançados produz uma cópia; não uses essa distinção como substituto para tornar a alteração explícita.

Quando queres alterar o original, escreve dados[mascara] = novo_valor. Quando queres trabalhar à parte, usa .copy().

Estatísticas e acumulados de arrays

sum, mean, min, max, std e var reduzem valores. NumPy usa ddof=0 por defeito em std e var; indica ddof=1 para a convenção amostral. argmin e argmax devolvem posições, enquanto min e max devolvem valores. Sem eixo, a posição refere-se ao array achatado.

np.cumsum([2, 3, 1]) devolve 2, 5 e 6; np.cumprod devolve 2, 6 e 6. Num array 2D, indica axis para conservar a organização pretendida. Sem eixo, os acumulados usam uma sequência achatada. A presença de NaN pode propagar ausência; funções como np.nansum exprimem a decisão de ignorar NaN.

Gerar dados aleatórios reproduzíveis

Cria um gerador com rng = np.random.default_rng(12). A semente fixa o estado inicial. Na mesma versão e com a mesma sequência de chamadas, podes repetir a experiência; mudar a ordem das chamadas muda os valores seguintes.

Método do geradorResultado
rng.random(4)Quatro reais uniformes em [0, 1)
rng.integers(1, 7, size=4)Quatro inteiros de 1 a 6, extremo superior excluído
rng.standard_normal(4)Quatro observações normais, média 0 e desvio padrão 1
rng.normal(10, 2, size=4)Normal com média 10 e desvio padrão 2
rng.uniform(2, 5, size=4)Uniforme entre 2 e 5
rng.binomial(8, 0.25, size=4)Número de sucessos em oito ensaios, probabilidade 0,25
rng.permutation(valores)Nova sequência com os elementos baralhados
rng.shuffle(valores)Baralha o objeto fornecido, sem devolver uma nova sequência

Slides e programas antigos usam np.random.seed, rand, randint e randn. Correspondem à interface anterior: rand gera uniformes, randint inteiros e randn normais padrão. Para código novo, o gerador explícito evita partilhar estado aleatório global entre exemplos.

Repetir uma simulação de dados
import numpy as np

def lancamentos(semente):
    rng = np.random.default_rng(semente)
    return rng.integers(1, 7, size=12)

a = lancamentos(12)
b = lancamentos(12)
print("repetiu:", np.array_equal(a, b))
print("entre 1 e 6:", bool(((a >= 1) & (a <= 6)).all()))
print("contagens:", np.bincount(a, minlength=7)[1:].tolist())
Dados de entrada

As contagens somam 12. Não devem ser iguais por face numa amostra pequena. Um gerador reproduz uma simulação; não transforma resultados aleatórios numa garantia de frequências exatas.

Exercícios

Prever o tamanho da redução

Um array tem forma (2, 3). Qual é a forma de a.sum(axis=0)?

A tua resposta

Primeira pista
O eixo 0 representa as linhas neste array.
Mais uma pista

O resultado precisa de um total para cada uma das três colunas.

Ver solução

A forma é (3,). Em [[2, 3, 4], [5, 1, 2]], os valores seriam [7, 4, 6].

  • (3,). O eixo das duas linhas é reduzido; sobra um valor por coluna.
  • (2,). Seria o resultado de reduzir axis=1.
  • (2, 3). A soma por um eixo reduz uma dimensão, salvo opções como keepdims.

Erros frequentes

Pensar que axis=0 significa devolver um valor por linha.

Voltar à explicação
Escolher o desconto por linha

Para uma matriz (2, 3), queres multiplicar cada linha por um desconto próprio. Qual deve ser a forma do array de fatores?

A tua resposta

Primeira pista
Compara as formas a partir da direita.
Mais uma pista

Precisas de conservar dois fatores e permitir que cada um se repita em três colunas.

Ver solução

Usa fatores com forma (2, 1). Por exemplo, np.array([0.9, 0.8])[:, None].

  • (2, 1). O eixo das colunas tem tamanho 1 e alarga para as três colunas.
  • (2,). A última dimensão 2 não é compatível com 3.
  • (3,). Aplica um fator por coluna, não um por linha.

Erros frequentes

Supor que o número de fatores basta sem conferir o alinhamento das dimensões.

Voltar à explicação
Reconhecer dados partilhados

a = np.array([1, 2, 3]); b = a[

]; b[0] = 8. Quanto vale a[0]?

Primeira pista
Um slice básico pode devolver uma vista.
Mais uma pista
A vista refere a primeira parte dos mesmos dados.
Ver solução

a[0] passa a 8. Para separar os dados, usa b = a[

].copy().

Erros frequentes

Transferir a regra dos slices de listas para arrays NumPy.

Voltar à explicação
Calcular bytes dos dados

Um array tem forma (2, 3) e dtype float64. Quantos bytes ocupam os seus dados, sem contar a estrutura do objeto?

Primeira pista

Calcula quantos elementos existem e quantos bytes tem cada um.

Mais uma pista
Há seis elementos. Cada float64 usa oito bytes.
Ver solução

2 × 3 × 8 = 48 bytes. a.size é 6, a.itemsize é 8 e a.nbytes é 48.

Erros frequentes

Tratar 64 bits como 64 bytes ou somar as dimensões em vez de as multiplicar.

Voltar à explicação

À tua maneira

Aparência

Modo de cor
Tema
Cor de destaque

Leitura

Fonte de leitura

Álgebra, lógica e uma ideia de cada vez.

Código

Fonte do código

CSS personalizado

Ativa uma sugestão ou guarda o teu CSS. Só muda este navegador.

Usa --page, --text e --accent para acompanhar o tema.

Seletores e recuperação

.site-header, .prose, .course-card, [data-reading-history], [data-playground] e .page-actions.

Abre a aparência com a tecla vírgula ou no rodapé. Se o CSS esconder os controlos, abre esta página sem CSS personalizado.

Pesquisar

Escreve para pesquisar em todo o site.

para escolher · Enter para abrir · Esc para fechar

Atalhos de teclado

Clica numa tecla para a mudar. Esc cancela. Backspace desativa.

PesquisarCtrl / Cmd K

Os atalhos não interferem enquanto escreves. Tab e Enter funcionam sempre.