Eu tenho uma variável, x, que é da forma (2,2,50,100).
Eu também tenho uma matriz, y, que é igual a np.array ([0,10,20]). Uma coisa estranha acontece quando eu indexo x [0,:,:, y].
x = np.full((2,2,50,100),np.nan)
y = np.array([0,10,20])
print(x.shape)
(2,2,50,100)
print(x[:,:,:,y].shape)
(2,2,50,3)
print(x[0,:,:,:].shape)
(2,50,100)
print(x[0,:,:,y].shape)
(3,2,50)
Por que o último produz (3,2,50) e não (2,50,3)?
Respostas:
É assim que o numpy usa a indexação avançada para transmitir formas de array. Quando você passa a
0
para o primeiro índice ey
o último, numpy transmitirá0
a mesma forma quey
. A seguir equivalência detém:x[0,:,:,y] == x[(0, 0, 0),:,:,y]
. aqui está um exemploAgora, como você efetivamente passa dois conjuntos de índices, está usando a API de indexação avançada para formar (nesse caso) pares de índices.
Qual tem uma primeira dimensão igual ao comprimento de
y
. Isto é o que você está vendo.Como exemplo, observe uma matriz com 4 dimensões, descritas no próximo bloco:
x
tem uma forma seqüencial realmente fácil de entender que agora podemos usar para mostrar o que está acontecendo ...A primeira dimensão é como ter 2 pastas de trabalho do Excel, a segunda dimensão é como ter 3 folhas em cada pasta de trabalho, a terceira dimensão é como ter 4 linhas por folha e a última dimensão é de 5 valores para cada linha (ou colunas por folha).
Olhando dessa maneira, solicitando
x[0,:,:,0]
, está o ditado: "na primeira pasta de trabalho, para cada planilha, para cada linha, me dê o primeiro valor / coluna".Mas agora, com a indexação avançada, podemos pensar
x[(0,0,0),:,:,y]
como "na primeira pasta de trabalho, para cada planilha, para cada linha, me dê oy
valor / coluna. Ok, agora faça isso para cada valor dey
"Onde fica louco é que numpy será transmitido para corresponder às dimensões externas da matriz de índice. Portanto, se você quiser fazer a mesma operação acima, mas para as "pastas de trabalho do Excel", não precisará fazer loop e concatenar. Você pode simplesmente passar uma matriz para a primeira dimensão, mas DEVE ter uma forma compatível.
Passar um número inteiro é transmitido para
y.shape == (3,)
. Se você deseja passar uma matriz como o primeiro índice, apenas a última dimensão da matriz deve ser compatívely.shape
. Ou seja, a última dimensão do primeiro índice deve ser 3 ou 1.Encontre uma breve explicação nos documentos: https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#combining-advanced-and-basic-indexing
Editar:
A partir da pergunta original, para obter uma linha do seu sub-corte desejado, você pode usar
x[0][:,:,y]
:No entanto, se você estiver tentando atribuir a essas sub-fatias, tenha muito cuidado para ver uma exibição de memória compartilhada da matriz original. Caso contrário, a atribuição não será para a matriz original, mas uma cópia.
A memória compartilhada ocorre apenas quando você usa um número inteiro ou uma fatia para subconjunto de sua matriz,
x[:,0:3,:,:]
ou seja, oux[0,:,:,1:-1]
.Na sua pergunta original e no meu exemplo
y
não é um int ou uma fatia, portanto, sempre acabará atribuindo uma cópia do original.MAS! Como sua matriz para
y
pode ser expressa como uma fatia, você PODE obter uma visualização atribuível de sua matriz por meio de:Aqui, usamos a fatia
0:21:10
para obter todos os índices em que estariarange(0,21,10)
. Temos que usar21
e não20
porque o ponto de parada é excluído da fatia, assim como norange
função.Então, basicamente, se você pode construir uma fatia que atenda aos seus critérios de subslicing, poderá fazer a atribuição.
fonte
É chamado
combining advanced and basic indexing
. Emcombining advanced and basic indexing
, numpy, faça primeiro a indexação na indexação avançada e subespaça / concatene o resultado para a dimensão da indexação básica.Exemplo dos documentos:
assim, em
x[0,:,:,y]
,0
ey
são antecedência indexação. Eles são transmitidos juntos para gerar dimensão(3,)
.este
(3,)
segue para o início da 2ª e 3ª dimensão para fazer(3, 2, 50)
Para ver que a 1ª e última dimensão realmente estão transmitindo em conjunto, você pode tentar mudar
0
para[0,1]
ver o erro da radiodifusãofonte