NumPy em Python. Parte 3

Prefácio do tradutor


Olá novamente! Continuando nossa série de artigos sobre a tradução de mana sobre numpy. Boa leitura.


Operadores de comparação e teste de valor


A comparação booleana pode ser usada para comparação elementar de matrizes do mesmo comprimento. O valor de retorno é uma matriz de valores booleanos True / False:

>>> a = np.array([1, 3, 0], float) >>> b = np.array([0, 3, 2], float) >>> a > b array([ True, False, False], dtype=bool) >>> a == b array([False, True, False], dtype=bool) >>> a <= b array([False, True, True], dtype=bool) 

O resultado da comparação pode ser armazenado em uma matriz:

 >>> c = a > b >>> c array([ True, False, False], dtype=bool) 

As matrizes podem ser comparadas com um único valor:

 >>> a = np.array([1, 3, 0], float) >>> a > 2 array([False, True, False], dtype=bool) 

Os operadores any e all podem ser usados ​​para determinar se pelo menos um ou todos os elementos são verdadeiros, respectivamente:

 >>> c = np.array([ True, False, False], bool) >>> any(c) True >>> all(c) False 

Expressões booleanas combinadas podem ser aplicadas a matrizes elemento a elemento usando as funções especiais logic_and, logic_or e logic_not:

 >>> a = np.array([1, 3, 0], float) >>> np.logical_and(a > 0, a < 3) array([ True, False, False], dtype=bool) >>> b = np.array([True, False, True], bool) >>> np.logical_not(b) array([False, True, False], dtype=bool) >>> c = np.array([False, True, False], bool) >>> np.logical_or(b, c) array([ True, True, False], dtype=bool) 

A função where cria uma nova matriz a partir de duas outras matrizes do mesmo comprimento usando um filtro booleano para selecionar entre dois elementos. Sintaxe básica: where (boolarray,
truearray, falsearray):

 >>> a = np.array([1, 3, 0], float) >>> np.where(a != 0, 1 / a, a) array([ 1. , 0.33333333, 0. ]) 

Com a função where, a comparação em massa também pode ser implementada:

 >>> np.where(a > 0, 3, 2) array([3, 3, 2]) 

Algumas funções tornam possível testar valores em uma matriz. A função diferente de zero retorna uma tupla de índices de valores diferentes de zero. O número de elementos na tupla é igual ao número de eixos na matriz:

 >>> a = np.array([[0, 1], [3, 0]], float) >>> a.nonzero() (array([0, 1]), array([1, 0])) 

Você também pode verificar os valores de finitude e NaN (não um número):

 >>> a = np.array([1, np.NaN, np.Inf], float) >>> a array([ 1., NaN, Inf]) >>> np.isnan(a) array([False, True, False], dtype=bool) >>> np.isfinite(a) array([ True, False, False], dtype=bool) 

Embora tenhamos usado constantes numpy aqui para adicionar NaN e infinito, elas podem ser o resultado da aplicação de operações matemáticas padrão.

Selecionando e manipulando elementos da matriz


Já vimos, como nas listas, elementos de matriz podem ser obtidos usando a operação de acesso por índice. No entanto, diferentemente das listas, as matrizes também permitem selecionar itens usando outras matrizes. Isso significa que podemos usar uma matriz para filtrar subconjuntos específicos dos elementos de outras matrizes.

Matrizes booleanas podem ser usadas como matrizes para filtragem:

 >>> a = np.array([[6, 4], [5, 9]], float) >>> a >= 6 array([[ True, False], [False, True]], dtype=bool) >>> a[a >= 6] array([ 6., 9.]) 

Vale notar que, quando passamos uma matriz booleana a> = 6 como um índice para a operação de acesso pelo índice da matriz a, a matriz retornada armazenará apenas valores True. Também podemos escrever uma matriz para filtrar em uma variável:

 >>> a = np.array([[6, 4], [5, 9]], float) >>> sel = (a >= 6) >>> a[sel] array([ 6., 9.]) 

É possível obter uma filtragem mais sofisticada usando expressões booleanas:

 >>> a[np.logical_and(a > 5, a < 9)] >>> array([ 6.]) 

Além da seleção booleana, você também pode usar matrizes inteiras. Nesse caso, a matriz inteira armazena os índices dos elementos a serem obtidos da matriz. Considere o seguinte exemplo unidimensional:

 >>> a = np.array([2, 4, 6, 8], float) >>> b = np.array([0, 0, 1, 3, 2, 1], int) >>> a[b] array([ 2., 2., 4., 8., 6., 4.]) 

Em outras palavras, quando usamos b para obter os elementos de a, pegamos os 0º, 0º, 1º, 3º, 2º e 1º elementos de a nesta ordem. As listas também podem ser usadas como matrizes para filtragem:

 >>> a = np.array([2, 4, 6, 8], float) >>> a[[0, 0, 1, 3, 2, 1]] array([ 2., 2., 4., 8., 6., 4.]) 

Para matrizes multidimensionais, precisamos transferir várias matrizes inteiras unidimensionais para o índice do operador de acesso ( tradutor de notas: no nosso caso, índices são matrizes ) para cada eixo. Cada uma das matrizes passa pela seguinte sequência: o primeiro elemento corresponde ao índice da linha, que é o primeiro elemento da matriz b, o segundo elemento corresponde ao índice da coluna, que é o primeiro elemento da matriz c e assim por diante. ( Nota do tradutor: a primeira matriz [2, 2] e a segunda [1, 4], temos elementos com os índices [2, 1] e [2, 4] na saída ) Exemplo:

 >>> a = np.array([[1, 4], [9, 16]], float) >>> b = np.array([0, 0, 1, 1, 0], int) >>> c = np.array([0, 1, 1, 1, 1], int) >>> a[b,c] array([ 1., 4., 16., 16., 4.]) 

Uma função take especial está disponível para buscar com matrizes inteiras. Isso funciona da mesma forma que o operador take em um índice:

 >>> a = np.array([2, 4, 6, 8], float) >>> b = np.array([0, 0, 1, 3, 2, 1], int) >>> a.take(b) array([ 2., 2., 4., 8., 6., 4.]) 

A função take também fornece o argumento do eixo para obter uma subseção da matriz multidimensional ao longo de um eixo. ( Nota tradutor: linha ou coluna (para matrizes bidimensionais) ).

 >>> a = np.array([[0, 1], [2, 3]], float) >>> b = np.array([0, 0, 1], int) >>> a.take(b, axis=0) array([[ 0., 1.], [ 0., 1.], [ 2., 3.]]) >>> a.take(b, axis=1) array([[ 0., 0., 1.], [ 2., 2., 3.]]) 

Ao contrário da função take, existe uma função put, que pega valores da matriz original e os grava em índices específicos em outra matriz put.

 >>> a = np.array([0, 1, 2, 3, 4, 5], float) >>> b = np.array([9, 8, 7], float) >>> a.put([0, 3], b) >>> a array([ 9., 1., 2., 8., 4., 5.]) 

Observe que o valor 7 da matriz original b não foi usado, pois apenas 2 índices [0, 3] são indicados. A matriz original será repetida, se necessário, se os comprimentos não corresponderem:

 >>> a = np.array([0, 1, 2, 3, 4, 5], float) >>> a.put([0, 3], 5) >>> a array([ 5., 1., 2., 5., 4., 5.]) 

Matemática vetorial e matricial


O NumPy fornece muitas funções para trabalhar com vetores e matrizes. A função dot retorna o produto escalar de vetores:

 >>> a = np.array([1, 2, 3], float) >>> b = np.array([0, 1, 1], float) >>> np.dot(a, b) 5.0 

A função ponto também pode multiplicar matrizes:

 >>> a = np.array([[0, 1], [2, 3]], float) >>> b = np.array([2, 3], float) >>> c = np.array([[1, 1], [4, 0]], float) >>> a array([[ 0., 1.], [ 2., 3.]]) >>> np.dot(b, a) array([ 6., 11.]) >>> np.dot(a, b) array([ 3., 13.]) >>> np.dot(a, c) array([[ 4., 0.], [ 14., 2.]]) >>> np.dot(c, a) array([[ 2., 4.], [ 0., 4.]]) 

Você também pode obter o produto escalar, tensor e externo de matrizes e vetores. Observe que para vetores o produto interno e escalar coincide.

 >>> a = np.array([1, 4, 0], float) >>> b = np.array([2, 2, 1], float) >>> np.outer(a, b) array([[ 2., 2., 1.], [ 8., 8., 4.], [ 0., 0., 0.]]) >>> np.inner(a, b) 10.0 >>> np.cross(a, b) array([ 4., -1., -6.]) 

O NumPy também fornece um conjunto de funções e métodos internos para trabalhar com álgebra linear. Tudo isso pode ser encontrado no submódulo linalg. Esses módulos também podem ser operados com matrizes degeneradas e não degeneradas. O determinante da matriz é pesquisado desta maneira:

 >>> a = np.array([[4, 2, 0], [9, 3, 7], [1, 2, 1]], float) >>> a array([[ 4., 2., 0.], [ 9., 3., 7.], [ 1., 2., 1.]]) >>> np.linalg.det(a) -48. 

Você também pode encontrar o vetor próprio e o valor próprio da matriz:

 >>> vals, vecs = np.linalg.eig(a) >>> vals array([ 9. , 2.44948974, -2.44948974]) >>> vecs array([[-0.3538921 , -0.56786837, 0.27843404], [-0.88473024, 0.44024287, -0.89787873], [-0.30333608, 0.69549388, 0.34101066]]) 

Uma matriz não degenerada pode ser encontrada da seguinte forma:

 >>> b = np.linalg.inv(a) >>> b array([[ 0.14814815, 0.07407407, -0.25925926], [ 0.2037037 , -0.14814815, 0.51851852], [-0.27777778, 0.11111111, 0.11111111]]) >>> np.dot(a, b) array([[ 1.00000000e+00, 5.55111512e-17, 2.22044605e-16], [ 0.00000000e+00, 1.00000000e+00, 5.55111512e-16], [ 1.11022302e-16, 0.00000000e+00, 1.00000000e+00]]) 

Uma única decomposição (um análogo da diagonalização de uma matriz não quadrada) pode ser obtida da seguinte maneira:

 >>> a = np.array([[1, 3,4], [5, 2, 3]], float) >>> U, s, Vh = np.linalg.svd(a) >>> U array([[-0.6113829 , -0.79133492], [-0.79133492, 0.6113829 ]]) >>> s array([ 7.46791327, 2.86884495]) >>> Vh array([[-0.61169129, -0.45753324, -0.64536587], [ 0.78971838, -0.40129005, -0.46401635], [-0.046676 , -0.79349205, 0.60678804]]) 

Terminamos a terceira parte. Boa sorte e até breve!

Source: https://habr.com/ru/post/pt413381/


All Articles