6.12. Selectare și rearanjare¶
Reducerile comprimau un tablou până la un scalar sau un rezultat de rang mai mic. Selectarea acoperă operațiile care aleg care elemente supraviețuiesc și unde ajung: alegere condiționată, limitare, sortare, căutarea indicilor, reordonarea de-a lungul unei axe.
6.12.1. Alegere condiționată¶
where() returnează un tablou care preia elemente din x acolo unde condiția este adevărată și din y în caz contrar. Cei trei operanzi se difuzează împreună:
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])
Acesta este instrumentul potrivit pentru un „if/else per element” fără a scrie o buclă Python.
clip() este o prescurtare pentru maximum(lo, minimum(a, hi)) – saturează valorile la un interval:
np.clip(a, 2.0, 4.0)
# array([2.0, 2.0, 3.0, 4.0, 4.0])
maximum() și minimum() iau doi operanzi și returnează, element cu element, valoarea mai mare / mai mică:
np.maximum(a, 3.0)
np.minimum(a, np.array([5, 4, 3, 2, 1]))
6.12.2. Găsirea indicilor¶
nonzero() returnează coordonatele fiecărui element diferit de zero, împărțite într-un tablou de indici per dimensiune. Pentru o intrare 2-D, rezultatul este un tuplu de două tablouri: primul conține indicii de rând, al doilea conține indicii de coloană. Împerecherea lor pe coloane dă (row, col) al fiecărei poziții diferite de zero:
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))
Intrările diferite de zero din m sunt m[0, 1] = 2 și m[1, 0] = 3. Primul tablou returnat [0, 1] dă indicii lor de rând; al doilea [1, 0] dă indicii lor de coloană. Citind cele două tablouri unul lângă altul se recuperează pozițiile (0, 1) și (1, 0).
Două reduceri produc, de asemenea, indici:
argmin()/argmax()– indicele celui mai mic / mai mare element.argsort()– un tablou de întregi care ar sorta intrarea de-a lungul axei date (implicit ultima):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])
argsortreturnează întotdeaunauint16; prin urmare, tabloul sortat nu trebuie să aibă mai mult de 65.535 de elemente pe axa sortată.
bincount() numără aparițiile fiecărui întreg nenegativ într-o intrare 1-D uint8 / uint16
histogram = np.bincount(np.array([0, 1, 1, 2, 2, 2], dtype=np.uint8))
# array([1, 2, 3], dtype=uint16)
Util pentru construirea histogramelor de valori de pixeli de tip întreg mic fără a scrie o buclă Python.
6.12.3. Sortare și reordonare¶
sort() returnează o copie sortată a tabloului de-a lungul axei date (implicit ultima). Folosește sort() direct pe tablou pentru o versiune pe loc:
np.sort(np.array([3, 1, 2], dtype=np.float))
# array([1.0, 2.0, 3.0])
flip() inversează ordinea de-a lungul axei date (fiecare axă atunci când nu se transmite niciun axis):
np.flip(np.array([1, 2, 3, 4]))
# array([4, 3, 2, 1])
roll() deplasează ciclic elementele cu numărul dat. Util pentru implementarea unui registru de deplasare în stil ring-buffer:
np.roll(np.array([1, 2, 3, 4]), 1)
# array([4, 1, 2, 3])
take() este forma explicită a indexării avansate (fancy indexing) – alege elemente la indici arbitrari:
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. Filtrare și editări structurale¶
compress() este forma explicită a indexării booleene – returnează feliile din a selectate de condiția booleană:
a = np.array([10, 20, 30, 40], dtype=np.uint8)
np.compress(a > 15, a)
# array([20, 30, 40], dtype=uint8)
delete() returnează o copie cu intrările de la indicii dați eliminate:
a = np.array([10, 20, 30, 40, 50], dtype=np.uint8)
np.delete(a, [1, 3])
# array([10, 30, 50], dtype=uint8)
diff() returnează diferența discretă progresivă de ordinul n a tabloului de-a lungul unei axe. Folosită pentru a calcula modificările de prim ordin între eșantioane adiacente:
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. Cât costă fiecare operație¶
Aproape fiecare funcție de pe această pagină returnează un tablou nou alocat. Două excepții:
sort()sortează pe loc; funcția liberăsort()returnează o copie sortată.take()acceptă un cuvânt-cheieout=pentru a scrie într-un tampon (buffer) care există deja.
Într-o buclă care rulează de multe ori pe secundă, preferă sort() pe loc și reutilizează tampoane prealocate peste tot. Măștile booleene în sine sunt alocate de fiecare dată când rulează comparația – construiește o mască o singură dată și reutilizeaz-o între operații în loc să o reconstruiești în interiorul fiecărei iterații.