6.12. Urval och omarrangering¶
Reduktioner kollapsade en array ned till en skalär eller ett resultat av lägre rang. Urval täcker de operationer som väljer vilka element som överlever och var de hamnar: villkorligt val, klippning, sortering, uppslagning av index, omordning längs en axel.
6.12.1. Villkorligt val¶
where() returnerar en array som tar element från x där villkoret är sant och från y annars. De tre operanderna broadcastas tillsammans:
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])
Detta är rätt verktyg för ett ”if/else per element” utan att skriva en Python-loop.
clip() är en förkortning för maximum(lo, minimum(a, hi)) – mätta värdena till ett intervall:
np.clip(a, 2.0, 4.0)
# array([2.0, 2.0, 3.0, 4.0, 4.0])
maximum() och minimum() tar två operander och returnerar elementvis det större / mindre:
np.maximum(a, 3.0)
np.minimum(a, np.array([5, 4, 3, 2, 1]))
6.12.2. Hitta index¶
nonzero() returnerar koordinaterna för varje element som inte är noll, uppdelade i en indexarray per dimension. För 2-D-indata är resultatet en tupel av två arrayer: den första innehåller radindexen, den andra innehåller kolumnindexen. Att para ihop dem kolumnvis ger (row, col) för varje position som inte är noll:
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 element i m som inte är noll är m[0, 1] = 2 och m[1, 0] = 3. Den första returnerade arrayen [0, 1] ger deras radindex; den andra [1, 0] ger deras kolumnindex. Att läsa de två arrayerna sida vid sida återskapar positionerna (0, 1) och (1, 0).
Två reduktioner producerar också index:
argmin()/argmax()– index för det minsta / största elementet.argsort()– en heltalsarray som skulle sortera indata längs den givna axeln (standard är den sista):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])
argsortreturnerar alltiduint16; arrayen som sorteras får därför inte ha fler än 65 535 element på den sorterade axeln.
bincount() räknar förekomster av varje icke-negativt heltal i en 1-D uint8 / uint16-indata:
histogram = np.bincount(np.array([0, 1, 1, 2, 2, 2], dtype=np.uint8))
# array([1, 2, 3], dtype=uint16)
Användbart för att bygga histogram av pixelvärden med små heltal utan att skriva en Python-loop.
6.12.3. Sortering och omordning¶
sort() returnerar en sorterad kopia av arrayen längs den givna axeln (den sista som standard). Använd sort() direkt på arrayen för en version på plats:
np.sort(np.array([3, 1, 2], dtype=np.float))
# array([1.0, 2.0, 3.0])
flip() vänder ordningen längs den givna axeln (varje axel när ingen axis anges):
np.flip(np.array([1, 2, 3, 4]))
# array([4, 3, 2, 1])
roll() förskjuter element cykliskt med det givna antalet. Användbart för att implementera ett skiftregister i ringbuffert-stil:
np.roll(np.array([1, 2, 3, 4]), 1)
# array([4, 1, 2, 3])
take() är den explicita formen av avancerad indexering – plocka element vid godtyckliga index:
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. Filtrering och strukturella ändringar¶
compress() är den explicita formen av boolesk indexering – returnera de delar av a som väljs av det booleska villkoret:
a = np.array([10, 20, 30, 40], dtype=np.uint8)
np.compress(a > 15, a)
# array([20, 30, 40], dtype=uint8)
delete() returnerar en kopia där posterna vid de givna indexen är borttagna:
a = np.array([10, 20, 30, 40, 50], dtype=np.uint8)
np.delete(a, [1, 3])
# array([10, 30, 50], dtype=uint8)
diff() returnerar den n:te diskreta framåtdifferensen av arrayen längs en axel. Används för att beräkna förstaordningsändringar mellan intilliggande sampel:
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. Vad varje operation kostar¶
Nästan varje funktion på denna sida returnerar en nyallokerad array. Två undantag:
sort()sorterar på plats; den fristående funktionensort()returnerar en sorterad kopia.take()accepterar nyckelordetout=för att skriva in i en buffert som redan finns.
I en loop som körs många gånger per sekund, föredra sort() på plats och återanvänd förallokerade buffertar överallt annars. Booleska masker allokeras själva varje gång jämförelsen körs – bygg en mask en gång och återanvänd den över flera operationer i stället för att bygga om den inuti varje iteration.