6.12. Selectie en herschikking#
Reducties vouwden een array samen tot een scalair of een resultaat met lagere rang. Selectie dekt de bewerkingen die kiezen welke elementen overleven en waar ze terechtkomen: voorwaardelijke keuze, afkappen, sorteren, indices opzoeken, herordenen langs een as.
6.12.1. Voorwaardelijke keuze#
where() geeft een array terug die elementen uit x neemt waar de voorwaarde waar is en anders uit y. De drie operanden broadcasten samen:
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])
Dit is het juiste gereedschap voor een “if/else per element” zonder een Python-lus te schrijven.
clip() is een afkorting voor maximum(lo, minimum(a, hi)) – verzadig de waarden tot een bereik:
np.clip(a, 2.0, 4.0)
# array([2.0, 2.0, 3.0, 4.0, 4.0])
maximum() en minimum() nemen twee operanden en geven elementsgewijs de grotere / kleinere terug:
np.maximum(a, 3.0)
np.minimum(a, np.array([5, 4, 3, 2, 1]))
6.12.2. Indices vinden#
nonzero() geeft de coördinaten terug van elk niet-nul element, opgesplitst in één index-array per dimensie. Voor een 2-D-invoer is het resultaat een tuple van twee arrays: de eerste bevat de rij-indices, de tweede bevat de kolom-indices. Door ze kolomsgewijs te koppelen krijg je de (row, col) van elke niet-nul positie:
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))
De niet-nul elementen in m zijn m[0, 1] = 2 en m[1, 0] = 3. De eerste teruggegeven array [0, 1] geeft hun rij-indices; de tweede [1, 0] geeft hun kolom-indices. Door de twee arrays naast elkaar te lezen, herstel je de posities (0, 1) en (1, 0).
Twee reducties produceren ook indices:
argmin()/argmax()– index van het kleinste / grootste element.argsort()– een geheeltallige array die de invoer langs de gegeven as zou sorteren (standaard de laatste):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])
argsortgeeft altijduint16terug; de te sorteren array mag daarom niet meer dan 65.535 elementen op de gesorteerde as hebben.
bincount() telt het aantal voorkomens van elk niet-negatief geheel getal in een 1-D uint8 / uint16-invoer:
histogram = np.bincount(np.array([0, 1, 1, 2, 2, 2], dtype=np.uint8))
# array([1, 2, 3], dtype=uint16)
Handig om histogrammen van pixelwaarden met kleine gehele getallen te bouwen zonder een Python-lus te schrijven.
6.12.3. Sorteren en herordenen#
sort() geeft een gesorteerde kopie van de array langs de gegeven as terug (standaard de laatste). Gebruik sort() rechtstreeks op de array voor een in-place versie:
np.sort(np.array([3, 1, 2], dtype=np.float))
# array([1.0, 2.0, 3.0])
flip() keert de volgorde langs de gegeven as om (elke as wanneer er geen axis wordt meegegeven):
np.flip(np.array([1, 2, 3, 4]))
# array([4, 3, 2, 1])
roll() verschuift elementen cyclisch met het gegeven aantal. Handig voor het implementeren van een schuifregister in ringbufferstijl:
np.roll(np.array([1, 2, 3, 4]), 1)
# array([4, 1, 2, 3])
take() is de expliciete vorm van fancy indexing – kies elementen op willekeurige indices:
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. Filteren en structurele bewerkingen#
compress() is de expliciete vorm van booleaanse indexing – geef de segmenten van a terug die door de booleaanse voorwaarde zijn geselecteerd:
a = np.array([10, 20, 30, 40], dtype=np.uint8)
np.compress(a > 15, a)
# array([20, 30, 40], dtype=uint8)
delete() geeft een kopie terug waarin de elementen op de gegeven indices zijn verwijderd:
a = np.array([10, 20, 30, 40, 50], dtype=np.uint8)
np.delete(a, [1, 3])
# array([10, 30, 50], dtype=uint8)
diff() geeft het n-de discrete voorwaartse verschil van de array langs een as terug. Gebruikt om eerste-orde veranderingen tussen aangrenzende monsters te berekenen:
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. Wat elke bewerking kost#
Bijna elke functie op deze pagina geeft een vers toegewezen array terug. Twee uitzonderingen:
sort()sorteert in-place; de vrije functiesort()geeft een gesorteerde kopie terug.take()accepteert eenout=-trefwoord om in een al bestaande buffer te schrijven.
Geef in een lus die vele keren per seconde draait de voorkeur aan de in-place sort() en hergebruik overal elders vooraf toegewezen buffers. Booleaanse maskers zelf worden elke keer dat de vergelijking draait toegewezen – bouw een masker eenmalig en hergebruik het over bewerkingen heen in plaats van het binnen elke iteratie opnieuw op te bouwen.