2011-08-21 10 views
15

¿Hay una función numpy para dividir una matriz a lo largo de un eje con elementos de otra matriz? Por ejemplo, supongamos que tengo una matriz a con forma (l, m, n) y una matriz b con forma (m,); Busco algo equivalente a:numpy divide a lo largo del eje

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 

Por ejemplo, esto es útil cuando la normalización de un conjunto de vectores:

>>> 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.]) 

Respuesta

23

Para el ejemplo específico que has dado: dividir una (l, m, n) array (m,) se puede utilizar 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 

Usted puede leer todo acerca de las normas de radiodifusión here. También puede usar newaxis más de una vez si es necesario. (por ejemplo, para dividir una matriz de forma (3, 4, 5, 6) por una matriz de forma (3, 5)).

Desde mi comprensión de los documentos, el uso de newaxis + broadcasting también evita cualquier copia de matriz innecesaria.

La indexación, newaxis, etc. se describen con más detalle here ahora. (Documentación reorganizada desde que se publicó esta respuesta por primera vez).

0

creo que se puede conseguir este comportamiento con el comportamiento de difusión habitual de 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]]) 

Si he interpretado correctamente.

Si desea que el otro eje se podría incorporar todo:

> 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, usted no tiene. ese método falla, por ejemplo, con el conjunto de 2 d que di como ejemplo. como resultado, para el ejemplo que te di, puedes hacer c = a/np.apply_along_axis (np.linalg.norm, 1, a) [:, np.newaxis] pero estoy buscando algo más general como la función divide_along_axis() que defino en la pregunta. – user545424

+1

¿Qué hay de la transposición (ver respuesta editada)? O podría definir 'divide_along_axis' transponiendo, dividiendo y luego transponiendo primero. – Owen

+1

Solo agrega un nuevo eje a 1d array. – tillsten

Cuestiones relacionadas