6.12. Odabir i preraspoređivanje¶
Redukcije su sažele polje na skalar ili rezultat nižeg ranga. Odabir pokriva operacije koje biraju koji elementi preživljavaju i gdje završavaju: uvjetni odabir, ograničavanje (clipping), sortiranje, traženje indeksa, preraspoređivanje duž osi.
6.12.1. Uvjetni odabir¶
where() vraća polje koje uzima elemente iz x ondje gdje je uvjet istinit, a iz y inače. Tri operanda se proširuju zajedno:
a = np.array([1, 2, 3, 4, 5], dtype=np.float)
np.where(a < 3, a, 0.0)
# array([1.0, 2.0, 0.0, 0.0, 0.0])
Ovo je pravi alat za „if/else po elementu” bez pisanja Python petlje.
clip() je kratica za maximum(lo, minimum(a, hi)) – zasićuje vrijednosti na raspon:
np.clip(a, 2.0, 4.0)
# array([2.0, 2.0, 3.0, 4.0, 4.0])
maximum() i minimum() uzimaju dva operanda i vraćaju element po element veći / manji:
np.maximum(a, 3.0)
np.minimum(a, np.array([5, 4, 3, 2, 1]))
6.12.2. Traženje indeksa¶
nonzero() vraća koordinate svakog ne-nultog elementa, podijeljene u po jedno polje indeksa za svaku dimenziju. Za 2-D ulaz rezultat je n-torka od dva polja: prvo sadrži indekse redaka, drugo sadrži indekse stupaca. Njihovo uparivanje po stupcima daje (row, col) svake ne-nulte pozicije:
m = np.array([[0, 2, 0],
[3, 0, 0]], dtype=np.float)
np.nonzero(m)
# (array([0, 1], dtype=uint16), array([1, 0], dtype=uint16))
Ne-nulti unosi u m su m[0, 1] = 2 i m[1, 0] = 3. Prvo vraćeno polje [0, 1] daje njihove indekse redaka; drugo [1, 0] daje njihove indekse stupaca. Čitanje dvaju polja jedno uz drugo vraća pozicije (0, 1) i (1, 0).
Dvije redukcije također daju indekse:
argsort()– cjelobrojno polje koje bi sortiralo ulaz duž zadane osi (zadano je posljednja):a = np.array([40, 10, 30, 20], dtype=np.uint8) idx = np.argsort(a) # array([1, 3, 2, 0], dtype=uint16) a[idx] # array([10, 20, 30, 40])
argsortuvijek vraćauint16; polje koje se sortira stoga ne smije imati više od 65.535 elemenata na sortiranoj osi.
bincount() broji pojavljivanja svakog nenegativnog cijelog broja u 1-D uint8 / uint16 ulazu:
histogram = np.bincount(np.array([0, 1, 1, 2, 2, 2], dtype=np.uint8))
# array([1, 2, 3], dtype=uint16)
Korisno za izgradnju histograma pikselskih vrijednosti malih cijelih brojeva bez pisanja Python petlje.
6.12.3. Sortiranje i preraspoređivanje¶
sort() vraća sortiranu kopiju polja duž zadane osi (zadano posljednja). Koristite sort() izravno na polju za inačicu na mjestu (in-place):
np.sort(np.array([3, 1, 2], dtype=np.float))
# array([1.0, 2.0, 3.0])
flip() obrće redoslijed duž zadane osi (svake osi kada axis nije proslijeđen):
np.flip(np.array([1, 2, 3, 4]))
# array([4, 3, 2, 1])
roll() ciklički pomiče elemente za zadani broj. Korisno za implementaciju posmačnog registra u stilu prstenastog međuspremnika:
np.roll(np.array([1, 2, 3, 4]), 1)
# array([4, 1, 2, 3])
take() je eksplicitan oblik naprednog indeksiranja – biranje elemenata na proizvoljnim indeksima:
a = np.array([10, 20, 30, 40, 50], dtype=np.uint8)
np.take(a, [0, 2, 4])
# array([10, 30, 50], dtype=uint8)
6.12.4. Filtriranje i strukturne izmjene¶
compress() je eksplicitan oblik booleovog indeksiranja – vraća isječke a odabrane booleovim uvjetom:
a = np.array([10, 20, 30, 40], dtype=np.uint8)
np.compress(a > 15, a)
# array([20, 30, 40], dtype=uint8)
delete() vraća kopiju s uklonjenim unosima na zadanim indeksima:
a = np.array([10, 20, 30, 40, 50], dtype=np.uint8)
np.delete(a, [1, 3])
# array([10, 30, 50], dtype=uint8)
diff() vraća n-tu diskretnu razliku unaprijed polja duž osi. Koristi se za izračun promjena prvog reda između susjednih uzoraka:
samples = np.array([1, 3, 6, 10, 15], dtype=np.float)
np.diff(samples)
# array([2.0, 3.0, 4.0, 5.0])
6.12.5. Što košta svaka operacija¶
Gotovo svaka funkcija na ovoj stranici vraća svježe alocirano polje. Dva izuzetka:
sort()sortira na mjestu (in-place); slobodna funkcijasort()vraća sortiranu kopiju.take()prihvaća ključnu riječout=za pisanje u međuspremnik koji već postoji.
U petlji koja se izvodi mnogo puta u sekundi, dajte prednost sort() na mjestu i ponovno koristite unaprijed alocirane međuspremnike posvuda drugdje. Same booleove maske alociraju se svaki put kada se usporedba izvede – izgradite masku jednom i ponovno je koristite kroz operacije umjesto da je iznova gradite unutar svake iteracije.