2011-08-21 9 views
15

Esiste una funzione numpy per dividere un array lungo un asse con elementi provenienti da un altro array? Ad esempio, supponiamo di avere un array a con forma (l, m, n) e un array b con forma (m,); Sto cercando qualcosa di equivalente a:numpy divide lungo l'asse

def divide_along_axis(a,b,axis=None): 
    if axis is None: 
     return a/b 
    c = a.copy() 
    for i, x in enumerate(c.swapaxes(0,axis)): 
     x /= b[i] 
    return c 

Ad esempio, ciò è utile quando normalizzare una serie di vettori:

>>> a = np.random.randn(4,3) 
array([[ 1.03116167, -0.60862215, -0.29191449], 
     [-1.27040355, 1.9943905 , 1.13515384], 
     [-0.47916874, 0.05495749, -0.58450632], 
     [ 2.08792161, -1.35591814, -0.9900364 ]]) 
>>> np.apply_along_axis(np.linalg.norm,1,a) 
array([ 1.23244853, 2.62299312, 0.75780647, 2.67919815]) 
>>> c = divide_along_axis(a,np.apply_along_axis(np.linalg.norm,1,a),0) 
>>> np.apply_along_axis(np.linalg.norm,1,c) 
array([ 1., 1., 1., 1.]) 

risposta

23

Per l'esempio specifico che hai dato: dividere un (l, m, n) array (m,) è possibile utilizzare np .newaxis:

a = np.arange(1,61, dtype=float).reshape((3,4,5)) # Create a 3d array 
a.shape           # (3,4,5) 

b = np.array([1.0, 2.0, 3.0, 4.0])    # Create a 1-d array 
b.shape           # (4,) 

a/b            # Gives a ValueError 

a/b[:, np.newaxis]        # The result you want 

è possibile leggere tutti circa le regole di trasmissione here. È anche possibile utilizzare newaxis più di una volta, se necessario. (ad esempio per dividere una matrice di forma (3,4,5,6) con una matrice di forma (3,5)).

Dalla mia comprensione dei documenti, l'uso di newaxis + broadcasting evita anche qualsiasi copia di array non necessaria.

L'indicizzazione, newaxis ecc. Sono descritte più completamente here ora. (La documentazione è stata riorganizzata da quando è stata pubblicata questa risposta per la prima volta).

0

penso che si può ottenere questo comportamento con comportamento abituale trasmissione di numpy:

In [9]: a = np.array([[1., 2.], [3., 4.]]) 

In [10]: a/np.sum(a, axis=0) 
Out[10]: 
array([[ 0.25  , 0.33333333], 
     [ 0.75  , 0.66666667]]) 

Se ho interpretato correttamente.

Se si desidera che l'altro asse si potrebbe trasporre tutto:

> a = np.random.randn(4,3).transpose() 
> norms = np.apply_along_axis(np.linalg.norm,0,a) 
> c = a/norms 
> np.apply_along_axis(np.linalg.norm,0,c) 
array([ 1., 1., 1., 1.]) 
+0

no, non è così. questo metodo fallisce ad esempio con l'array 2-d che ho fornito come esempio. come risulta, per l'esempio che ti ho dato puoi fare c = a/np.apply_along_axis (np.linalg.norm, 1, a) [:, np.newaxis] ma sto cercando qualcosa di più generale come la funzione divide_along_axis() che definisco nella domanda. – user545424

+1

Che ne dici di trasporre (vedi risposta modificata)? O potresti definire 'divide_along_axis' prima trasponendo, dividendo, poi trasponendo indietro. – Owen

+1

Basta aggiungere un nuovo asse all'array 1d. – tillsten