master:tutorial_numpy_1_index Tutorial Numpy - index
ndarray
Índice:
O ndarray
foi projetado para acesso otimizado a uma grande quantidade de dados. Neste sentido, os conceitos
descritos a seguir sobre as três formas de cópias entre variáveis ditas sem cópia, cópia rasa (shallow) e
cópia profunda (deep) são fundamentais para uma codificação eficiente. Podemos dizer que um ndarray
possui
o cabeçalho que contém dados pelas informações sobre o tipo do elemento, a dimensionalidade (shape
) e
passo ou deslocamento para o próximo elemento (strides
) e os dados raster em si. A tabela
a seguir mostra a situação do cabeçalho e dos dados nos três tipos de cópias.
Tipo | Cabeçalho: Type, Shape, Strides | Dados raster | Exemplo |
---|---|---|---|
Sem cópia, apenas ref | apontador original | apontador original | a = b |
Cópia rasa | novo | apontador original | b = a.reshape, slicing, a.T |
Cópia profunda | novo | novo | a = b.copy() |
No caso abaixo, usaremos o comando normal de igual como atribuição do array a
para o array b
.
Verifica-se que tanto o shape como os dados de b
são os mesmos de a
. Tudo se passa como b
fosse apenas um apontador para a
. Qualquer modificação em b
é refletida em a
.
In [1]:
import numpy as np
a = np.arange(6)
b = a
print "a =\n",a
print "b =\n",b
b.shape = (2,3) # mudança no shape de b,
print "\na shape =",a.shape # altera o shape de a
b[0,0] = -1 # mudança no conteúdo de b
print "a =\n",a # altera o conteudo de a
print "\nid de a = ",id(a) # id é um identificador único de objeto
print "id de b = ",id(b) # a e b possuem o mesmo id
print 'np.may_share_memory(a,b):',np.may_share_memory(a,b)
Observe que mesmo no retorno de uma função, a cópia explícita pode não acontecer. Veja o exemplo a seguir de uma função que apenas retorna a variável de entrada:
In [2]:
def cc(a):
return a
b = cc(a)
print "id de a = ",id(a)
print "id de b = ",id(b)
print 'np.may_share_memory(a,b):',np.may_share_memory(a,b)
A cópia rasa é muito útil e extensivamente utilizada. É usada quando se quer indexar o array original através da mudança de dimensionalidade ou do refatiamento, porém sem a necessidade de realizar uma cópia dos dados raster. Desta forma consegue-se uma otimização no acesso ao array n-dimensional. Existem várias formas onde a cópia rasa acontece, sendo as principais:
reshape
onde o número de elementos do ndarray
é o mesmo, porém sua dimensionalidade
é alterada; ravel()
. entre outros.O exemplo a seguir mostra inicialmente a criação de um vetor unidimensional sequencial sendo "visto" de forma bidimensional ou tridimensional.
In [3]:
a = np.arange(30)
print "a =\n", a
b = a.reshape( (5, 6))
print "b =\n", b
b[:, 0] = -1
print "a =\n", a
c = a.reshape( (2, 3, 5) )
print "c =\n", c
print 'c.base is a:',c.base is a
print 'np.may_share_memory(a,c):',np.may_share_memory(a,c)
O exemplo a seguir mostra a cópia rasa no uso de fatiamento. No exemplo, todos os elementos de linhas
e colunas pares são modificados para 1. CUIDADO: quando é feita a atribuição de b = 1.
, é importante
que b
seja referenciado como ndarray na forma b[:,:]
, caso contrário, se fizermos b = 1.
, uma nova
variável é criada.
In [4]:
import ia636 as ia
a = np.zeros( (5, 6))
print ia.iaimginfo(a)
b = a[::2,::2]
print ia.iaimginfo(b)
b[:,:] = 1.
print 'b=\n', b
print 'a=\n', a
print 'b.base is a:',b.base is a
print 'np.may_share_memory(a,b):',np.may_share_memory(a,b)
In [ ]:
Este outro exemplo é uma forma atraente de processar uma coluna de uma matriz bidimensional,
porém é preciso CUIDADO, pois o uso de b deve ser com b[:] se for atribuído um novo valor para
ele, caso contrário, se fizermos b = arange(5), uma nova variável é criada.
.. code:: python
a = np.arange(25).reshape((5,5))
print 'a=\n',a
b = a[:,0]
print 'b=',b
b[:] = np.arange(5)
print 'b=',b
print 'a=\n',a
Transposto
----------
A operação matricial de transposição que troca linhas por colunas produz também um *view*
da imagem, sem necessidade de cópia:
.. code:: python
a = np.arange(24).reshape((4,6))
print 'a:\n',a
at = a.T
print 'at:\n',at
print 'np.may_share_memory(a,at):',np.may_share_memory(a,at)
Ravel
-----
Aplicando-se o método ``ravel()`` a um ``ndarray``, gera-se um *view* do raster
linearizado (i.e. uma única dimensão) do ``ndarray``.
.. code:: python
a = np.arange(24).reshape((4,6))
print 'a:\n',a
av = a.ravel()
print 'av.shape:',av.shape
print 'av:\n',av
print 'np.may_share_memory(a,av):',np.may_share_memory(a,av)
Cópia profunda
==============
Cria uma copia completa do array, do seu shape e conteúdo. A recomendação é utilizar a
função ``copy()`` para realizar a copia profunda, entretanto é possível conseguir a
copia profunda pelo ``np.array``.
.. code:: python
b = a.copy()
c = np.array(a, copy=True)
print "id de a = ",id(a)
print "id de b = ",id(b)
print "id de c = ",id(c)
Documentação Oficial Numpy
===========================
`http://wiki.scipy.org/Tentative_NumPy_Tutorial#head-1529ae93dd5d431ffe3a1001a4ab1a394e70a5f2 Copies and Views`