1. Data a grafy#

1.1. První kroky#

Komentáře budou jenom stručné, pokud chcete podrobné vysvětlení jednotlivých příkazů, můžete je vykopírovat do nějakého nástroje umělé inteligence, například ChatGPT nebo ZZZ Code AI. Oba nástroje umí komunikovat i v češtině.

Co googlit

Klíčová slova, která se hodí pro dotazy pro vyhledávací službu. Pro potřeby nalezení návodů, tutoriálů, tipů, uživatelského manuálu apod.

Slovo, fráze

Použití

Python

Programovací jazyk, který budeme používat

Jupyter, JupterLab

Prostředí, ve kterém budeme Python používat nejčastěji. Prostředí pro práci je mnoho, volíme takové, které nevyžaduje instalaci na lokální PC.

NumPy

Knihovna numerické výpočty.

SciPy

Knihovna pro řešení diferenciálních rovnic a pro mnoho dalšího.

solve_ivp

Příkaz z knihovny SciPy pro řešení diferenciálních rovnic.

Matplotlib

Knihovna pro kreslení obrázků, grafů. Nejčastěji použijeme pro vizualizaci výstupu přkazu solve_ivp.

Pandas

Knihovna pro práci s tabulkami.

dataframe

Název pro tabulky používaný při práci s knihovnou Pandas.

difefrenciální rovnice, počáteční úloha, ODE, ordinary differential equation, IVP, initial value problem

Název matematických nástrojů používaný při modelování

Markdown

Jeden z nejjednodušších značkovacích jazyků, používá se pro doprovodné texty v Jupyter zápisnících

LaTeX, \(\LaTeX\), latex

Nejrychlejší a nejspolehlivější metoda psaní matematických výrazů do textu, kompatibilní s Markdown a s relativně nedávnou verzí MS Word. Také samostatný typografický systém, ale my budeme využívat jenom pro psaní matematických výrazů, kde je LaTeX nenahraditelný.

# načtení knihoven
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# vytvoření pole pro definiční obor a vykreslení dvou goniometrickcýh funkcí
x = np.linspace(0,10,100)
plt.plot(x,np.sin(x))
plt.plot(x,np.cos(x))
[<matplotlib.lines.Line2D at 0x7f85c2638d10>]
../_images/51509d283bc73febf246a9e1821ccaf249e13d61acee57e15d6e70eef4b2f94d.png
# vytvoření pole pro definiční obor a vykreslení dvou goniometrickcýh funkcí
pocet_bodu = 100
a,b = 0, 10
x = np.linspace(a,b,pocet_bodu)
plt.plot(x,np.sin(x))
plt.plot(x,np.cos(x))
[<matplotlib.lines.Line2D at 0x7f85c2700dd0>]
../_images/51509d283bc73febf246a9e1821ccaf249e13d61acee57e15d6e70eef4b2f94d.png

Při skutečné práci chceme zpravidla oddělit načtení dat, jejich zpracování a vizuální prezentaci. K tomu se hodí data ukládat do tabulek.

df = pd.DataFrame(index=x) # Prázdná tabulka se zadanými hodnotami řádkového indexu
df["sinus"] = np.sin(x) # vytvoření sloupce s daty
df["kosinus"] = np.cos(x) # vytvoření dalšího sloupce s daty
df
sinus kosinus
0.00000 0.000000 1.000000
0.10101 0.100838 0.994903
0.20202 0.200649 0.979663
0.30303 0.298414 0.954437
0.40404 0.393137 0.919480
... ... ...
9.59596 -0.170347 -0.985384
9.69697 -0.268843 -0.963184
9.79798 -0.364599 -0.931165
9.89899 -0.456637 -0.889653
10.00000 -0.544021 -0.839072

100 rows × 2 columns

df.plot()
<Axes: >
../_images/f00c4e1721eb28737071d369c7efcef58561b77c713a14eeeb17fe7d2b55ded0.png

U velkých tabulek je efektivnější a pohodlnější nejprve vytvořit tabulku i se sloupci a poté do ní doplnit data. Následující kód připraví proměnné a prázdnou tabulku.

K = 1
r_seznam = np.array([1,2,3])
x = np.linspace(0,1,100)
df = pd.DataFrame(index=x, columns=r_seznam)
df
1 2 3
0.000000 NaN NaN NaN
0.010101 NaN NaN NaN
0.020202 NaN NaN NaN
0.030303 NaN NaN NaN
0.040404 NaN NaN NaN
... ... ... ...
0.959596 NaN NaN NaN
0.969697 NaN NaN NaN
0.979798 NaN NaN NaN
0.989899 NaN NaN NaN
1.000000 NaN NaN NaN

100 rows × 3 columns

Následující kód do tabulky doplní data. Postupuje se po sloupcích.

for r in r_seznam:
    df[r] = r * x * (1 - x/K)
df
1 2 3
0.000000 0.000000 0.000000 0.000000
0.010101 0.009999 0.019998 0.029997
0.020202 0.019794 0.039588 0.059382
0.030303 0.029385 0.058770 0.088154
0.040404 0.038772 0.077543 0.116315
... ... ... ...
0.959596 0.038772 0.077543 0.116315
0.969697 0.029385 0.058770 0.088154
0.979798 0.019794 0.039588 0.059382
0.989899 0.009999 0.019998 0.029997
1.000000 0.000000 0.000000 0.000000

100 rows × 3 columns

ax = df.plot()
ax.legend(title = "Hodnota r")
ax.set(title="Růst v prostředí s omezenou nosnou kapacitou", 
       xlabel="Velikost populace", 
       ylabel="Rychlost růstu")
[Text(0.5, 1.0, 'Růst v prostředí s omezenou nosnou kapacitou'),
 Text(0.5, 0, 'Velikost populace'),
 Text(0, 0.5, 'Rychlost růstu')]
../_images/a65d0b349765d5961034f2046f2f69c73bfc0b145bdb38f27d818714feb9334c.png

1.2. Simulace ochlazování#

Následující kód vytvoří tabulku se třemi sloupci pro tři řešení. Řádkový index bude obsahovat časové údaje.

N = 500
t = np.linspace(0,5,500)
k_values = [1,2,3]
df = pd.DataFrame(index=t, columns=k_values)
T_okoli = 20

df.iloc[0,:] = 90
df
1 2 3
0.00000 90 90 90
0.01002 NaN NaN NaN
0.02004 NaN NaN NaN
0.03006 NaN NaN NaN
0.04008 NaN NaN NaN
... ... ... ...
4.95992 NaN NaN NaN
4.96994 NaN NaN NaN
4.97996 NaN NaN NaN
4.98998 NaN NaN NaN
5.00000 NaN NaN NaN

500 rows × 3 columns

Následující kód vyřízne z tabulky sloupec s indexem 1. Ten odpovídá jednomu řešení. S tímto vektorem budeme pracovat. Protože v tomto případě nevzniká jiná proměnná, ale pouze odkaz na část tabulky, úpravou vektoru T dojde i k modifikaci dat v tabulce.

T = df[1].values
T
array([90, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan], dtype=object)

Ukázka přístupu k hodnotám. Pomocí hranaté závorky a řádkového indexu.

T[0]
90

Řádkový index jsou časové značky, ty si uložíme do proměnné t. K jednotlivým časovým značkám je možno přistupovat pomocí t[n], kde n je pořadí hodnoty ve vektoru t, číslováno od nuly.

t = df.index
t
Index([                0.0, 0.01002004008016032, 0.02004008016032064,
       0.03006012024048096, 0.04008016032064128,  0.0501002004008016,
       0.06012024048096192, 0.07014028056112225, 0.08016032064128256,
       0.09018036072144288,
       ...
         4.909819639278557,   4.919839679358717,   4.929859719438878,
         4.939879759519038,   4.949899799599198,   4.959919839679358,
         4.969939879759519,   4.979959919839679,    4.98997995991984,
                       5.0],
      dtype='float64', length=500)

Takto nastavíme teplotu ve druhém časovém okamžiku (tj. index času je 1, protože se indexuje od nuly) na konkrétní hodnotu.

T[1] = 50
T
array([90, 50, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,
       nan, nan, nan, nan, nan], dtype=object)

Proměnná T je odkazem na stejná data, jako jsou v tabulce. Proto se automaticky změní i hodnota v tabulce.

df
1 2 3
0.00000 90 90 90
0.01002 50 NaN NaN
0.02004 NaN NaN NaN
0.03006 NaN NaN NaN
0.04008 NaN NaN NaN
... ... ... ...
4.95992 NaN NaN NaN
4.96994 NaN NaN NaN
4.97996 NaN NaN NaN
4.98998 NaN NaN NaN
5.00000 NaN NaN NaN

500 rows × 3 columns

A nyní najdeme teploty v cyklu přes všechny časy a přes všechny počáteční hodnoty.

for k in k_values:
    T = df[k].values
    for i in range(N-1):
        dt = t[i+1] - t[i]
        T[i+1] = T[i] - dt*(T[i]-T_okoli)*k
ax = df.plot()
ax.set(ylim=(0,None))
[(0.0, 93.49999914938851)]
../_images/db3945d68d70c0c40eeaef6053dc105f33b3cd9cf73590415241f51b97d1f958.png
df
1 2 3
0.00000 90 90 90
0.01002 89.298597 88.597194 87.895792
0.02004 88.604222 87.222501 85.854836
0.03006 87.916805 85.875357 83.875232
0.04008 87.236276 84.555209 81.955134
... ... ... ...
4.95992 20.478815 20.003113 20.000019
4.96994 20.474017 20.003051 20.000019
4.97996 20.469268 20.00299 20.000018
4.98998 20.464565 20.00293 20.000018
5.00000 20.45991 20.002871 20.000017

500 rows × 3 columns

Nakonec je vhodné všechny části seskupit do jedné buňky. Zpravidla totiž pojmenováváme objekty pořád stejně, aby se daly recyklovat útržky kódu (tabulka -> dataframe -> df, osy -> axes -> ax, obrázek -> figure -> fig) a takto nedojde ke kolizi mezi názvy.

N = 500
t = np.linspace(0,5,500)
k_values = [1,2,3]
T_okoli = 20

df = pd.DataFrame(index=t, columns=k_values)
df.iloc[0,:] = 90
for k in k_values:
    T = df[k].values
    for i in range(N-1):
        dt = t[i+1] - t[i]
        T[i+1] = T[i] - dt*(T[i]-T_okoli)*k
ax = df.plot()
ax.set(ylim=(0,None), title="Model ochlazování")
ax.legend(title="Parametr k")
# df.to_excel("data.xlsx")
df
1 2 3
0.00000 90 90 90
0.01002 89.298597 88.597194 87.895792
0.02004 88.604222 87.222501 85.854836
0.03006 87.916805 85.875357 83.875232
0.04008 87.236276 84.555209 81.955134
... ... ... ...
4.95992 20.478815 20.003113 20.000019
4.96994 20.474017 20.003051 20.000019
4.97996 20.469268 20.00299 20.000018
4.98998 20.464565 20.00293 20.000018
5.00000 20.45991 20.002871 20.000017

500 rows × 3 columns

../_images/9bd900f12aa8e82e75602beede2ff20dceac4724a13451c75b9d7db9bfe80095.png