3. diel - Tvorba polí
V predchádzajúcej lekcii, Dátové typy, sme sa pozreli na to, aké základné dátové typy používa knižnica NumPy a ako sa s nimi pracuje.
V tomto tutoriále knižnice NumPy v Pythone sa pozrieme na pole v knižnici NumPy a naučíme sa ich vytvárať. Vysvetlíme si, aké je dôležité udržiavať pole homogénne.
Poľa v NumPy - ndarray
Polia, ktoré poskytuje knižnica NumPy, sa do značnej miery správajú podobne ako bežné zoznamy v Pythone. Je možné do nich ukladať najrôznejšie typy premenných - čísla, reťazce i všeobecné objekty a potom k prvkom pristupovať, prípadne ich meniť. Oproti bežným zoznamom v Pythone ale nie je možné do nich prvky pridávať a odoberať. Polia v NumPy majú pevne daný počet prvkov, podobne ako to majú polia v jazykoch C alebo Java.
Pole vs. zoznam - rozlíšenie pojmov
Ešte raz si zopakujme veľmi dôležitý poznatok, ktorý
sme spomenuli v lekcii NumPy - Predstavenie knižnice v
kapitole Zoznamy
v Pythone vs NumPy arrays. Zoznamy v Pythone sú
dynamické. Zodpovedajú tomu, čo v iných jazykoch označujeme ako
list
– zoznam. Oproti tomu v NumPy sa jedná o skutočné pole -
array
, ako ich poznáme z jazykov C či Java. V NumPy ich budeme
označovať aj ich technickým názvom ako ndarray
. Natívne
zoznamy Pythona a poľa NumPy budeme v tutoriáli striktne
odlišovať.
Ukážme si ešte pre istotu kód zoznamu a poľa:
list = [1, 2, 3] # list print(type(list)) array = np.array([1, 2, 3]) # ndarray print(type(array))
Vo výstupe konzoly dostaneme:
The difference between a list and an array:
class 'list'
class 'numpy.ndarray'
Poľa vs. zoznam - kedy použiť čo?
Prečo by sme mali použiť NumPy ndarray
, keď nám oproti
Pythonovskému zoznamu neumožňuje pridávať a odoberať prvky? Odpovede sú
dve - čas a priestor v pamäti. S poľom sa počítaču zaobchádza
jednoduchšie. Akonáhle sa raz pole vytvorí v pamäti, jeho dĺžka zostáva
až do zmazania Garbage Collectorom konštantná. Samozrejme sa občas nejaká
hodnota v ňom zmení, ale to je všetko.
Preto ak pracujeme s veľkým množstvom hodnôt alebo operácií, je
všeobecne rýchlejšie aj úspornejšie použiť ndarray
. Inak
samozrejme môžeme použiť aj základný Python zoznam.
Ako sa vytvára pole v NumPy
Existuje viacero spôsobov, ako ndarray
vytvoriť.
Najčastejšie použijeme "premenu" zoznamu pomocou metódy
np.array()
. NumPy však obsahuje mnoho ďalších zaujímavých
funkcií a metód, ktoré poskytujú ndarray
na výstupe. Pozrime
sa na niektoré z nich.
Vytvorenie NumPy poľa z Python zoznamu
Najprv si ukážeme už spomínanú metódu np.array()
:
natural_numbers_array = np.array([1, 2, 3]) animals_array = np.array(['dog', 'cat', 'pterodactyl']) date_array = np.array([np.datetime64('2023-07-20T17:23:10.42'), np.datetime64('2023-07-20'), np.datetime64('2023-07')])
Všeobecne je nevhodné miešať rôzne typy v jednom poli. Dátový typ NumPy poľa pri jeho vytvorení buď explicitne špecifikujeme, alebo je automaticky určený na základe hodnôt, ktoré do poľa vložíme. Pokiaľ vložíme do jedného poľa rôzne typy dát, NumPy ich všetky prevedie na jednotný typ. Vyberie pritom taký, ktorý dokáže reprezentovať všetky vložené hodnoty. Uveďme si príklad. Ak vytvoríme pole s celými číslami a jedno z nich bude desatinné, všetky čísla budú prevedené na desatinné. Podobne, ak pridáme reťazec do poľa s celými číslami, všetky čísla budú prevedené na reťazce. Je zrejmé, ako nepekne toto dokáže ovplyvniť výsledky matematických operácií.
Pretypovanie v poli je nákladné z hľadiska výkonu a ide o veľmi jednoduchý spôsob, ako si prirobiť naozaj nepríjemné problémy s neočakávaným správaním programu. Preto sa snažíme pole udržiavať homogénne.
No a ak budeme naozaj kreatívni a do jedného poľa namixujeme toľko typov,
že NumPy nedokáže nájsť jeden, ktorý by ich zastrešil, vznikne nám pole
prvkov object
:
mixed_array = np.array([1, 'dog', np.datetime64('2023-07-20T17:23:10.42')]) print(mixed_array.dtype)
Vo výstupe uvidíme:
Type of array elements:
object
Vytváranie viacrozmerných polí
Poďme si ukázať, ako s pomocou metódy np.array()
vytvoríme
viacrozmerné polia:
array_2D = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) array_3D = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
Prístup k prvkom v 3D poli
Naše array_3D
má formát 2 x (2 x 3)
. Predstavme
si ho ako kinosála. Formát 2 x (2 x 3)
nám hovorí, že máme
prízemie a poschodie a v každom z nich dva rady po troch sedadlách. Rozložme
si zápis poľa tak, aby bol intuitívnejší:
array_3D = np.array([ [[1, 2, 3], # first floor, first row [4, 5, 6]], # first floor, second row [[7, 8, 9], # second floor, first row [10, 11, 12]] # second floor, second row ]) # access to seat number 12 on the floor: seat = array_3D[1, 1, 2] # the variable seat will contain the number 12
Zaujímavosťou je, že môžeme vytvoriť aj polia s "dimenziou 0":
array_0D = np.array(10)
V podstate tým do poľa uložíme iba jednu hodnotu. Ak vytlačíme obsah
premennej array_0D
, dostaneme hodnotu 10
. Pokiaľ
však zistíme typ premennej, dostaneme ndarray
, nie
integer
:
print(array_0D) print(type(array_0D))
V konzole uvidíme:
Array with dimension 0: 10
Náhodné celé číslo -
np.random.randint()
Metóda randint()
v module random
knižnice NumPy
je základná funkcia pre generovanie náhodných čísel typu
integer
. Ako pre vygenerovanie jednej náhodnej hodnoty, tak aj
celého (aj viacrozmerného) poľa náhodných hodnôt.
Funkcie a metódy v module random
máme k dispozícii buď
priamo z knižnice (np.random
), alebo si modul pridáme priamo ako
premennú. To je spôsob, aký budeme kvôli zjednodušeniu kódu používať v
tutoriáli:
import numpy.random as random
Teraz už môžeme premennú random
používať priamo.
Metóda randint()
funguje jednoducho a poznáme ju už z kurzu
Základná konštrukcia jazyka Pythonu z lekcie Knižnice
math a random. Nechajme si teda vygenerovať náhodné číslo od nuly do
devätnástich:
random_number = random.randint(20)
Je potrebné si uvedomiť, že ako mnoho ďalších knižníc a
funkcií v Pythone, aj NumPy používa spodnú definovanú hranicu intervalu
"vrátane" (inkluzívne) a hornú hranicu "bez" (exkluzívne). V našom prípade
kód random.randint(20)
znamená v reči matematiky interval
<0; 20)
.
Poľa náhod
Pokiaľ chceme vytvoriť pole náhodných hodnôt, vyplníme metóde argument
požadovanej dĺžky poľa size
:
array_random_numbers = random.randint(3, 20, size=(5)) # meaning: fill an array of length 5 with numbers from 3 to 19 print(array_random_numbers) print() array_2D_random_numbers = random.randint(3, 20, size=(5, 4)) # fill an array with five rows and four columns with numbers from 3 to 19 print(array_2D_random_numbers)
Výstup v konzole:
Konzolová aplikácia
[ 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()
Metóda rand()
má trochu odlišnú syntax. Táto metóda
generuje náhodné číslo medzi 0
a 1
. Opäť v
half-open intervale, avšak tentoraz <0; 1)
. Pokiaľ chceme
získať desatinné číslo v inom intervale, musíme funkciu
rand()
prenásobiť a posunúť. Povedzme, že chceme náhodné
číslo v intervale <10, 30)
:
random_decimal_number = random.rand() * 20 + 10
Viac si o náhodných číslach povieme v ďalších lekciách. Teraz sa
presunieme na vytváranie polí. NumPy ndarray
pomocou metódy
rand()
vytvoríme tak, že do argumentu dáme číslo označujúce
rozmer poľa, ktoré chceme:
# Array of random numbers of length 3 random_1D_array = random.rand(3)
Získali sme polia troch čísel z intervalu <0,1)
. Podobne
vytvoríme aj viacrozmerné polia - jednoducho len pridáme číslo označujúce
ďalší rozmer:
# Matrix of random numbers with dimensions 3×4 random_2D_array = random.rand(3, 4)
Pre čísla v inom intervale ako <0,1)
opäť
použijeme posunutie násobením a pripočítaním čísla.
To je pre túto lekciu všetko.
V nasledujúcom kvíze, Kvíz - Dátové typy a polia v NumPy, si vyskúšame nadobudnuté skúsenosti z predchádzajúcich lekcií.