que - python 3.7 numpy




Fatiar uma matriz NumPy 2d, ou como eu extraio uma submatriz mxm de uma matriz nxn(n> m)? (5)

Com numpy, você pode passar uma fatia para cada componente do índice - assim, o seu exemplo x[0:2,0:2] acima funciona.

Se você quiser apenas ignorar colunas ou linhas, pode passar fatias com três componentes (isto é, iniciar, parar, passo).

Mais uma vez, para o seu exemplo acima:

>>> x[1:4:2, 1:4:2]
array([[ 5,  7],
       [13, 15]])

Que é basicamente: fatia na primeira dimensão, com início no índice 1, parar quando o índice é igual ou maior que 4 e adicionar 2 ao índice em cada passagem. O mesmo para a segunda dimensão. Novamente: isso só funciona para etapas constantes.

A sintaxe que você tem para fazer algo bem diferente internamente - o que x[[1,3]][:,[1,3]] realmente faz é criar uma nova matriz incluindo apenas as linhas 1 e 3 da matriz original (feita com o x[[1,3]] parte) e, em seguida, dividir novamente - criando uma terceira matriz - incluindo apenas as colunas 1 e 3 da matriz anterior.

Eu quero dividir uma matriz NumPy nxn. Eu quero extrair uma seleção arbitrária de m linhas e colunas dessa matriz (ou seja, sem qualquer padrão nos números de linhas / colunas), tornando-se uma nova matriz mxm. Para este exemplo, digamos que o array é 4x4 e eu quero extrair um array 2x2 dele.

Aqui é a nossa matriz:

from numpy import *
x = range(16)
x = reshape(x,(4,4))

print x
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]

A linha e as colunas a serem removidas são as mesmas. O caso mais fácil é quando eu quero extrair uma submatriz 2x2 que está no início ou no final, ou seja:

In [33]: x[0:2,0:2]
Out[33]: 
array([[0, 1],
       [4, 5]])

In [34]: x[2:,2:]
Out[34]: 
array([[10, 11],
       [14, 15]])

Mas e se eu precisar remover outra mistura de linhas / colunas? E se eu precisar remover a primeira e a terceira linhas / linhas, extraindo assim a submatriz [[5,7],[13,15]] ? Pode haver qualquer composição de linhas / linhas. Eu li em algum lugar que eu só preciso indexar meu array usando matrizes / listas de índices para linhas e colunas, mas isso não parece funcionar:

In [35]: x[[1,3],[1,3]]
Out[35]: array([ 5, 15])

Eu encontrei um caminho, que é:

    In [61]: x[[1,3]][:,[1,3]]
Out[61]: 
array([[ 5,  7],
       [13, 15]])

O primeiro problema com isso é que é dificilmente legível, embora eu possa viver com isso. Se alguém tiver uma solução melhor, eu certamente gostaria de ouvir.

Outra coisa é que eu li em um fórum que as matrizes de indexação com matrizes forçam o NumPy a fazer uma cópia da matriz desejada, portanto, ao tratar com grandes matrizes, isso pode se tornar um problema. Por que isso acontece / como funciona esse mecanismo?


Como Sven mencionou, x[[[0],[2]],[1,3]] devolverá as linhas 0 e 2 que correspondem às colunas 1 e 3 enquanto x[[0,2],[1,3]] retornará os valores x [0,1] e x [2,3] em uma matriz.

Há uma função útil para fazer o primeiro exemplo que dei, numpy.ix_ . Você pode fazer a mesma coisa que meu primeiro exemplo com x[numpy.ix_([0,2],[1,3])] . Isso pode evitar que você tenha que inserir todos esses colchetes extras.



Não tenho certeza de como isso é eficiente, mas você pode usar o intervalo () para dividir em ambos os eixos

 x=np.arange(16).reshape((4,4))
 x[range(1,3), :][:,range(1,3)] 

Se você quiser pular todas as outras linhas e todas as outras colunas, você pode fazer isso com o fatiamento básico:

In [49]: x=np.arange(16).reshape((4,4))
In [50]: x[1:4:2,1:4:2]
Out[50]: 
array([[ 5,  7],
       [13, 15]])

Isso retorna uma visão, não uma cópia da sua matriz.

In [51]: y=x[1:4:2,1:4:2]

In [52]: y[0,0]=100

In [53]: x   # <---- Notice x[1,1] has changed
Out[53]: 
array([[  0,   1,   2,   3],
       [  4, 100,   6,   7],
       [  8,   9,  10,  11],
       [ 12,  13,  14,  15]])

enquanto z=x[(1,3),:][:,(1,3)] usa indexação avançada e, portanto, retorna uma cópia:

In [58]: x=np.arange(16).reshape((4,4))
In [59]: z=x[(1,3),:][:,(1,3)]

In [60]: z
Out[60]: 
array([[ 5,  7],
       [13, 15]])

In [61]: z[0,0]=0

Note que x é inalterado:

In [62]: x
Out[62]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])

Se você deseja selecionar linhas e colunas arbitrárias, não poderá usar o fatiamento básico. Você terá que usar indexação avançada, usando algo como x[rows,:][:,columns] , onde rows e columns são seqüências. Isto, obviamente, vai lhe dar uma cópia, não uma visão, do seu array original. Isso é como se deve esperar, já que um array numpy usa memória contígua (com strides constantes), e não haveria como gerar uma view com linhas e colunas arbitrárias (já que isso exigiria strides não constantes).







slice