Na předchozí článek pojednávající o integrovaných vývojových prostředích, v němž jsme se zmiňovali především o IPythonu a taktéž o IPython Notebooku, dnes tematicky navážeme, protože si ukážeme, jakým způsobem je možné využít IPython Notebook společně s knihovnou Numpy. Tyto dva nástroje, pokud jsou navíc v případě potřeby doplněny o knihovnu SciPy a Matplotlib, mohou v mnoha oblastech zdárně konkurovat i komerčním nástrojům typu Matlab či Maple.

Obsah

1. Integrovaná vývojová prostředí ve Fedoře: praktické použití IPython Notebooku a knihovny Numpy

2. Základy, na nichž je postavena knihovna Numpy

3. Datové typy prvků, z nichž jsou tvořena pole

4. Konstruktory polí

5. Konstruktor numpy.zeros

6. Konstruktor numpy.ones

7. Funkce numpy.arange

8. Funkce numpy.linspace

9. Přetypování všech prvků v poli

10. Zjištění tvaru pole pomocí funkce numpy.shape

11. Změna tvarů polí s využitím funkce numpy.reshape

12. Vliv nepovinného parametru „order“ na (zdánlivou) změnu tvaru pole

13. Předchozí části seriálu

14. Odkazy na Internetu

1. Integrovaná vývojová prostředí ve Fedoře: praktické použití IPythonu a knihovny Numpy

V minulé části seriálu o integrovaných vývojových prostředích, která jsou dostupná (nejenom) pro vývojáře pracující ve Fedoře, jsme se zaměřili na popis nástrojů nazvaných IPython a IPython Notebook. Připomeňme si ve stručnosti, že se sice nejedná o „klasická“ integrovaná vývojová prostředí typu Eclipse či Visual Studio, ale o nástroje, které díky použití smyčky REPL (IPython) či konceptu takzvaných diářů (IPython Notebook) umožňují, aby uživatelé vytvářeli aplikace či jen prováděli různé výpočty interaktivním způsobem, tj. dialogem mezi uživatelem a systémem. Takový způsob práce se může hodit například při řešení různých problémů z oblasti numerické matematiky, zpracování signálů, statistické výpočty apod. V dnešní části se zaměříme na popis použití knihovny Numpy, které se elegantně podařilo spojit dva světy – svět Pythonu s jeho „příjemnou“ a přehlednou syntaxí a svět numerické matematiky a výpočtů s maticemi, který se nejenom z historických důvodů vždy zaměřoval na použití Fortranu a částečně i programovacího jazyka C.

07

Obrázek 1: IPython je možné ovládat z terminálu (což je základní možnost dostupná ve všech systémech).

Dnes se budeme zabývat především těmi funkcemi a objekty, které jsou dostupné z hlavního balíčku knihovny Numpy. Ve skutečnosti však v této knihovně nalezneme i několik zajímavých a mnohdy velmi užitečných podbalíčků, jejichž jména a stručný popis jsou vypsány v tabulce pod tímto odstavcem:

Řádek Jméno podbalíčku Stručný popis
1 doc obsahuje dokumentaci ke knihovně i k základním konstrukcím a operacím
2 lib základní funkce používané i některými dalšími podbalíčky
3 random funkce pro využití generátorů pseudonáhodných číselných hodnot
4 linalg funkce z oblasti lineární algebry (bude popsáno příště)
5 fft rychlá Fourierova transformace a pomocné funkce (bude popsáno příště)
6 polynomial funkce pro práci s polynomy (taktéž bude popsáno příště)
7 testing nástroje pro psaní testů
8 f2py (jednosměrné) rozhraní mezi Fortranem a Pythonem
9 distutils další pomocné nástroje, které přímo nesouvisí s výpočty nad vektory a maticemi, ale se způsobem balíčkování

17

Obrázek 2: Alternativně je možné použít textově-grafickou Qt Consoli.

2. Základy, na nichž je postavena knihovna Numpy

Funkce a objekty nabízené knihovnou Numpy se sice volají přímo z Pythonu, ve skutečnosti se však interní datové struktury dosti podstatným způsobem odlišují od datových struktur využívaných samotným Pythonem. V knihovně Numpy tvoří základ datová struktura nazvaná ndarray, která reprezentuje pole o prakticky libovolném počtu dimenzí (ostatně „nd“ ve jménu „ndarray“ značí N-dimensional). Tato pole se liší od běžných seznamů či n-tic v Pythonu, protože ndarray jsou homogenní datovou strukturou: všechny prvky totiž mají shodný typ a navíc všechny prvky leží za sebou, zatímco seznamy v Pythonu jsou měnitelné (prvky lze přidávat a odebírat) a obecně nehomogenní (každý prvek může mít odlišný datový typ). Za tuto velkou flexibilitu se samozřejmě platí, a to jak většími nároky na operační paměť (reference na objekty), tak i pomalejším zpracováním.

18

Obrázek 3: Bublinová nápověda je jednou z vylepšení Qt Console oproti klasickému interaktivnímu interpretru.

3. Datové typy prvků, z nichž jsou tvořena pole

Při vytváření polí typu ndarray, ať již se jedná o vektory, matice či o pole s větším množstvím dimenzí, lze specifikovat datový typ všech prvků a dokonce i uspořádání prvků v paměti (buď podle zvyklostí jazyka Fortran nebo jazyka C). Podívejme se nyní na tabulku, v níž jsou vypsány možné typy prvků polí ndarray:

Řádek Typ Formát Rozsah Jednoznakový kód
1 bool uloženo po bajtech True/False '?'
2 int8 celočíselný se znaménkem -128..127 'b'
3 int16 celočíselný se znaménkem -32768..32767 'h'
4 int32 celočíselný se znaménkem -2147483648..2147483647 'i'
5 int64 celočíselný se znaménkem -9223372036854775808..9223372036854775807 'l'
6 uint8 celočíselný bez znaménka 0..255 'B'
7 uint16 celočíselný bez znaménka 0..65535 'H'
8 uint32 celočíselný bez znaménka 0..4294967295 'I'
9 uint64 celočíselný bez znaménka 0..18446744073709551615 'L'
10 float16 plovoucí řádová čárka poloviční přesnost (half) 'e'
11 float32 plovoucí řádová čárka jednoduchá přesnost (single) 'f'
12 float64 plovoucí řádová čárka dvojitá přesnost (double) 'd'
13 complex64 komplexní číslo (dvojice) 2×float32 'F'
14 complex128 komplexní číslo (dvojice) 2×float64 'D'

Poznámka: jednoznakové kódy je možné použít namísto jména typu, viz též funkce popsané v navazujících kapitolách.

19

Obrázek 4: Vykreslení funkce s využitím Qt Console.

4. Konstruktory polí

Pole typu ndarray je možné vytvořit několika různými způsoby. Základní funkcí sloužící k převodu různých typů Pythonovských objektů na pole je funkce nazvaná jednoduše numpy.array. Této funkci se předá objekt (což je typicky seznam, n-tice či objekt typu range) a popř. i další nepovinné parametry, které určují typ prvků nově vzniklého pole (dtype), zda se má provést kopie prvků (copy, většinou ano) či způsob uspořádání prvků v poli (order):

array(object, dtype=None, copy=True, order=None, subok=False, ndmin=0)

05

Obrázek 5: Všechny dnešní demonstrační příklady budeme testovat v IPython Notebooku, jehož prázdný list je zde otevřen ve webovém prohlížeči.

Nepovinný parametr order může nabývat hodnot:

Order Význam
'C' prvky jsou uspořádány jako v jazyku C
'F' prvky jsou uspořádány jako v jazyku Fortran
'A' ponecháme na implementaci, který způsob uspořádání zvolit

Jaký je tedy vlastně rozdíl mezi uspořádáním prvků podle 'C' a 'F'? Předpokládejme matici 3×3 prvky:

| 1 2 3 |
| 4 5 6 |
| 7 8 9 |

Tato matice může být v paměti uložena následujícím způsobem:

1 2 3 4 5 6 7 8 9 - 'C'

Alternativně je však možné prohodit řádky a sloupce (což více odpovídá matematickému zápisu matice):

1 4 7 2 5 8 3 6 9 - 'F'

Podívejme se nyní na několik praktických použití funkce numpy.array:

# vytvoření pole ze seznamu
numpy.array([1,2,3,4])
array([1, 2, 3, 4])

# vytvoření pole z typu 'range'
numpy.array(range(10))
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# explicitní specifikace typu všech prvků pole
numpy.array(range(10), dtype=numpy.float)
array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.])

# explicitní specifikace uspořádání prvků pole
# (nemá velký význam pro 1D pole=vektory)
numpy.array(range(10), order='C')
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# explicitní specifikace uspořádání prvků pole
# (nemá velký význam pro 1D pole=vektory)
numpy.array(range(10), order='F')
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# vytvoření dvourozměrné matice
numpy.array([[1,2,3],[4,5,6]])
array([[1, 2, 3],
       [4, 5, 6]])

06

Obrázek 6: Nápověda k modulu Numpy.

5. Konstruktor numpy.zeros

Kromě funkce numpy.array se poměrně často setkáme s nutností vytvořit vektor či matici s nulovými prvky. V tomto případě samozřejmě není nutné složitě vytvářet a předávat takové pole do funkce numpy.array, ale lze namísto toho využít funkci nazvanou numpy.zeros, což je rychlejší i méně paměťově náročnější. Té se předá n-tice (musí se skutečně jednat o n-tici, nikoli o seznam parametrů, proto nezapomeňte na závorky) specifikující dimenzi vektoru, matice či N-dimenzionálního pole:

zeros(shape, dtype=float, order='C')

Nepovinný parametr dtype se nastavuje buď na typ nebo na jednoznakový kód uvedený v tabulce ve třetí kapitole.

Podívejme se nyní na způsob použití této funkce:

# jednorozměrný vektor s jediným prvkem
numpy.zeros(1)
array([ 0.])

# jednorozměrný vektor s deseti prvky
numpy.zeros(10)
array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])

# matice o velikosti 5x5 prvků, každý prvek je typu float
numpy.zeros((5,5))

array([[ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.]])

# matice o velikosti 5x5 prvků, každý prvek je typu int
numpy.zeros((5,5),dtype=int)

array([[0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0]])

# použití komplexních čísel
numpy.zeros((2,2),dtype=numpy.complex)

array([[ 0.+0.j,  0.+0.j],
       [ 0.+0.j,  0.+0.j]])

07

Obrázek 7: Použití funkcí numpy.zeros a numpy.ones.

6. Konstruktor numpy.ones

Dalším velmi často používaným typem vektoru či matice je taková struktura, jejíž všechny prvky mají hodnotu 1. Takový vektor popř. matice je možné vytvořit funkcí numpy.ones

numpy.ones(shape, dtype=None, order='C')

Nepovinný parametr dtype se, podobně jako u předchozí funkce, nastavuje buď na typ nebo na jednoznakový kód uvedený v tabulce ve třetí kapitole.

Opět se podívejme na několik příkladů použití této funkce v praxi:

# jednorozměrný vektor s deseti prvky
numpy.ones(10)
array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.])

# matice se třemi řádky a čtyřmi sloupci
numpy.ones((3,4))

array([[ 1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.]])

# matice se třemi řádky a čtyřmi sloupci
# s explicitní specifikací typu prvků
numpy.ones((3,4), dtype=int)

array([[1, 1, 1, 1],
       [1, 1, 1, 1],
       [1, 1, 1, 1]])

# trojrozměrné pole s prvky typu int
numpy.ones((3,4,5), dtype=int)

array([[[1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1]],

       [[1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1]],

       [[1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1],
        [1, 1, 1, 1, 1]]])

# trojrozměrné pole s prvky typu int
# (oproti předchozímu příkladu se velikosti v jednotlivých dimenzích liší)
numpy.ones((5,4,3), dtype=int)

array([[[1, 1, 1],
        [1, 1, 1],
        [1, 1, 1],
        [1, 1, 1]],

       [[1, 1, 1],
        [1, 1, 1],
        [1, 1, 1],
        [1, 1, 1]],

       [[1, 1, 1],
        [1, 1, 1],
        [1, 1, 1],
        [1, 1, 1]],

       [[1, 1, 1],
        [1, 1, 1],
        [1, 1, 1],
        [1, 1, 1]],

       [[1, 1, 1],
        [1, 1, 1],
        [1, 1, 1],
        [1, 1, 1]]])

# zde může být použití typu komplexní číslo možná poněkud překvapující,
# ovšem stále platí, že 1=1+0j
numpy.ones((3,2),dtype=numpy.complex)

array([[ 1.+0.j,  1.+0.j],
       [ 1.+0.j,  1.+0.j],
       [ 1.+0.j,  1.+0.j]])

7. Funkce numpy.arange

Další funkcí určenou pro konstrukci vektoru je numpy.arange, přičemž poněkud zavádějící název „arange“ vznikl složením slov „array“ a „range“. Této funkci se předávají parametry s podobným významem, jaký mají u funkce xrange (Python 2.x) či range (Python 3.x), samozřejmě s tím rozdílem, že návratovou hodnotou funkce numpy.arange se skutečný vektor typu ndarray. Podívejme se na několik možností použití této poměrně nenápadné, ale o to užitečnější funkce:

# při použití jednoho parametru má tento parametr význam hodnoty "stop"
# vytvoří se vektor s prvky od 0 do "stop" (kromě)
numpy.arange(10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# specifikace hodnot "start" (včetně) a "stop" (kromě)
numpy.arange(10, 20)
array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])

# třetí nepovinný parametr určuje krok použitý při generování prvků vektoru
numpy.arange(10, 20, 2)
array([10, 12, 14, 16, 18])

# krok může být samozřejmě záporný
numpy.arange(20, 10, -2)
array([20, 18, 16, 14, 12])

# nemusíme zůstat pouze u celých čísel, protože pracovat je možné i s hodnotami
# typu float a complex
numpy.arange(0,5, 0.1)

array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9,  1. ,
        1.1,  1.2,  1.3,  1.4,  1.5,  1.6,  1.7,  1.8,  1.9,  2. ,  2.1,
        2.2,  2.3,  2.4,  2.5,  2.6,  2.7,  2.8,  2.9,  3. ,  3.1,  3.2,
        3.3,  3.4,  3.5,  3.6,  3.7,  3.8,  3.9,  4. ,  4.1,  4.2,  4.3,
        4.4,  4.5,  4.6,  4.7,  4.8,  4.9])

# použití komplexních konstant
numpy.arange(0+0j, 10+10j, 2+0j)
array([ 0.+0.j,  2.+0.j,  4.+0.j,  6.+0.j,  8.+0.j])

08

Obrázek 8: Příklady použití funkce numpy.arange v IPython Notebooku.

8. Funkce numpy.linspace

V některých případech nemusí být použití výše popsané funkce numpy.arange tím nejlepším řešením při vytváření vektoru obsahujícího sekvenci číselných hodnot. Typickým příkladem je sekvence generovaná s krokem 0.1, protože hodnotu 0.1 není možné formáty IEEE 754 single ani double přesně reprezentovat. Tím pádem nemusí být z volání funkce numpy.arange ihned zřejmé, kolik prvků se nakonec vygeneruje (typická chyba ±1). Pokud je nutné vytvořit vektor s přesným počtem prvků, může se namísto numpy.arange hodit funkce numpy.linspace, které se předá počáteční hodnota, koncová hodnota a popř. i počet prvků vektoru. Pokud počet prvků není explicitně zadán, použije se hodnota 50. Použití funkce numpy.linspace je tak ve skutečnosti velmi jednoduché:

# pokud se nespecifikuje počet prvků, bude se předpokládat, že výsledný
# vektor má mít padesát prvků
numpy.linspace(0, 1)

array([ 0.        ,  0.02040816,  0.04081633,  0.06122449,  0.08163265,
        0.10204082,  0.12244898,  0.14285714,  0.16326531,  0.18367347,
        0.20408163,  0.2244898 ,  0.24489796,  0.26530612,  0.28571429,
        0.30612245,  0.32653061,  0.34693878,  0.36734694,  0.3877551 ,
        0.40816327,  0.42857143,  0.44897959,  0.46938776,  0.48979592,
        0.51020408,  0.53061224,  0.55102041,  0.57142857,  0.59183673,
        0.6122449 ,  0.63265306,  0.65306122,  0.67346939,  0.69387755,
        0.71428571,  0.73469388,  0.75510204,  0.7755102 ,  0.79591837,
        0.81632653,  0.83673469,  0.85714286,  0.87755102,  0.89795918,
        0.91836735,  0.93877551,  0.95918367,  0.97959184,  1.        ])

# zde explicitně specifikujeme, že výsledný vektor má mít deset prvků
# (tím, že se začíná od nuly, získáme krok 0.11111111...)
numpy.linspace(0, 1, 10)

array([ 0.        ,  0.11111111,  0.22222222,  0.33333333,  0.44444444,
        0.55555556,  0.66666667,  0.77777778,  0.88888889,  1.        ])

# zde explicitně specifikujeme, že výsledný vektor má mít jedenáct prvků
numpy.linspace(0, 1, 11)
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9,  1. ])

# sekvence hodnot samozřejmě může i klesat
numpy.linspace(1, 0, 11)
array([ 1. ,  0.9,  0.8,  0.7,  0.6,  0.5,  0.4,  0.3,  0.2,  0.1,  0. ])

# použít je možné i komplexní čísla
numpy.linspace(0+0j, 1+0j, 10)

array([ 0.00000000+0.j,  0.11111111+0.j,  0.22222222+0.j,  0.33333333+0.j,
        0.44444444+0.j,  0.55555556+0.j,  0.66666667+0.j,  0.77777778+0.j,
        0.88888889+0.j,  1.00000000+0.j])

# použít je možné i komplexní čísla
numpy.linspace(0+0j, 0+1j, 10)

array([ 0.+0.j        ,  0.+0.11111111j,  0.+0.22222222j,  0.+0.33333333j,
        0.+0.44444444j,  0.+0.55555556j,  0.+0.66666667j,  0.+0.77777778j,
        0.+0.88888889j,  0.+1.j        ])

# další možnost použití komplexních čísel
numpy.linspace(0+0j, 1+1j, 10)

array([ 0.00000000+0.j        ,  0.11111111+0.11111111j,
        0.22222222+0.22222222j,  0.33333333+0.33333333j,
        0.44444444+0.44444444j,  0.55555556+0.55555556j,
        0.66666667+0.66666667j,  0.77777778+0.77777778j,
        0.88888889+0.88888889j,  1.00000000+1.j        ])

09

Obrázek 9: Příklady použití funkce numpy.linspace v IPython Notebooku.

9. Přetypování všech prvků v poli

Při práci s rozměrnými maticemi je v některých případech nutné provést přetypování všech prvků matice (či vektoru). Tuto operaci je možné provést dvěma způsoby. První způsob spočívá v tom, že se názvy datových typů, jako je například numpy.float32, numpy.int32 či numpy.complex128 (viz též tabulku uvedenou ve třetí kapitole), přímo použijí jako funkce pro přetypování:

# změna typu
numpy.float32(1.0)

# přetypování
numpy.int64([1,2,3,4])

# přetypování
numpy.float16([1,2,3,4])
array([ 1.,  2.,  3.,  4.], dtype=float16)

# vektor čísel typu float
numpy.linspace(0, 1, 10)

array([ 0.        ,  0.11111111,  0.22222222,  0.33333333,  0.44444444,
        0.55555556,  0.66666667,  0.77777778,  0.88888889,  1.        ])

# přetypování na vektor celých čísel
numpy.int32(numpy.linspace(0, 1, 10))
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 1], dtype=int32)

Alternativně se používá metoda (nikoli funkce) nazvaná astype, která se volá pro daný vektor, matici, či obecné n-dimenzionální pole. Této metodě se předá požadovaný typ prvků výsledného pole:

pole.astype(numpy.float32)
pole.astype(numpy.int8)
pole.astype(numpy.complex64)

a=numpy.arange(0, 10)

a.astype(numpy.complex64)
array([ 0.+0.j,  1.+0.j,  2.+0.j,  3.+0.j,  4.+0.j,  5.+0.j,  6.+0.j,
        7.+0.j,  8.+0.j,  9.+0.j], dtype=complex64)

10

Obrázek 10: Příklady přetypování a použití metody astype v IPython Notebooku.

10. Zjištění tvaru pole pomocí funkce numpy.shape

Termínem „tvar pole“ je v knihovně Numpy myšlena n-tice obsahující rozměry pole v jednotlivých dimenzích. Pro vektor tato n-tice obsahuje jediné číslo s délkou vektoru, pro matici obsahuje n-tice dvě čísla s počtem řádků a sloupců atd. Zjištění tvaru libovolného pole je tedy značně jednoduché:

# jednorozměrný vektor
a=numpy.array([1,2,3])

# dvourozměrná matice
b=numpy.array([[1,2,3],[4,5,6]])

# tvar vektoru
a.shape
(3,)

# tvar matice
b.shape
(2, 3)

# trojrozměrné pole
c=numpy.zeros((2,3,4))

c
array([[[ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.]],

       [[ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.],
        [ 0.,  0.,  0.,  0.]]])

# tvar trojrozměrného pole
c.shape
(2, 3, 4)

# další trojrozměrné pole, tentokrát vytvořené explicitně
d=numpy.array([[[1,2], [3,4]], [[5,6], [7,8]]])

numpy.shape(d)
(2, 2, 2)

11. Změna tvarů polí s využitím funkce numpy.reshape

Další velmi důležitou funkcí, s níž se v praxi často setkáme, je funkce nazvaná numpy.reshape, která dokáže změnit velikost matice a vhodným způsobem přeorganizovat prvky v původní matici. Této funkci se předávají dva parametry – prvním parametrem je vstupní pole (vektor, matice, ...), druhým parametrem pak specifikace tvaru výsledného pole, přičemž tvar je reprezentován n-ticí, v níž jsou uloženy velikosti pole v jednotlivých dimenzích. Podívejme se na několik příkladů:

# běžná matice se dvěma řádky a třemi sloupci
b=numpy.array([[1,2,3],[4,5,6]])

# změna tvaru matice na 3x2 prvky
numpy.reshape(b,(3,2))

array([[1, 2],
       [3, 4],
       [5, 6]])

# zde vlastně dostaneme původní matici
numpy.reshape(b,(2,3))

array([[1, 2, 3],
       [4, 5, 6]])

# vytvoření matice s jediným řádkem
numpy.reshape(b,(1,6))

array([[1, 2, 3, 4, 5, 6]])

# vytvoření matice s jediným sloupcem
numpy.reshape(b,(6,1))

array([[1],
       [2],
       [3],
       [4],
       [5],
       [6]])

11

Obrázek 11: Příklady použití funkce numpy.reshape na dvanáctiprvkový vstupní vektor v IPython Notebooku.

Při použití funkce numpy.reshape si dejte pozor na to, aby se při změně tvarů pole přesně dodržel počet prvků. Pokud by se měl počet prvků změnit, dojde ke vzniku výjimky:

a=numpy.array([1,2,3])

numpy.reshape(a, (2,2))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-74-fa31403e23c0> in <module>()
----> 1 numpy.reshape(a,(2,2))

/usr/lib/python3/dist-packages/numpy/core/fromnumeric.py in reshape(a, newshape, order)
    216     except AttributeError:
    217         return _wrapit(a, 'reshape', newshape, order=order)
--> 218     return reshape(newshape, order=order)
    219 
    220 

ValueError: total size of new array must be unchanged

K chybě dojde i v opačném případě, tj. pokud by byl počet prvků vstupního pole sice dostatečný, ale některé prvky by ve výsledném (vytvářeném) poli přebývaly:

x=numpy.arange(0,12)

numpy.reshape(x, (2,2))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-47-0943fdd71a8f> in <module>()
----> 1 numpy.reshape(x, (2,2))

/usr/lib/python3/dist-packages/numpy/core/fromnumeric.py in reshape(a, newshape, order)
    216     except AttributeError:
    217         return _wrapit(a, 'reshape', newshape, order=order)
--> 218     return reshape(newshape, order=order)
    219 
    220 

ValueError: total size of new array must be unchanged

Proč tomu tak je? Ve skutečnosti se totiž funkcí numpy.reshape nevytváří zcela nové pole s jiným tvarem, ale dochází pouze ke vzniku odlišného pohledu na jediné (zdrojové) pole.

Další příklad pro vstupní vektor s 24 prvky a výsledná pole se třemi či čtyřmi dimenzemi:

# zdrojový vektor
m=numpy.arange(24)

m

array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
       17, 18, 19, 20, 21, 22, 23])

# změna tvaru na trojrozměrné pole
numpy.reshape(m, (2,3,4))

array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])

# změna tvaru vektoru na trojrozměrné pole
numpy.reshape(m, (4,2,3))

array([[[ 0,  1,  2],
        [ 3,  4,  5]],

       [[ 6,  7,  8],
        [ 9, 10, 11]],

       [[12, 13, 14],
        [15, 16, 17]],

       [[18, 19, 20],
        [21, 22, 23]]])

# změna tvaru vektoru na čtyřrozměrné pole
numpy.reshape(m, (2,2,2,3))

array([[[[ 0,  1,  2],
         [ 3,  4,  5]],

        [[ 6,  7,  8],
         [ 9, 10, 11]]],


       [[[12, 13, 14],
         [15, 16, 17]],

        [[18, 19, 20],
         [21, 22, 23]]]])

# změna tvaru vektoru na čtyřrozměrné pole
numpy.reshape(m, (3,2,2,2))

array([[[[ 0,  1],
         [ 2,  3]],

        [[ 4,  5],
         [ 6,  7]]],


       [[[ 8,  9],
         [10, 11]],

        [[12, 13],
         [14, 15]]],


       [[[16, 17],
         [18, 19]],

        [[20, 21],
         [22, 23]]]])

12. Vliv nepovinného parametru „order“ na (zdánlivou) změnu tvaru pole

S nepovinným parametrem „order“ jsme se již setkali u funkce numpy.array. Tento parametr lze použít i při změně tvaru pole funkcí numpy.reshape. Opět platí, že je možné specifikovat řazení prvků podle jazyka Fortran či podle jazyka C. Změní se tedy pohled na původní pole resp. pohled na to, jakým způsobem knihovna Numpy počítá indexy prvků (k vlastnímu přeorganizování pole v operační paměti však nedojde):

# nyní vyzkoušíme význam nepovinného parametru order
numpy.reshape(m, (6,4))

array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23]])

numpy.reshape(m, (6,4), order='C')

array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19],
       [20, 21, 22, 23]])

numpy.reshape(m, (6,4), order='F')

array([[ 0,  6, 12, 18],
       [ 1,  7, 13, 19],
       [ 2,  8, 14, 20],
       [ 3,  9, 15, 21],
       [ 4, 10, 16, 22],
       [ 5, 11, 17, 23]])

12

Obrázek 12: Příklady použití funkce numpy.reshape na dvanáctiprvkový vstupní vektor v IPython Notebooku.

13. Předchozí části seriálu

  1. Vývojová prostředí ve Fedoře (1. díl)
    http://mojefedora.cz/vyvojova-prostredi-ve-fedore-1-dil/
  2. Vývojová prostředí ve Fedoře (2. díl)
    http://mojefedora.cz/vyvojova-prostredi-ve-fedore-2-dil/
  3. Vývojová prostředí ve Fedoře (3. díl)
    http://mojefedora.cz/vyvojova-prostredi-ve-fedore-3-dil/
  4. Vývojová prostředí ve Fedoře (4. díl)
    http://mojefedora.cz/vyvojova-prostredi-ve-fedore-4-dil/
  5. Integrovaná vývojová prostředí ve Fedoře: PyDev
    http://mojefedora.cz/integrovana-vyvojova-prostredi-ve-fedore-pydev/
  6. Integrovaná vývojová prostředí ve Fedoře: PyDev (2.část)
    http://mojefedora.cz/integrovana-vyvojova-prostredi-ve-fedore-pydev-2-cast/
  7. Integrovaná vývojová prostředí ve Fedoře: IPython a IPython Notebook
    http://mojefedora.cz/integrovana-vyvojova-prostredi-ve-fedore-ipython-a-ipython-notebook/

14. Odkazy na Internetu

  1. IPython homepage
    http://ipython.org/
  2. Dokumentace k IPythonu
    http://ipython.org/documentation.html#
  3. IPython Tutorial
    http://ipython.readthedocs.org/en/stable/interactive/tutorial.html
  4. NumPy Home Page
    http://www.numpy.org/
  5. NumPy v1.10 Manual
    http://docs.scipy.org/doc/numpy/index.html
  6. NumPy (Wikipedia)
    https://en.wikipedia.org/wiki/NumPy
  7. Matplotlib Home Page
    http://matplotlib.org/
  8. matplotlib (Wikipedia)
    https://en.wikipedia.org/wiki/Matplotlib
  9. The cell magics in IPython
    http://nbviewer.jupyter.org/github/ipython/ipython/blob/1.x/examples/notebooks/Cell%20Magics.ipynb
  10. 0MQ Home Page
    http://zeromq.org/
  11. Is IPython Notebook ever used as an IDE, or merely for presentations?
    https://www.reddit.com/r/IPython/comments/1uk7hp/is_ipython_notebook_ever_used_as_an_ide_or_merely/
  12. The IDE as a Bad Programming Language Enabler
    https://dzone.com/articles/ide-bad-programming-language
  13. Enhanced Interactive Python with IPython
    http://www.onlamp.com/pub/a/python/2005/01/27/ipython.html
  14. Direct mode
    https://en.wikipedia.org/wiki/Direct_mode
  15. Seznámení s Python IDE Spyder (článek vyšel zde na mojefedora.cz)
    http://mojefedora.cz/seznameni-s-python-ide-spyder/
  16. Stránka s popisem různých IDE pro Python
    http://quintagroup.com/cms/python/ide
  17. Eclipse (stránka o frameworku na Fedoraproject.org)
    https://fedoraproject.org/wiki/Eclipse
  18. PyDev (hlavní stránka)
    http://pydev.sourceforge.net/index.html
  19. PyDev (download, v podstatě není zapotřebí)
    http://pydev.sourceforge.net/download.html
  20. PyDev (stránka s metainformacemi o PyDev pluginu, použita v Eclipse)
    http://www.pydev.org/updates/
  21. PyDev (stránka s pluginem, použita v Eclipse)
    https://dl.bintray.com/fabioz/pydev/4.5.4/
  22. Certifikát, který lze do Eclipse doinstalovat
    http://www.pydev.org/pydev_certificate.cer
  23. PyDev FAQ
    http://pydev.sourceforge.net/faq.html
  24. PyDev (Wikipedia)
    https://en.wikipedia.org/wiki/PyDev
  25. Python (oficiální stránky projektu)
    https://www.python.org/
  26. Jython
    http://www.jython.org/
  27. IronPython
    http://ironpython.net/
  28. Python 3.5.1 documentation
    https://docs.python.org/3/
  29. PyDev: Unittest integration
    http://mojefedora.cz/integrovana-vyvojova-prostredi-ve-fedore-pydev/
  30. Continuous unit testing with Pydev (Python and Eclipse)
    http://stackoverflow.com/questions/1015581/continuous-unit-testing-with-pydev-python-and-eclipse
  31. Test-driven development
    https://en.wikipedia.org/wiki/Test-driven_development