2012-07-17 10 views
43

Per un esempio di lavoro minimo, digitalizziamo un array 2D. numpy.digitize richiede una matrice 1D:Come posso sapere se NumPy crea una vista o una copia?

import numpy as np 
N = 200 
A = np.random.random((N, N)) 
X = np.linspace(0, 1, 20) 
print np.digitize(A.ravel(), X).reshape((N, N)) 

Ora la documentation says:

... Una copia è fatta solo se necessario.

Come faccio a sapere se la copia è "necessaria" in questo caso? In generale, c'è un modo per determinare se una determinata operazione crea una copia o una vista?

+0

Se vuoi forzare la copia, la cosa migliore che ho trovato è usare np.copy, o np.array come 'tr = np.array (aT, copy = True)' –

risposta

45

Questa domanda è molto simile a un question che ho chiesto un po 'indietro:

È possibile controllare l'attributo base.

a = np.arange(50) 
b = a.reshape((5, 10)) 
print (b.base is a) 

Tuttavia, non è perfetto. Puoi anche controllare se condividono la memoria usando np.may_share_memory.

print (np.may_share_memory(a, b)) 

C'è anche le bandiere attributo che è possibile controllare:

print (b.flags['OWNDATA']) #False -- apparently this is a view 
e = np.ravel(b[:, 2]) 
print (e.flags['OWNDATA']) #True -- Apparently this is a new numpy object. 

Ma quest'ultima sembra un po 'di pesce per me, anche se non riesco a mettere il dito sul perché ...

+0

Interessante, grazie per i link alle tue risposte Lascerò la mia domanda mentre la dicitura "vista" contro "condivisione" è diversa (e non è emersa in una ricerca). – Hooked

+0

@Hooked - Sì, questo è appena abbastanza diverso per me da rispondere alla tua domanda invece di contrassegnarlo come un duplicato (non so cosa penseranno gli altri). Comunque, spero che questo sia utile. – mgilson

+1

Stavo solo provando alcuni di questi e usando 'flags ['OWNDATA']' può sicuramente fallire in alcuni casi. Nel tuo esempio, se usi 'e = np.reshape (b [:, 2], -1)' invece di 'ravel',' flags ['OWNDATA'] 'sarà False, anche se è stata fatta una copia. – amicitas

14

Nella documentazione per reshape ci sono alcune informazioni su come garantire un'eccezione se la vista non può essere fatta:

Non è sempre possibile modificare la forma di una matrice senza copiare i dati. Se si desidera un errore essere sollevata se i dati vengono copiati, è necessario assegnare la nuova forma all'attributo forma della matrice:

>>> a = np.zeros((10, 2)) 
# A transpose make the array non-contiguous 
>>> b = a.T 
# Taking a view makes it possible to modify the shape without modiying the 
# initial object. 
>>> c = b.view() 
>>> c.shape = (20) 
AttributeError: incompatible shape for a non-contiguous array 



Questo non è esattamente una risposta alla tua domanda , ma in alcuni casi potrebbe essere altrettanto utile.

Problemi correlati