6.3. Taulukoiden luominen

Jokainen esimerkki näiden sivujen lopussa alkaa siitä, että ndarray on jo kädessä. Tämä sivu on luettelo siitä, kuinka tuo taulukko syntyy. Konstruktoreita on neljä perhettä:

  • Python-iteroitavasta – tavanomainen literaali- / lista- / monikkomuoto.

  • Esitäytetty annetulla muodolla – nollat, ykköset, vakioarvo, identiteettimatriisi.

  • Sekvenssinä generoitu – alueeseen perustuvat tai tasavälein sijoitetut arvot.

  • RAM-muistissa jo olevan puskurin käärintä – oheislaitetapaus.

Jokainen konstruktori ottaa dtype=-avainsanan ja oletusarvona on float. Sensoridata haluaa lähes aina pienemmän dtypen kuin oletus.

Jokainen alla oleva esimerkki alkaa näin:

from ulab import numpy as np

6.3.1. Python-iteroitavasta

array() rakentaa ndarray-taulukon mistä tahansa numeroita sisältävästä iteroitavasta:

a = np.array([1, 2, 3, 4])
print(a)

Tuloste:

array([1.0, 2.0, 3.0, 4.0], dtype=float)

Sisäkkäiset iteroitavat tuottavat moniulotteisia taulukoita. Sisempien iteroitavien on oltava kaikki samanpituisia, tai nostetaan ValueError

m = np.array([[1, 2, 3],
              [4, 5, 6]], dtype=np.uint8)

Jo olemassa oleva ndarray on myös kelvollinen syöte; array() kopioi aina. Välttääksesi kopioinnin, kun sitä ei tarvita, käytä asarray()

b = np.asarray(a, dtype=np.float)   # same dtype -> no copy

6.3.2. Esitäytetty annetulla muodolla

Kun kohdemuoto tunnetaan mutta sisältöä ei vielä, varaa puskuri etukäteen ja kirjoita siihen myöhemmin:

  • zeros() – täytetty nollilla.

  • ones() – täytetty ykkösillä.

  • full() – täytetty annetulla arvolla.

  • empty() – alias funktiolle zeros() (ulab ei jätä puskuria alustamattomaksi).

  • eye() – identiteetin kaltainen N-kertaa-M-matriisi, jossa on ykkösiä k:nnella diagonaalilla.

  • diag() – diagonaalimatriisi vektorista tai matriisin diagonaali.

np.zeros((3, 3))                   # 3x3 of zeros
np.ones(5, dtype=np.uint8)         # length-5 vector of ones
np.full((2, 3), 7, dtype=np.int8)  # 2x3, all 7
np.eye(4)                          # 4x4 identity
np.diag([1, 2, 3])                 # 3x3, [1, 2, 3] on the diagonal

shape-argumentti on joko yksittäinen kokonaisluku (1-ulotteiselle taulukolle) tai monikko.

6.3.3. Sekvenssinä generoitu

  • arange() – tasavälein sijoitetut arvot kuten sisäänrakennettu range(), mutta palauttaa aina ndarray-taulukon:

    np.arange(0, 10, 2)            # array([0, 2, 4, 6, 8])
    
  • linspace()num tasavälein sijoitettua pistettä kahden rajan välillä, ylärajan ollessa mukana kun endpoint=True

    np.linspace(0, 1, num=11)      # 0.0, 0.1, ..., 1.0
    
  • logspace() – geometrisesti sijoitetut pisteet. start ja stop ovat eksponentteja, eivät päätepisteitä; tulos kulkee arvosta base ** start arvoon base ** stop

    np.logspace(0, 3, num=4)       # 1.0, 10.0, 100.0, 1000.0
    
  • meshgrid() – rakentaa kaksi koordinaattimatriisia kahdesta 1-ulotteisesta taulukosta, jotta pikselikohtainen funktio f(x, y) voidaan arvioida koko ruudukolle yhdessä vektoroidussa kutsussa. Annettuna pituuden W x-vektori ja pituuden H y-vektori, meshgrid palauttaa kaksi H-kertaa-W-matriisia: X on x-vektori toistettuna jokaisella rivillä alaspäin, Y on y-vektori toistettuna jokaisessa sarakkeessa, joten X[i, j] on x-koordinaatti ja Y[i, j] on rivillä i ja sarakkeessa j olevan solun y-koordinaatti:

    x = np.arange(4)            # [0, 1, 2, 3]
    y = np.arange(3)            # [0, 1, 2]
    X, Y = np.meshgrid(x, y)
    # X = [[0, 1, 2, 3],
    #      [0, 1, 2, 3],
    #      [0, 1, 2, 3]]
    # Y = [[0, 0, 0, 0],
    #      [1, 1, 1, 1],
    #      [2, 2, 2, 2]]
    

    f(X, Y) arvioi sitten funktion ruudukon jokaisessa solussa yhdellä lausekkeella. Esimerkiksi keskipisteestä laskettava etäisyyskartta (H, W)-kehyksen yli on np.sqrt((X - cx)**2 + (Y - cy)**2) meshgrid()-funktion palauttamia matriiseja vastaan.

6.3.4. Yhdistäminen

concatenate() yhdistää taulukkomonikon olemassa olevaa akselia pitkin:

a = np.array([[1, 2], [3, 4]], dtype=np.uint8)
b = np.array([[5, 6]],         dtype=np.uint8)
np.concatenate((a, b), axis=0)
# array([[1, 2], [3, 4], [5, 6]], dtype=uint8)

Kaikkien syötteiden on jaettava sama dtype ja ndim sekä vastattava toisiaan jokaisella muulla akselilla paitsi yhdistettävällä. concatenate() varaa uuden taulukon, joka on tarpeeksi suuri sisältämään jokaisen syötteen, ja kopioi datan siihen, joten se on oikea työkalu jo olemassa olevien taulukoiden kertaluonteiseen yhdistämiseen; se on väärä työkalu suoratoistosilmukan sisällä, jossa kohteen varaaminen etukäteen kerran ja siihen kirjoittaminen siivuosoituksen kautta on oikea malli.

6.3.5. Olemassa olevan puskurin käärintä

Kamerassa hyödyllisin konstruktori on frombuffer(). Se tulkitsee olemassa olevan tavumaisen puskurin uudelleen 1-ulotteiseksi ndarray-taulukoksi kopioimatta ainuttakaan tavua:

buf = bytearray(8)
audio = np.frombuffer(buf, dtype=np.int16)
# 4 int16 samples, sharing memory with buf

audio-taulukon kautta tehdyt kirjoitukset näkyvät buf-puskurissa ja päinvastoin. Valitun dtype-tyypin on jaettava puskurin pituus tasan.

offset= ohittaa puskurin alussa olevan otsikon; count= rajoittaa luettavien alkioiden määrää:

np.frombuffer(buf, dtype=np.uint8, offset=2, count=4)

Tämä on oikea konstruktori aina, kun oheislaite antaa sovellukselle raakapuskurin – ADC-näytteet bytearray-objektissa, SPI-väylältä vedetty hyötykuorma. Oheislaitteen kirjoittamat tavut ovat taulukko.

Kun oheislaite kirjoittaa monitavuisia arvoja tavujärjestyksessä, jota kameran CPU ei natiivisti lue, byteswap() kääntää jokaisen alkion tavujärjestyksen niin, että arvot luetaan oikein. Se palauttaa oletuksena uuden taulukon; inplace=True muokkaa lähdettä paikallaan.

frombuffer() käsittelee vain numpy-toteutuksen itsensä määrittelemät dtype-tyypit. Oheislaitteille, jotka tuottavat 32-bittisiä kokonaislukunäytteitä, from_int32_buffer() ja vastaavat muuntavat float-tyypiksi yhdellä läpikäynnillä.