NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Lekce 3 - Tvorba polí

V předchozí lekci, Datové typy, jsme se podívali na to, jaké základní datové typy používá knihovna NumPy a jak se s nimi pracuje.

V tomto tutoriálu knihovny NumPy v Pythonu se podíváme na pole v knihovně NumPy a naučíme se je vytvářet. Vysvětlíme si, jak je důležité udržovat pole homogenní.

Pole v NumPy - ndarray

Pole, která poskytuje knihovna NumPy, se do značné míry chovají podobně jako běžné seznamy v Pythonu. Lze do nich ukládat nejrůznější typy proměnných - čísla, řetězce i obecné objekty a poté k prvkům přistupovat, případně je měnit. Oproti běžným seznamům v Pythonu ale není možné do nich prvky přidávat a odebírat. Pole v NumPy mají pevně daný počet prvků, podobně jako to mají pole v jazycích C či Java.

Pole vs. seznam - rozlišení pojmů

Ještě jednou si zopakujme velmi důležitý poznatek, který jsme zmínili v lekci NumPy - Představení knihovny v kapitole Seznamy v Pythonu vs NumPy arrays. Seznamy v Pythonu jsou dynamické. Odpovídají tomu, co v jiných jazycích označujeme jako list - seznam. Oproti tomu v NumPy se jedná o skutečná pole - array, jako je známe z jazyků C či Java. V NumPy je budeme označovat také jejich technickým názvem jako ndarray. Nativní seznamy Pythonu a pole NumPy budeme v tutoriálu striktně odlišovat.

Ukažme si ještě pro jistotu kód seznamu a pole:

seznam = [1, 2, 3]    # seznam
print(type(seznam))

pole = np.array([1, 2, 3])    # ndarray
print(type(pole))

Ve výstupu konzole dostaneme:

Rozdíl mezi seznamem a polem:
class 'list'
class 'numpy.ndarray'

Pole vs. seznam - kdy použít co?

Proč bychom měli použít NumPy ndarray, když nám oproti Pythonovskému seznamu neumožňuje přidávat a odebírat prvky? Odpovědi jsou dvě - čas a prostor v paměti. S polem se počítači zachází jednodušeji. Jakmile se jednou pole vytvoří v paměti, jeho délka zůstává až do smazání Garbage Collectorem konstantní. Samozřejmě se občas nějaká hodnota v něm změní, ale to je vše.

Proto pokud pracujeme s velkým množstvím hodnot nebo operací, je obecně rychlejší i úspornější použít ndarray. Jinak samozřejmě můžeme použít i základní Python seznam.

Jak se vytváří pole v NumPy

Existuje více způsobů, jak ndarray vytvořit. Nejčastěji použijeme "přeměnu" seznamu pomocí metody np.array(). NumPy nicméně obsahuje mnoho dalších zajímavých funkcí a metod, které poskytují ndarray na výstupu. Podívejme se na některé z nich.

Vytvoření NumPy pole z Python seznamu

Nejprve si ukážeme již zmíněnou metodu np.array():

prirozena_cisla_pole = np.array([1, 2, 3])
zvirata_pole = np.array(['pes', 'kočka', 'pterodaktyl'])
datum_pole = np.array([np.datetime64('2023-07-20T17:23:10.42'), np.datetime64('2023-07-20'), np.datetime64('2023-07')])

Obecně je nevhodné míchat různé typy v jednom poli. Datový typ NumPy pole při jeho vytvoření buď explicitně specifikujeme, nebo je automaticky určen na základě hodnot, které do pole vložíme. Pokud vložíme do jednoho pole různé typy dat, NumPy je všechny převede na jednotný typ. Vybere přitom takový, který dokáže reprezentovat všechny vložené hodnoty. Uveďme si příklad. Pokud vytvoříme pole s celými čísly a jedno z nich bude desetinné, všechna čísla budou převedena na desetinná. Podobně, pokud přidáme řetězec do pole s celými čísly, všechna čísla budou převedena na řetězce. Je zřejmé, jak nepěkně toto dokáže ovlivnit výsledky matematických operací.

Přetypování v poli je nákladné z hlediska výkonu a jde o velmi snadný způsob, jak si přidělat opravdu nepříjemné problémy s neočekávaným chováním programu. Proto se snažíme pole udržovat homogenní.

No a pokud budeme opravdu kreativní a do jednoho pole namixujeme tolik typů, že NumPy nedokáže najít jeden, který by je zastřešil, vznikne nám pole prvků object:

mix_pole = np.array([1, 'pes', np.datetime64('2023-07-20T17:23:10.42')])
print(mix_pole.dtype)

Ve výstupu uvidíme:

Typ prvků pole:
object

Vytváření vícerozměrných polí

Pojďme si ukázat, jak s pomocí metody np.array() vytvoříme vícerozměrná pole:

pole_2D = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
pole_3D = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
Přístup k prvkům v 3D poli

Naše pole_3D má formát 2 x (2 x 3). Představme si ho jako kinosál. Formát 2 x (2 x 3) nám říká, že máme přízemí a patro a v každém z nich dvě řady po třech sedadlech. Rozložme si zápis pole tak, aby byl intuitivnější:

pole_3D = np.array([
[[1, 2, 3],    # přízemí, první řada
[4, 5, 6]],    # přízemí, druhá řada
[[7, 8, 9],    # patro, první řada
[10, 11, 12]]  # patro, druhá řada
])

# Přístup k sedadlu č. 12 v patře:
sedadlo = pole_3D[1, 1, 2]  # v proměnné sedadlo bude číslo 12

Zajímavostí je, že můžeme vytvořit i pole s "dimenzí 0":

pole_0D = np.array(10)

V podstatě tím do pole uložíme jen jednu hodnotu. Pokud vytiskneme obsah proměnné pole_0D, dostaneme hodnotu 10. Pokud však zjistíme typ proměnné, dostaneme ndarray, nikoli integer:

print(pole_0D)
print(type(pole_0D))

V konzoli uvidíme:

Pole s dimenzí 0:
10

	
	

Náhodné celé číslo - np.random.randint()

Metoda randint() v modulu random knihovny NumPy je základní funkce pro generování náhodných čísel typu integer. Jak pro vygenerování jedné náhodné hodnoty, tak i celého (i vícerozměrného) pole náhodných hodnot.

Funkce a metody v modulu random máme k dispozici buď přímo z knihovny (np.random), nebo si modul přidáme přímo jako proměnnou. To je způsob, jaký budeme kvůli zjednodušení kódu používat v tutoriálu:

import numpy.random as random

Nyní už můžeme proměnnou random používat přímo.

Metoda randint() funguje jednoduše a známe ji už z kurzu Základní konstrukce jazyka Pythonu z lekce Knihovny math a random. Nechme si tedy vygenerovat náhodné číslo od nuly do devatenácti:

nahodne_cislo = random.randint(20)

Je potřeba si uvědomit, že jako mnoho dalších knihoven a funkcí v Pythonu, i NumPy používá spodní definovanou hranici intervalu "včetně" (inkluzivní) a horní hranici "bez" (exkluzivní). V našem případě kód random.randint(20) znamená v řeči matematiky interval <0; 20).

Pole náhod :-)

Pokud chceme vytvořit pole náhodných hodnot, vyplníme metodě argument požadované délky pole size:

pole_nahodnych_cisel = random.randint(3, 20, size=(5)) # znamená naplň pole o délce 5 čísel čísly od 3 do 19
print(pole_nahodnych_cisel)
print()
pole_2D_nahodnych_cisel = random.randint(3, 20, size=(5, 4)) # naplň pole o pěti řádcích a čtyřech sloupcích čísly od 3 do 19
print(pole_2D_nahodnych_cisel)

Výstup v konzoli:

Konzolová aplikace
[ 8  7  7  5 17]

[[19  8 14  8]
 [14  5  5  3]
 [ 4  6 17 10]
 [16 14  5  6]
 [19 18  8  9]]

Náhodný double - np.random.rand()

Metoda rand() má trochu odlišnou syntaxi. Tato metoda generuje náhodné číslo mezi 0 a 1. Opět v half-open intervalu, ovšem tentokrát <0; 1). Pokud chceme získat desetinné číslo v jiném intervalu, musíme funkci rand() přenásobit a posunout. Řekněme, že chceme náhodné číslo v intervalu <10, 30):

nahodne_desetinne_cislo = random.rand() * 20 + 10

Více si o náhodných číslech řekneme v dalších lekcích. Teď se přesuneme k vytváření polí. NumPy ndarray pomocí metody rand() vytvoříme tak, že do argumentu dáme číslo označující rozměr pole, které chceme:

# Pole náhodných čísel délky 3
nahodne_1D_pole = random.rand(3)

Získali jsme pole tří čísel z intervalu <0,1). Podobně vytvoříme i vícerozměrná pole - prostě jen přidáme číslo označující další rozměr:

# Matice náhodných čísel o rozměrech 3×4
nahodne_2D_pole = random.rand(3, 4)

Pro čísla v jiném intervalu než <0,1) opět použijeme posunutí násobením a přičtením čísla.

To je pro tuto lekci vše.

V následujícím kvízu, Kvíz - Datové typy a pole v NumPy, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.


 

Předchozí článek
Datové typy
Všechny články v sekci
NumPy - Matematika v Pythonu
Přeskočit článek
(nedoporučujeme)
Kvíz - Datové typy a pole v NumPy
Článek pro vás napsal Miloš Halda
Avatar
Uživatelské hodnocení:
15 hlasů
Autor se věnuje především bioinformatice a s ní souvisejícím tématům. Nevyhýbá se OOP jazykům, statistice a nástrojům pro analýzu dat.
Aktivity