Jak přetvořit pole NumPy v Pythonu

Photo of author

By etechblogcz

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.