U ovom uputstvu naučićete kako da koristite NumPy `reshape()` funkciju za transformaciju oblika NumPy nizova, a da pritom ne menjate izvorne podatke.
Kada radite sa NumPy nizovima, često ćete možda želeti da promenite dimenzije postojećeg niza. Ovo može biti naročito korisno kada u više koraka transformišete podatke.
NumPy `reshape()` funkcija vam omogućava da to lako uradite. U narednim minutima naučićete sintaksu za korišćenje funkcije `reshape()`, kao i kako transformisati nizove u različite dimenzije.
Šta je promena oblika u NumPy nizovima?
Kada radite sa NumPy nizovima, možda ćete prvo želeti da kreirate jednodimenzionalni niz brojeva, a zatim ga transformišete u niz sa željenom dimenzijom.
Ovo je posebno korisno kada dimenzije novog niza nisu unapred poznate ili su određene tokom izvršavanja. Takođe, moguće je da određeni korak obrade podataka zahteva da ulaz bude određenog oblika.
Tu promena oblika dolazi do izražaja.
Na primer, razmotrimo sledeći primer. Imamo vektor, odnosno jednodimenzionalni niz od 6 elemenata. Njega možemo preoblikovati u niz oblika 2×3, 3×2, 6×1 itd.
▶ Da biste pratili primere u ovom uputstvu, potrebno je da imate instalirane Python i NumPy. Ako još uvek nemate NumPy, pogledajte naš vodič za instalaciju NumPy.
Sada možete da importujete NumPy pod pseudonimom `np` izvršavanjem: `import numpy as np`.
Nastavimo sa učenjem sintakse u sledećem odeljku.
Sintaksa NumPy `reshape()` funkcije
Evo sintakse za korišćenje NumPy `reshape()` funkcije:
np.reshape(arr, newshape, order="C"|"F"|"A")
- `arr` je bilo koji validan NumPy niz. To je niz čiji oblik želite da promenite.
- `newshape` je oblik novog niza. To može biti ceo broj ili torka (tuple).
- Kada je `newshape` ceo broj, vraćeni niz je jednodimenzionalan.
- `order` se odnosi na redosled kojim želite da čitate elemente niza koji se transformiše.
- Podrazumevana vrednost je ‘C’, što znači da će se elementi originalnog niza čitati u redosledu sličnom C indeksiranju (počevši od 0).
- ‘F’ označava indeksiranje slično Fortranu (počinje od 1). A ‘A’ čita elemente u C ili Fortran redosledu, u zavisnosti od rasporeda memorije niza `arr`.
Dakle, šta vraća `np.reshape()`?
Vraća transformisan prikaz originalnog niza ako je to moguće. U suprotnom, vraća kopiju niza.
Naveli smo da će NumPy `reshape()` pokušati da vrati prikaz kad god je to moguće. U suprotnom, vraća kopiju. Nastavimo sa objašnjavanjem razlike između prikaza (view) i kopije.
Prikaz naspram kopije NumPy nizova
Kao što samo ime kaže, kopija je duplikat originalnog niza. Bilo kakve izmene na kopiji neće uticati na originalni niz.
S druge strane, prikaz se odnosi na transformisanu prezentaciju originalnog niza. To znači da će svaka izmena na prikazu uticati i na originalni niz i obrnuto.
Korišćenje NumPy `reshape()` za promenu oblika 1D niza u 2D niz
#1. Počnimo sa kreiranjem primera niza korišćenjem `np.arange()` funkcije.
Potreban nam je niz od 12 brojeva, od 1 do 12, koji ćemo nazvati `arr1`. Pošto NumPy `arange()` funkcija podrazumevano isključuje krajnju tačku, postavićemo zaustavnu vrednost na 13.
Sada koristimo gore navedenu sintaksu i transformišemo `arr1` sa 12 elemenata u 2D niz oblika (4,3). Nazvaćemo ga `arr2` sa 4 reda i 3 kolone.
import numpy as np
arr1 = np.arange(1,13)
print("Originalni niz, pre transformacije:\n")
print(arr1)
# Transformacija niza
arr2 = np.reshape(arr1,(4,3))
print("\nTransformisani niz:")
print(arr2)
Pogledajmo originalne i transformisane nizove.
Originalni niz, pre transformacije:
[ 1 2 3 4 5 6 7 8 9 10 11 12]
Transformisani niz:
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
Umesto prosleđivanja niza kao argumenta funkciji `np.reshape()`, možete takođe pozvati metodu `.reshape()` nad originalnim nizom.
Možete pokrenuti `dir(arr1)` i dobićete listu svih mogućih metoda i atributa koje možete koristiti nad objektom niza `arr1`.
dir(arr1)
# Izlaz
[
...
...
'reshape'
...
..
]
U gornjoj ćeliji koda možete videti da je `.reshape()` validna metoda za korišćenje nad postojećim NumPy nizom `arr1`.
▶ Dakle, možete koristiti i sledeću pojednostavljenu sintaksu za transformaciju NumPy nizova.
arr.reshape(d0,d1,...,dn)
# gde:
# d0, d1,..,dn su dimenzije transformisanog niza
# d0 * d1 * ...* dn = N, broj elemenata u arr
Za ostatak ovog uputstva, koristićemo ovu sintaksu u našim primerima.
#2. Pokušajmo da transformišemo naš vektor od 12 elemenata u niz 12 x 1.
import numpy as np
arr1 = np.arange(1,13)
print("Originalni niz, pre transformacije:\n")
print(arr1)
# Transformacija niza
arr3 = arr1.reshape(12,1)
print("\nTransformisani niz:")
print(arr3)
U donjem izlazu možete videti da je niz transformisan kako je traženo.
Originalni niz, pre transformacije:
[ 1 2 3 4 5 6 7 8 9 10 11 12]
Transformisani niz:
[[ 1]
[ 2]
[ 3]
[ 4]
[ 5]
[ 6]
[ 7]
[ 8]
[ 9]
[10]
[11]
[12]]
❔ Dakle, kako da proverimo da li smo dobili kopiju ili prikaz?
Da biste to proverili, možete pozvati atribut `base` na vraćenom nizu.
- Ako je niz kopija, atribut `base` će biti `None`.
- Ako je niz prikaz, atribut `base` će biti originalni niz.
Brzo ovo proverimo.
arr3.base
# Izlaz
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
Kao što vidite, atribut `base` za `arr3` vraća originalni niz. To znači da smo dobili prikaz originalnog niza.
#3. Sada, pokušajmo da transformišemo vektor u drugi validan niz 2 x 6.
import numpy as np
arr1 = np.arange(1,13)
print("Originalni niz, pre transformacije:\n")
print(arr1)
# Transformacija niza
arr4 = arr1.reshape(2,6)
print("\nTransformisani niz:")
print(arr4)
A evo i izlaza:
Originalni niz, pre transformacije:
[ 1 2 3 4 5 6 7 8 9 10 11 12]
Transformisani niz:
[[ 1 2 3 4 5 6]
[ 7 8 9 10 11 12]]
U sledećem odeljku, transformisaćemo `arr1` u 3D niz.
Korišćenje NumPy `reshape()` za transformaciju 1D niza u 3D niz
Da bismo transformisali `arr1` u 3D niz, postavimo željene dimenzije na (1, 4, 3).
import numpy as np
arr1 = np.arange(1,13)
print("Originalni niz, pre transformacije:\n")
print(arr1)
# Transformacija niza
arr3D = arr1.reshape(1,4,3)
print("\nTransformisani niz:")
print(arr3D)
Sada smo kreirali 3D niz od istih 12 elemenata kao u originalnom nizu `arr1`.
Originalni niz, pre transformacije:
[ 1 2 3 4 5 6 7 8 9 10 11 12]
Transformisani niz:
[[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]]
Kako otkloniti greške tipa `ValueError` tokom transformacije oblika
Ako se sećate sintakse, transformacija je validna samo kada je proizvod dimenzija jednak broju elemenata u nizu.
import numpy as np
arr1 = np.arange(1,13)
print("Originalni niz, pre transformacije:\n")
print(arr1)
# Transformacija niza
arr2D = arr1.reshape(4,4)
print("\nTransformisani niz:")
print(arr2D)
Ovde pokušavate da transformišete niz od 12 elemenata u niz 4×4 sa 16 elemenata. Interpretator izbacuje grešku `ValueError`, kao što se vidi ispod.
Originalni niz, pre transformacije:
[ 1 2 3 4 5 6 7 8 9 10 11 12]
-----------------------------------------------------------
ValueError
Traceback (most recent call last)
<ipython-input-11-63552bcc8c37> in <module>()
6
7 # Transformacija niza
----> 8 arr2 = arr1.reshape(4,4)
9 print("\nTransformisani niz:")
10 print(arr2)
ValueError: cannot reshape array of size 12 into shape (4,4)
Da biste izbegli ovakve greške, možete koristiti -1 da automatski zaključite oblik za jednu od dimenzija, na osnovu ukupnog broja elemenata.
Na primer, ako unapred znate n-1 dimenziju, možete koristiti -1 da biste zaključili n-tu dimenziju u transformisanom nizu.
Ako imate niz od 24 elementa i želite da ga transformišete u 3D niz. Pretpostavimo da vam trebaju 4 reda i 3 kolone. Možete proslediti vrednost -1 duž treće dimenzije.
import numpy as np
arr1 = np.arange(1,25)
print("Originalni niz, pre transformacije:\n")
print(arr1)
# Transformacija niza
arr_res = arr1.reshape(4,3,-1)
print("\nTransformisani niz:")
print(arr_res)
print(f"Oblik arr_res:{arr_res.shape}")
Kada proverite oblik niza, možete videti da transformisani niz ima oblik 2 duž treće dimenzije.
Originalni niz, pre transformacije:
[ 1 2 3 4 5 6 7 8 9 10 11 12
13 14 15 16 17 18 19 20 21 22 23 24]
Transformisani niz:
[[[ 1 2]
[ 3 4]
[ 5 6]]
[[ 7 8]
[ 9 10]
[11 12]]
[[13 14]
[15 16]
[17 18]]
[[19 20]
[21 22]
[23 24]]]
Oblik arr_res:(4, 3, 2)
Ovo je naročito korisno za izravnavanje niza. O tome ćete naučiti u sledećem odeljku.
Korišćenje NumPy `reshape()` za izravnavanje niza
Postoje situacije kada ćete morati da se vratite sa N-dimenzionalnih nizova na izravnat niz. Pretpostavimo da želite da izravnate sliku u dugačak vektor piksela.
Hajde da kodiramo jednostavan primer koristeći sledeće korake:
- Generišite niz slika 3 x 3 u sivim tonovima, `img_arr`, sa pikselima u opsegu od 0 do 255.
- Zatim izravnajte ovaj `img_arr` i odštampajte izravnat niz, `flat_arr`.
- Takođe, odštampajte oblike `img_arr` i `flat_arr` da biste ih proverili.
img_arr = np.random.randint(0, 255, (3,3))
print(img_arr)
print(f"Oblik img_arr: {img_arr.shape}")
flat_arr = img_arr.reshape(-1)
print(flat_arr)
print(f"Oblik flat_arr: {flat_arr.shape}")
Evo izlaza:
[[195 145 77]
[ 63 193 223]
[215 43 36]]
Oblik img_arr: (3, 3)
[195 145 77 63 193 223 215 43 36]
Oblik flat_arr: (9,)
U gornjoj ćeliji koda možete videti da je `flat_arr` 1D vektor vrednosti piksela sa 9 elemenata.
Zaključak 👩🏫
Vreme je da brzo pregledamo ono što smo naučili.
- Koristite `np.reshape(arr, newshape)` da biste transformisali oblik `arr` u oblik naveden u `newshape`. `newshape` je torka (tuple) koja određuje dimenzije transformisanog niza.
- Alternativno, koristite `arr.reshape(d0, d1, …, dn)` da biste transformisali oblik `arr` da bude d0 x d1 x … x dn.
- Proverite da li je d0 * d1 * …* dn = N, broj elemenata u originalnom nizu, da biste izbegli greške tipa `ValueError` tokom transformacije oblika.
- Koristite -1 za najviše jednu dimenziju u novom obliku ako želite da se dimenzija automatski zaključi.
- Na kraju, možete koristiti `arr.reshape(-1)` da izravnate niz.
Sada kada znate kako da koristite NumPy `reshape()`, naučite kako funkcioniše NumPy `linspace()` funkcija.
Možete isprobati primere koda u Jupyter svesci ako želite. Ako tražite druga razvojna okruženja, pogledajte naš vodič o Jupyter alternativama.