6.11. Reduções¶
Uma redução colapsa um array ao longo de um ou mais eixos calculando somas, médias, mínimos, entre outros. Cada redução é uma única chamada à biblioteca aplicada ao array completo, muito mais rápida do que o ciclo Python equivalente. O numpy cobre as mais comuns:
sum()– soma de todos os elementosmean()– média aritmética (soma dividida pelo número de elementos)std()– desvio padrão;ddof=ajusta o divisor (N - ddof)median()– valor central quando os elementos estão ordenados (percentil 50)all()/any()– reduções de valor lógico em arrays booleanos
6.11.1. Sem a palavra-chave axis¶
Sem axis=, uma redução devolve um escalar que abrange todo o array:
a = np.array([1, 2, 3, 4], dtype=np.float)
np.sum(a) # 10.0
np.mean(a) # 2.5
np.std(a) # 1.118...
np.median(a) # 2.5
b = np.array([40, 10, 30, 20], dtype=np.float)
np.max(b) # 40.0
np.argmax(b) # 0 (index of the maximum)
6.11.2. Com a palavra-chave axis¶
axis= contrai um eixo específico e deixa os restantes intactos. O resultado é um array de classificação uma unidade inferior à entrada:
m = np.arange(12, dtype=np.float).reshape((3, 4))
np.sum(m) # 66.0 - scalar
np.sum(m, axis=0) # length-4 - column sums
np.sum(m, axis=1) # length-3 - row sums
A mesma regra de forma aplica-se a todas as reduções: axis=0 colapsa o primeiro eixo, axis=1 colapsa o segundo, e assim por diante. A média e o desvio padrão ao longo de uma linha, por exemplo, escrevem-se np.mean(m, axis=1) e np.std(m, axis=1). O resultado tem o comprimento do outro eixo.
A palavra-chave keepdims=True mantém o eixo contraído no lugar com comprimento 1 em vez de o eliminar. A distinção é importante quando o resultado reduzido precisa de ser difundido de volta contra o original: keepdims preserva a classificação, o que mantém as regras de difusão alinhadas eixo a eixo.
Subtrair a média de cada linha a essa linha é o uso canónico:
m = np.arange(12, dtype=np.float).reshape((3, 4))
row_means = np.mean(m, axis=1, keepdims=True)
# row_means has shape (3, 1)
centred = m - row_means
# (3, 4) - (3, 1) -> (3, 4), each row centred on its own mean
Sem keepdims, np.mean(m, axis=1) devolve um resultado unidimensional de forma (3,). Difundir (3, 4) - (3,) alinha (3,) como (1, 3) após o acréscimo de classificação, o que é incompatível com (3, 4): os últimos eixos discordam (4 contra 3) e nenhum é 1, por isso o numpy lança ValueError. É o keepdims=True que mantém a subtração válida.
6.11.3. A disposição importa¶
Combinado com a disposição row-major abordada em Forma e strides, reduzir ao longo do último eixo é o caso mais económico. A redução percorre o bloco de dados na direção em que está armazenado, sem saltos de linha para linha:
m = np.arange(2000, dtype=np.float).reshape((2, 1000))
np.sum(m, axis=1) # cheap - long axis is the inner one
np.sum(m, axis=0) # has to jump rows on every step
Quando a aplicação tem a possibilidade de escolher a disposição de um buffer, coloque o eixo longo por último para que as reduções ao longo do mesmo corram na direção mais rápida.
6.11.4. Iteráveis como entrada¶
A maioria das reduções aceita um iterável Python (uma list, um range, um tuplo) em vez de um ndarray. A conveniência tem um custo de alguns microssegundos pela conversão implícita – que se acumula rapidamente dentro de um ciclo. Quando os mesmos dados são reduzidos várias vezes, construa o ndarray uma vez e passe-o como argumento.