numpy разделить вдоль оси
есть ли функция numpy для разделения массива вдоль оси с элементами из другого массива? Например, предположим, что у меня есть array a С формой (l,m,n) и массивом b С формой (m,); я ищу что-то эквивалентное:
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
например, это полезно при нормализации массив векторов:
>>> 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.])
2 ответов
для конкретного примера, который вы дали: разделив массив (l,m,n) на (m,), вы можете использовать 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
вы можете прочитать все о правилах вещания здесь. Вы также можете использовать newaxis более одного раза, если это необходимо. (например, разделить массив shape (3,4,5,6) на массив shape (3,5)).
из моего понимания документов, использование newaxis + broadcasting позволяет также избежать ненужного копирования массива.
индексирование, newaxis etc описаны более полно здесь сейчас. (Документация реорганизована с момента первого опубликования этого ответа).
Я думаю, вы можете получить это поведение с обычным поведением вещания 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]])
Если я правильно истолковал.
Если вы хотите другую ось, вы можете перенести все:
> 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.])