V tomto průvodci se detailně seznámíte s funkcí `reshape()` knihovny NumPy, která slouží k transformaci rozměrů NumPy polí, aniž by došlo ke změně samotných dat.
Při práci s NumPy poli se často setkáte s potřebou upravit existující pole do jiného tvaru. Tento proces, známý jako přetvarování, se hodí zejména při víceúrovňovém zpracování dat.
S pomocí funkce `reshape()` knihovny NumPy je tato úprava snadná. Během několika minut si osvojíte její syntaxi a naučíte se, jak přetvářet pole do různých rozměrů.
Co Znamená Přetváření v NumPy Polích?
Během práce s NumPy poli se může objevit potřeba nejprve definovat jednorozměrné pole čísel a následně jej přetvořit do pole o požadovaných rozměrech.
Tento postup je obzvláště užitečný, když rozměry nového pole nejsou předem známy, nebo jsou odvozeny až v průběhu výpočtu. Dále se hodí v případech, kdy specifický krok zpracování vyžaduje, aby vstupní data měla předem definovaný tvar.
Právě v těchto situacích se přetváření stává nepostradatelným nástrojem.
Představte si například vektor – jednorozměrné pole šesti prvků. Tento vektor lze transformovat do polí o rozměrech 2×3, 3×2, 6×1, a dalších.
▶️ Pro bezproblémové sledování příkladů v tomto tutoriálu je nezbytné, abyste měli nainstalovaný Python a knihovnu NumPy. Pokud ještě nemáte NumPy, podívejte se na náš návod k instalaci.
Nyní můžete importovat NumPy pod aliasem `np` použitím příkazu `import numpy as np`.
V následující sekci se podíváme na syntaxi této funkce.
Syntaxe Funkce `reshape()` v NumPy
Následující řádek kódu zobrazuje syntaxi pro použití funkce `reshape()` v NumPy:
np.reshape(arr, newshape, order="C"|'F'|'A')
- `arr` reprezentuje libovolný platný NumPy objekt pole. Jedná se o pole, které se má přetvarovat.
- `newshape` definuje tvar nového pole. Může to být celé číslo nebo n-tice.
- Pokud je `newshape` celé číslo, výsledné pole bude jednorozměrné.
- `order` určuje pořadí, ve kterém se budou číst prvky původního pole.
- Výchozí hodnota je `’C’`, což znamená, že prvky původního pole budou čteny v pořadí podobném indexaci v jazyce C (začínající od 0).
- `’F’` znamená indexaci podobnou Fortranu (začínající od 1). `’A’` čte prvky buď v pořadí podobném C, nebo Fortranu, v závislosti na uspořádání paměti pole `arr`.
A co tedy funkce `np.reshape()` vrací?
Pokud je to možné, vrací přeformátovaný _pohled_ na původní pole. V opačném případě vrací _kopii_ pole.
Jak bylo zmíněno výše, NumPy `reshape()` se snaží vrátit _pohled_ vždy, když je to proveditelné. V ostatních případech vrací _kopii_. Nyní se podíváme na rozdíly mezi _pohledem_ a _kopií_.
Pohled vs. Kopie v NumPy Polích
Jak již název napovídá, _kopie_ je samostatná duplikát původního pole. Jakékoli úpravy provedené v kopii neovlivní původní pole.
Naproti tomu _pohled_ představuje pouze odkaz na přetvarovaný pohled na původní pole. To znamená, že jakákoli změna v _pohledu_ se projeví i v původním poli a naopak.
Použití Funkce `reshape()` pro Přetvoření 1D Pole na 2D Pole
#1. Začněme vytvořením příkladového pole pomocí funkce `np.arange()`.
Potřebujeme pole s 12 čísly v rozsahu od 1 do 12, které pojmenujeme `arr1`. Vzhledem k tomu, že funkce NumPy `arange()` standardně nezahrnuje koncový bod, nastavíme koncovou hodnotu na 13.
Nyní použijeme výše uvedenou syntaxi k přetvarování `arr1` s 12 prvky do 2D pole o rozměrech (4,3). Toto pole nazveme `arr2` a bude mít 4 řádky a 3 sloupce.
import numpy as np arr1 = np.arange(1,13) print("Původní pole, před přetvarováním:n") print(arr1) # Přetvarování pole arr2 = np.reshape(arr1,(4,3)) print("nPřetvarované pole:") print(arr2)
Podívejme se na původní a upravená pole.
Původní pole, před přetvarováním: [ 1 2 3 4 5 6 7 8 9 10 11 12] Přetvarované pole: [[ 1 2 3] [ 4 5 6] [ 7 8 9] [10 11 12]]
Místo předávání pole jako argument funkce `np.reshape()`, lze také volat metodu `.reshape()` přímo na původním poli.
Zavoláním `dir(arr1)` zobrazíte seznam všech dostupných metod a atributů, které lze použít u objektu pole `arr1`.
dir(arr1) # Výstup [ ... ... 'reshape' ... .. ]
Z výše uvedeného výstupu je zřejmé, že `.reshape()` je platná metoda pro použití u existujícího NumPy pole `arr1`.
▶️ Proto můžete k přetvarování NumPy polí využít i následující zjednodušenou syntaxi.
arr.reshape(d0,d1,...,dn) # Kde: # d0, d1,..,dn jsou rozměry přetvarovaného pole # d0 * d1 * ...* dn = N, počet prvků v arr
Pro zbytek tohoto návodu budeme používat tuto syntaxi v našich příkladech.
#2. Pokusme se nyní přetvořit náš vektor s 12 prvky do pole o rozměrech 12 x 1.
import numpy as np arr1 = np.arange(1,13) print("Původní pole, před přetvarováním:n") print(arr1) # Přetvarování pole arr3 = arr1.reshape(12,1) print("nPřetvarované pole:") print(arr3)
Ve výstupu níže můžete vidět, že pole bylo úspěšně přetvarováno.
Původní pole, před přetvarováním: [ 1 2 3 4 5 6 7 8 9 10 11 12] Přetvarované pole: [[ 1] [ 2] [ 3] [ 4] [ 5] [ 6] [ 7] [ 8] [ 9] [10] [11] [12]]
❔ Jak tedy ověříme, zda jsme získali kopii, nebo _pohled_?
K ověření můžeme použít atribut `.base` na vráceném poli.
- Pokud je pole kopií, atribut `.base` bude `None`.
- Pokud je pole _pohledem_, atribut `.base` bude odkazovat na původní pole.
Rychle to ověřme.
arr3.base # Výstup array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
Jak je vidět, atribut `.base` pole `arr3` vrací původní pole. To znamená, že jsme získali _pohled_ na původní pole.
#3. Nyní zkusme přetvořit vektor do dalšího platného pole o rozměrech 2 x 6.
import numpy as np arr1 = np.arange(1,13) print("Původní pole, před přetvarováním:n") print(arr1) # Přetvarování pole arr4 = arr1.reshape(2,6) print("nPřetvarované pole:") print(arr4)
A zde je výstup:
Původní pole, před přetvarováním: [ 1 2 3 4 5 6 7 8 9 10 11 12] Přetvarované pole: [[ 1 2 3 4 5 6] [ 7 8 9 10 11 12]]
V následující sekci se naučíme, jak přetvořit `arr1` do 3D pole.
Použití Funkce `reshape()` pro Přetvoření 1D Pole na 3D Pole
Pro přetvoření `arr1` na 3D pole nastavíme požadované rozměry na (1, 4, 3).
import numpy as np arr1 = np.arange(1,13) print("Původní pole, před přetvarováním:n") print(arr1) # Přetvarování pole arr3D = arr1.reshape(1,4,3) print("nPřetvarované pole:") print(arr3D)
Nyní jsme vytvořili 3D pole se stejnými 12 prvky, které obsahuje i původní pole `arr1`.
Původní pole, před přetvarováním: [ 1 2 3 4 5 6 7 8 9 10 11 12] Přetvarované pole: [[[ 1 2 3] [ 4 5 6] [ 7 8 9] [10 11 12]]]
Jak Ladit Chyby Hodnoty Během Přetvarování
Jak jsme si řekli na začátku, změna tvaru je platná pouze v případě, že součin rozměrů odpovídá celkovému počtu prvků v poli.
import numpy as np arr1 = np.arange(1,13) print("Původní pole, před přetvarováním:n") print(arr1) # Přetvarování pole arr2D = arr1.reshape(4,4) print("nPřetvarované pole:") print(arr2D)
Zde se pokoušíme přetvořit pole o 12 prvcích na pole 4×4, které má 16 prvků. Interpret proto vyvolá chybu hodnoty, jak můžete vidět níže.
Původní pole, před přetvarováním: [ 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 # Přetvarování pole ----> 8 arr2 = arr1.reshape(4,4) 9 print("nPřetvarované pole:") 10 print(arr2) ValueError: cannot reshape array of size 12 into shape (4,4)
Abyste se vyhnuli podobným chybám, můžete použít hodnotu -1, která automaticky odvodí rozměr pro jednu z dimenzí na základě celkového počtu prvků.
Například, pokud znáte předem n – 1 rozměrů, můžete použít -1 k odvození n-tého rozměru v přetvarovaném poli.
Pokud máte pole o 24 prvcích a chcete ho přetvořit do 3D pole, přičemž potřebujete 3 řádky a 4 sloupce, můžete podél třetího rozměru zadat hodnotu -1.
import numpy as np arr1 = np.arange(1,25) print("Původní pole, před přetvarováním:n") print(arr1) # Přetvarování pole arr_res = arr1.reshape(4,3,-1) print("nPřetvarované pole:") print(arr_res) print(f"Tvar arr_res:{arr_res.shape}")
Při kontrole tvaru pole můžete vidět, že přetvarované pole má podél třetího rozměru rozměr 2.
Původní pole, před přetvarováním: [ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24] Přetvarované pole: [[[ 1 2] [ 3 4] [ 5 6]] [[ 7 8] [ 9 10] [11 12]] [[13 14] [15 16] [17 18]] [[19 20] [21 22] [23 24]]] Tvar arr_res:(4, 3, 2)
Tento přístup se hodí zejména při zplošťování pole. Více o tom se dozvíte v následující části.
Použití Funkce `reshape()` pro Zploštění Pole
Občas se může stát, že budete potřebovat přejít z N-rozměrných polí zpět k zploštělému poli. Představte si například, že chcete sloučit obrázek do dlouhého vektoru pixelů.
Projděme si jednoduchý příklad krok za krokem:
- Vytvořte pole s obrázkem ve stupních šedi o rozměrech 3×3, které nazveme `img_arr`, a to s pixely v rozmezí od 0 do 255.
- Dále zploštíme toto pole `img_arr` a vytiskneme zploštělé pole `flat_arr`.
- Pro ověření si také vytiskneme tvary polí `img_arr` a `flat_arr`.
img_arr = np.random.randint(0, 255, (3,3)) print(img_arr) print(f"Tvar img_arr: {img_arr.shape}") flat_arr = img_arr.reshape(-1) print(flat_arr) print(f"Tvar flat_arr: {flat_arr.shape}")
Zde je výstup:
[[195 145 77] [ 63 193 223] [215 43 36]] Tvar img_arr: (3, 3) [195 145 77 63 193 223 215 43 36] Tvar flat_arr: (9,)
Z výše uvedeného výstupu je vidět, že `flat_arr` je 1D vektor hodnot pixelů s 9 prvky.
Shrnutí👩🏫
Je čas si stručně zopakovat, co jsme se naučili.
- Pro přetvarování pole `arr` do tvaru definovaného v parametru `newshape` použijte `np.reshape(arr, newshape)`. `newshape` je n-tice definující rozměry přetvarovaného pole.
- Alternativně můžete pro přetvarování `arr` do tvaru `d0 x d1 x … x dn` použít `arr.reshape(d0, d1, …, dn)`.
- Pro prevenci chyb hodnot při přetvarování nezapomeňte ověřit, zda `d0 * d1 * …* dn = N`, kde `N` je počet prvků v původním poli.
- Pokud chcete, aby se rozměr odvodil automaticky, použijte hodnotu -1 maximálně pro jeden rozměr v novém tvaru.
- A konečně, pro zploštění pole můžete použít `arr.reshape(-1)`.
Nyní, když znáte princip fungování funkce `reshape()` v NumPy, se podívejte, jak funguje funkce `linspace()` v NumPy.
Pokud chcete, můžete si vyzkoušet příklady kódu v Jupyter notebooku. Hledáte-li další vývojová prostředí, prohlédněte si náš průvodce o alternativách Jupyter.