Eu quero cortar uma matriz NumPy nxn. Eu quero extrair uma seleção arbitrária de m linhas e colunas dessa matriz (ou seja, sem nenhum padrão no número de linhas / colunas), tornando-a uma nova matriz mxm. Neste exemplo, digamos que a matriz é 4x4 e quero extrair uma matriz 2x2 dela.
Aqui está 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 começo ou no fim, 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 linha / linha, extraindo a submatriz [[5,7],[13,15]]
? Pode haver qualquer composição de linhas / linhas. Eu li em algum lugar que eu só preciso indexar minha matriz 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 uma maneira, que é:
In [61]: x[[1,3]][:,[1,3]]
Out[61]:
array([[ 5, 7],
[13, 15]])
A primeira questão é que é dificilmente legível, embora eu possa viver com isso. Se alguém tiver uma solução melhor, eu certamente gostaria de ouvi-la.
Outra coisa é que li em um fórum que a indexação de matrizes com matrizes força o NumPy a fazer uma cópia da matriz desejada, portanto, ao tratar com matrizes grandes, isso pode se tornar um problema. Por que é assim / como esse mecanismo funciona?
x[[[1],[3]],[1,3]]
cria apenas uma nova matriz, enquantox[[1,3],:][:,[1,3]]
copia duas vezes, então use a primeira.Eu não acho isso
x[[1,3]][:,[1,3]]
dificilmente legível. Se você quiser ser mais claro sobre sua intenção, pode:Eu não sou especialista em fatiar, mas normalmente, se você tentar dividir em uma matriz e os valores forem contínuos, você voltará a ver onde o valor da passada é alterado.
Por exemplo, nas entradas 33 e 34, embora você obtenha uma matriz 2x2, o passo é 4. Assim, quando você indexa a próxima linha, o ponteiro se move para a posição correta na memória.
Claramente, esse mecanismo não se encaixa bem no caso de uma matriz de índices. Portanto, numpy terá que fazer a cópia. Afinal, muitas outras funções matemáticas da matriz dependem do tamanho, avanço e alocação de memória contínua.
fonte
Se você quiser pular todas as outras linhas e outras colunas, poderá fazê-lo com o fatiamento básico:
Isso retorna uma visualização, não uma cópia da sua matriz.
while
z=x[(1,3),:][:,(1,3)]
usa indexação avançada e, portanto, retorna uma cópia:Observe que
x
não é alterado:Se você deseja selecionar linhas e colunas arbitrárias, não pode usar o fatiamento básico. Você precisará usar a indexação avançada, usando algo como
x[rows,:][:,columns]
, onderows
ecolumns
são sequências. Obviamente, isso fornecerá uma cópia, não uma visualização, da sua matriz original. É o que se espera, uma vez que uma matriz numpy usa memória contígua (com avanços constantes), e não haveria maneira de gerar uma exibição com linhas e colunas arbitrárias (já que isso exigiria avanços não constantes).fonte
Com numpy, você pode passar uma fatia para cada componente do índice - assim, seu
x[0:2,0:2]
exemplo acima funciona.Se você quiser pular uniformemente colunas ou linhas, pode passar fatias com três componentes (ou seja, iniciar, parar, etapa).
Novamente, para o seu exemplo acima:
O que é basicamente: fatia na primeira dimensão, com início no índice 1, pare quando o índice for igual ou superior a 4 e adicione 2 ao índice em cada passagem. O mesmo para a segunda dimensão. Novamente: isso funciona apenas para etapas constantes.
A sintaxe que você precisa fazer é algo completamente 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 ax[[1,3]]
parte) e, em seguida, cortar novamente isso - criando uma terceira matriz - incluindo apenas colunas 1 e 3 da matriz anterior.fonte
Eu tenho uma pergunta semelhante aqui: Escrevendo no subarray de um ndarray da maneira mais pythoniana. Python 2 .
Seguindo a solução da postagem anterior para o seu caso, a solução se parece com:
Um usando ix_:
Qual é:
fonte
Não sei ao certo quão eficiente isso é, mas você pode usar range () para cortar nos dois eixos
fonte