6.12. Výběr a přeuspořádání¶
Redukce sbalily pole na skalár nebo výsledek nižšího řádu. Výběr pokrývá operace, které vybírají, které prvky přežijí a kam skončí: podmíněná volba, oříznutí, řazení, vyhledávání indexů, přeuspořádání podél osy.
6.12.1. Podmíněná volba¶
where() vrací pole, které přebírá prvky z x tam, kde je podmínka pravdivá, a z y jinak. Tyto tři operandy se broadcastují dohromady:
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])
To je správný nástroj pro „if/else na každý prvek“ bez psaní smyčky v Pythonu.
clip() je zkratka pro maximum(lo, minimum(a, hi)) – nasytí hodnoty do daného rozsahu:
np.clip(a, 2.0, 4.0)
# array([2.0, 2.0, 3.0, 4.0, 4.0])
maximum() a minimum() přijímají dva operandy a vrací po prvcích větší / menší hodnotu:
np.maximum(a, 3.0)
np.minimum(a, np.array([5, 4, 3, 2, 1]))
6.12.2. Hledání indexů¶
nonzero() vrací souřadnice každého nenulového prvku rozdělené do jednoho indexového pole na dimenzi. Pro dvourozměrný vstup je výsledkem n-tice dvou polí: první obsahuje indexy řádků, druhé indexy sloupců. Jejich spárování po sloupcích dává (row, col) každé nenulové pozice:
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))
Nenulové položky v m jsou m[0, 1] = 2 a m[1, 0] = 3. První vrácené pole [0, 1] udává jejich indexy řádků; druhé [1, 0] udává jejich indexy sloupců. Čtení obou polí vedle sebe obnovuje pozice (0, 1) a (1, 0).
Indexy produkují i dvě redukce:
argsort()– celočíselné pole, které by seřadilo vstup podél dané osy (výchozí je poslední):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])
argsortvždy vracíuint16; řazené pole proto nesmí mít na řazené ose více než 65 535 prvků.
bincount() počítá výskyty každého nezáporného celého čísla v jednorozměrném vstupu typu uint8 / uint16
histogram = np.bincount(np.array([0, 1, 1, 2, 2, 2], dtype=np.uint8))
# array([1, 2, 3], dtype=uint16)
Užitečné pro vytváření histogramů hodnot pixelů s malými celými čísly bez psaní smyčky v Pythonu.
6.12.3. Řazení a přeuspořádání¶
sort() vrací seřazenou kopii pole podél dané osy (ve výchozím nastavení poslední). Pro variantu na místě použijte sort() přímo na poli:
np.sort(np.array([3, 1, 2], dtype=np.float))
# array([1.0, 2.0, 3.0])
flip() obrací pořadí podél dané osy (každé osy, když není axis předáno):
np.flip(np.array([1, 2, 3, 4]))
# array([4, 3, 2, 1])
roll() cyklicky posouvá prvky o daný počet. Užitečné pro implementaci posuvného registru ve stylu kruhového bufferu:
np.roll(np.array([1, 2, 3, 4]), 1)
# array([4, 1, 2, 3])
take() je explicitní forma pokročilého indexování (fancy indexing) – výběr prvků na libovolných indexech:
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. Filtrování a strukturální úpravy¶
compress() je explicitní forma logického indexování – vrací řezy pole a vybrané logickou podmínkou:
a = np.array([10, 20, 30, 40], dtype=np.uint8)
np.compress(a > 15, a)
# array([20, 30, 40], dtype=uint8)
delete() vrací kopii s odstraněnými položkami na daných indexech:
a = np.array([10, 20, 30, 40, 50], dtype=np.uint8)
np.delete(a, [1, 3])
# array([10, 30, 50], dtype=uint8)
diff() vrací n-tou diskrétní dopřednou diferenci pole podél osy. Používá se k výpočtu změn prvního řádu mezi sousedními vzorky:
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. Kolik každá operace stojí¶
Téměř každá funkce na této stránce vrací nově alokované pole. Dvě výjimky:
sort()řadí na místě; volná funkcesort()vrací seřazenou kopii.take()přijímá klíčové slovoout=pro zápis do již existujícího bufferu.
Ve smyčce, která běží mnohokrát za sekundu, dejte přednost sort() na místě a všude jinde znovu využívejte předem alokované buffery. Logické masky se samy alokují pokaždé, když proběhne porovnání – vytvořte masku jednou a využívejte ji napříč operacemi, místo abyste ji znovu vytvářeli uvnitř každé iterace.