6.11. Redukciók¶
A redukció egy tömböt egy vagy több tengely mentén összegzéssel, átlagolással, minimum képzésével és így tovább összevon. Minden redukció egyetlen könyvtárhívás a teljes tömbön, ami sokkal gyorsabb, mint a megfelelő Python ciklus. A numpy lefedi a leggyakrabban használtakat:
sum()– az összes elem összegemean()– számtani átlag (az összeg osztva az elemek számával)std()– szórás, addof=állítja az osztót (N - ddof)median()– a középső érték, ha az elemek rendezettek (50. percentilis)argmin()/argmax()– a minimális vagy maximális elem indexe
6.11.1. Az axis kulcsszó nélkül¶
Az axis= nélkül meghívva a redukció a teljes tömböt lefedő skalárt ad vissza:
a = np.array([1, 2, 3, 4], dtype=np.float)
np.sum(a) # 10.0
np.mean(a) # 2.5
np.std(a) # 1.118...
np.median(a) # 2.5
b = np.array([40, 10, 30, 20], dtype=np.float)
np.max(b) # 40.0
np.argmax(b) # 0 (index of the maximum)
6.11.2. Az axis kulcsszóval¶
Az axis= egy megnevezett tengelyt von össze, a többit pedig érintetlenül hagyja. Az eredmény egy a bemenetnél eggyel alacsonyabb rangú tömb:
m = np.arange(12, dtype=np.float).reshape((3, 4))
np.sum(m) # 66.0 - scalar
np.sum(m, axis=0) # length-4 - column sums
np.sum(m, axis=1) # length-3 - row sums
Ugyanez az alakszabály érvényes minden redukcióra: az axis=0 az első tengelyt vonja össze, az axis=1 a másodikat, és így tovább. Az átlag / szórás egy sor mentén például így írható: np.mean(m, axis=1) és np.std(m, axis=1). Az eredmény hossza a másik tengely hossza.
A keepdims=True kulcsszó az összevont tengelyt 1 hosszúsággal a helyén tartja ahelyett, hogy elhagyná. A különbség akkor számít, amikor a redukált eredménynek vissza kell broadcastolódnia az eredeti ellen: a keepdims megőrzi a rangot, ami tengelyről tengelyre összehangoltan tartja a broadcasting szabályokat.
Az egyes sorok átlagának az adott sorból való kivonása a kanonikus felhasználás:
m = np.arange(12, dtype=np.float).reshape((3, 4))
row_means = np.mean(m, axis=1, keepdims=True)
# row_means has shape (3, 1)
centred = m - row_means
# (3, 4) - (3, 1) -> (3, 4), each row centred on its own mean
A keepdims nélkül az np.mean(m, axis=1) egy (3,) alakú 1 dimenziós eredményt ad vissza. A (3, 4) - (3,) broadcastolása a rang elé fűzése után (1, 3) formára igazítja a (3,) alakot, ami nem kompatibilis a (3, 4) alakkal: az utolsó tengelyek eltérnek (4 a 3-mal szemben), és egyik sem 1, így a numpy ValueError hibát vált ki. A keepdims=True az, ami a kivonást érvényben tartja.
6.11.3. Az elrendezés számít¶
A Alak és lépésközök oldalon tárgyalt sorfolytonos elrendezéssel kombinálva az utolsó tengely menti redukció a legolcsóbb eset. A redukció abban az irányban járja be az adatblokkot, ahogyan az tárolva van, sorról sorra ugrálás nélkül:
m = np.arange(2000, dtype=np.float).reshape((2, 1000))
np.sum(m, axis=1) # cheap - long axis is the inner one
np.sum(m, axis=0) # has to jump rows on every step
Amikor az alkalmazás eldöntheti, hogyan rendezzen el egy puffert, tedd a hosszú tengelyt utolsónak, hogy az azon végzett redukciók a gyors irányba fussanak.
6.11.4. Iterálhatók bemenetként¶
A legtöbb redukció elfogad egy Python iterálhatót (egy list, egy range, egy tuple) az ndarray helyett. A kényelem néhány mikroszekundumba kerül az implicit konverzió miatt – ami egy ciklusban gyorsan összeadódik. Amikor ugyanazokat az adatokat többször redukálod, építsd fel az ndarray objektumot egyszer, és add tovább.