2011-08-21 22 views
15

Czy istnieje funkcja numpy do dzielenia tablicy wzdłuż osi z elementami z innej tablicy? Załóżmy na przykład, że mam tablicę a o kształcie (l, m, n) i tablicę b o kształcie (m,); Szukam czegoś, co odpowiada:numpy dzielę wzdłuż osi

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 

Na przykład ta jest przydatna, gdy normalizację tablicę wektorów:

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

Odpowiedz

23

: dzielenie się (L, M, N) przez tablicę (m,), można użyć 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 

można przeczytać o zasadach nadawania here. Możesz również użyć newaxis więcej niż raz, jeśli to konieczne. (na przykład, aby podzielić macierz kształtu (3,4,5,6) przez macierz kształtu (3,5).

Z mojego rozumienia dokumentów, używanie newaxis + broadcast zapobiega również niepotrzebnemu kopiowaniu tablic.

Indeksowanie, newaxis itp. Są teraz opisywane bardziej szczegółowo jako here. (Dokumentacja reorganizowała się od momentu opublikowania tej odpowiedzi).

0

Myślę, że można dostać ten problem ze zwykłym zachowaniem nadawania NumPy za:

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

Jeśli dokonałem prawidłowej interpretacji.

Jeśli chcesz inną oś można transponować wszystko: dla konkretnego przykładu dałeś

> 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

nie, nie masz. ta metoda nie działa na przykład z tablicą 2-d podaną jako przykład. jak się okazuje, dla przykładu dałem ci c = a/np.apply_along_axis (np.linalg.norm, 1, a) [:, np.newaxis], ale szukam czegoś bardziej ogólnego jak funkcja divide_along_axis() i definiuję w pytaniu. – user545424

+1

Co powiecie na transpozycję (patrz poprawiona odpowiedź)? Można też zdefiniować "dzielenie_okresu_osiowego", najpierw transponując, dzieląc, a następnie transponując z powrotem. – Owen

+1

Po prostu dodaj nową oś do tablicy 1d. – tillsten

Powiązane problemy