6.6. Indeksointi ja viipalointi¶
ndarray-taulukkoa osoitetaan neljällä tavalla: yksittäisillä indekseillä, viipaleilla, totuusarvomaskeilla ja kunkin sijoitusmuodoilla.
6.6.1. Yksittäiset alkiot¶
Hakasulkeindeksointi palauttaa arvon annetussa sijainnissa:
a = np.arange(10, dtype=np.uint8)
print(a[0], a[-1]) # 0 9
print(a[1], a[-2]) # 1 8
Negatiiviset indeksit lasketaan lopusta, samoin kuin Python-list:lle. Sallitun alueen ulkopuolinen indeksi nostaa IndexError-poikkeuksen.
Korkeamman asteen taulukoissa jokainen akseli ottaa indeksin. Indeksit menevät yhden hakasulkuparin sisään pilkuilla erotettuina:
m = np.arange(9, dtype=np.uint8).reshape((3, 3))
print(m[1, 1]) # 4
print(m[2, 0]) # 6
Kun indeksejä annetaan vähemmän kuin akseleita, indeksoimattomat akselit jäävät ennalleen. Tuloksena on asteeltaan redusoitu näkymä lähteeseen:
print(m[0]) # the first row, as a 1-D view of m
6.6.2. Viipaleet¶
Viipale start:stop:step palauttaa näkymän taulukkoon. Näkymä jakaa taustalla olevan datapuskurin lähteen kanssa; näkymän kautta kirjoittaminen kirjoittaa lähteeseen:
a = np.arange(10, dtype=np.uint8)
v = a[::2] # array([0, 2, 4, 6, 8], dtype=uint8)
v[0] = 99
print(a)
# array([99, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=uint8)
Kun tarvitaan riippumaton puskuri, copy() tuottaa sellaisen eksplisiittisesti.
Viipalointi laajenee luonnostaan korkeampiin ulottuvuuksiin. Jokainen akseli ottaa oman viipaleensa:
m = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]], dtype=np.uint8)
m[0] # first row
m[0, :2] # first two elements of row 0
m[:, 0] # column 0 (still 2-D in ulab)
m[-1] # last row
m[::2, ::2] # every other row, every other column
Kokonaisluvun (yksittäinen indeksi, pudottaa akselin) ja viipaleen (säilyttää akselin) sekoittaminen on sallittua, ja näin yksittäisen rivin / yksittäisen sarakkeen haku tavallisesti kirjoitetaan.
6.6.3. Totuusarvomaskit¶
Lähteen kanssa samanmuotoinen totuusarvotaulukko valitsee alkiot, joissa maski on True. Totuusarvoindeksointi toimii tällä hetkellä 1-ulotteisilla taulukoilla; korkeamman asteen syötteet nostavat NotImplementedError-poikkeuksen:
a = np.arange(9, dtype=np.float)
mask = a < 5
print(a[mask])
Tuloste:
array([0.0, 1.0, 2.0, 3.0, 4.0], dtype=float)
Maski on tavallinen bool-ndarray, joten mikä tahansa sellaisen tuottava lauseke toimii:
b = np.array([4, 4, 4, 3, 3, 3, 13, 13, 13], dtype=np.uint8)
a = np.arange(9, dtype=np.uint8)
print(a[a * a > np.sin(b) * 100.0])
Totuusarvoindeksointi palauttaa kopion. Valitut alkiot sijaitsevat niissä sijainneissa, joissa maski on True – ei säännöllisellä askelvälillä lähteen läpi – joten ei ole kuvaajaa, jota näkymä voisi käyttää niiden osoittamiseen, ja tulos materialisoidaan omaan puskuriinsa.
6.6.4. Kokonaislukutaulukolla indeksointi¶
Indeksilistan tai -taulukon välittäminen hakasulkeissa poimii nuo alkiot yhdellä askeleella:
a = np.array([10, 20, 30, 40, 50], dtype=np.uint8)
a[[0, 2, 4]]
# array([10, 30, 50], dtype=uint8)
Tulos on kopio; poimitut alkiot eivät enää jaa muistia lähteen kanssa. Sama muoto toimii sijoituksen vasemmalla puolella:
a[[0, 2, 4]] = 0
# array([0, 20, 0, 40, 0], dtype=uint8)
take() (käsitelty sivulla Valinta ja uudelleenjärjestely) on saman operaation funktiomuoto ja hyväksyy out=-avainsanan varauksettomaan käyttöön suoratoistosilmukassa.
6.6.5. Viipalesijoitus¶
Viipaleet ja maskit esiintyvät sijoituksen vasemmalla puolella aivan kuten oikeallakin. Oikea puoli voi olla skalaari, toinen taulukko tai näkymä:
m = np.zeros((3, 3), dtype=np.uint8)
m[0] = 1 # whole row 0 set to 1
m[:, 2] = 3 # whole column 2 set to 3
m[1, 1:3] = [7, 8] # row 1, columns 1 and 2
Totuusarvomaskit vasemmalla puolella korvaavat ehdon täyttävät alkiot:
a = np.arange(9, dtype=np.uint8)
a[a < 3] = 99
# array([99, 99, 99, 3, 4, 5, 6, 7, 8], dtype=uint8)
a = np.arange(9, dtype=np.uint8)
b = np.array(range(9)) + 12
a[b < 15] = b[b < 15]
# array([12, 13, 14, 3, 4, 5, 6, 7, 8], dtype=uint8)
6.6.6. Miksi viipalesijoituksella on merkitystä kamerassa¶
Viipalesijoitus kirjoittaa jo olemassa olevan taulukon kautta. Uutta taulukkoa ei varata. Siinä on ero seuraavien välillä:
out = a + b # makes a new array the size of a
out = out * 2 # makes another new array
ja:
out[:] = a # writes into the existing out
out += b # in place
out *= 2 # in place
Ensimmäinen versio pyytää kameralta kahden uuden taulukon verran RAM-muistia; toinen versio ei pyydä mitään. Mikrokontrollerissa, jossa RAM on rajallinen, tuo ero on usein ero mukavasti toimivan skriptin ja muistinsa loppuun käyttävän skriptin välillä.
Sivu Suorituskyky käsittelee kuviota yksityiskohtaisesti. Tärkeä sääntö toistaiseksi on, että viipalesijoitus, paikalla muokkaavat aritmeettiset operaattorit (+=, *=, …) ja universaalien funktioiden out=-avainsana ovat ne kolme työkalua, jotka tekevät varauksettomat päivitykset mahdollisiksi.