6.11. Redukcije¶
Redukcija sažima polje duž jedne ili više osi zbrajanjem, usrednjavanjem, uzimanjem minimuma i tako dalje. Svaka redukcija je jedan poziv biblioteke nad cijelim poljem, mnogo brži od ekvivalentne Python petlje. numpy pokriva uobičajene:
sum()– zbroj svih elemenatamean()– aritmetička sredina (zbroj podijeljen brojem elemenata)std()– standardna devijacija,ddof=prilagođava djelitelj (N - ddof)median()– srednja vrijednost kada su elementi sortirani (50. percentil)argmin()/argmax()– indeks minimalnog ili maksimalnog elementaall()/any()– redukcije istinitosne vrijednosti nad booleovim poljima
6.11.1. Bez ključne riječi axis¶
Pozvana bez axis=, redukcija vraća skalar koji pokriva cijelo polje:
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. S ključnom riječi axis¶
axis= sažima jednu imenovanu os i ostavlja ostale netaknute. Rezultat je polje za jedan rang nižeg ranga od ulaza:
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
Isto pravilo oblika vrijedi za svaku redukciju: axis=0 sažima prvu os, axis=1 sažima drugu, i tako dalje. Sredina / standardna devijacija duž retka, na primjer, pišu se kao np.mean(m, axis=1) i np.std(m, axis=1). Rezultat ima duljinu druge osi.
Ključna riječ keepdims=True zadržava sažetu os na mjestu s duljinom 1 umjesto da je izbaci. Razlika je važna kada se reducirani rezultat treba ponovno proširiti (broadcast) prema izvornom: keepdims čuva rang, što održava pravila proširivanja usklađenima os po os.
Oduzimanje sredine svakog retka od tog retka kanonska je upotreba:
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
Bez keepdims, np.mean(m, axis=1) vraća 1-D rezultat oblika (3,). Proširivanje (3, 4) - (3,) poravnava (3,) kao (1, 3) nakon dodavanja ranga sprijeda, što je nekompatibilno s (3, 4): posljednje osi se ne podudaraju (4 naspram 3) i nijedna nije 1, pa numpy baca ValueError. keepdims=True je ono što oduzimanje održava valjanim.
6.11.3. Raspored je važan¶
U kombinaciji s rasporedom po recima (row-major) opisanim u Oblik i koraci, redukcija duž posljednje osi najjeftiniji je slučaj. Redukcija prolazi kroz blok podataka u smjeru u kojem je pohranjen, bez skokova iz retka u redak:
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
Kada aplikacija ima izbor kako rasporediti međuspremnik, stavite dugu os zadnju kako bi redukcije duž nje radile u brzom smjeru.
6.11.4. Iterabilni objekti kao ulaz¶
Većina redukcija prihvaća Python iterabilni objekt (list, range, n-torku) umjesto ndarray. Ta pogodnost košta nekoliko mikrosekundi za implicitnu konverziju – što se brzo nakuplja u petlji. Kada se isti podaci reduciraju više puta, izgradite ndarray jednom i proslijedite ga uokolo.