Na naucse.python.cz bohužel nefunguje zobrazování interaktivních plotly grafů. Pro zobrazení včetně grafů můžeš použít nbviewer: https://nbviewer.jupyter.org/github/coobas/pydataladies-dashboard/blob/main/notebooks/dashboardy-1.ipynb nebo si notebook pustit lokálně. Všechny soubory pohromadě najdeš v repozitáři https://github.com/coobas/pydataladies-dashboard.
Při práci s daty je mnoho příležitostí, kdy se hodí interaktivita. Při vizualici se hodí zvětšování / změnšování měřítka, výběr podoblasti, ukázání vykreslených hodnot apod. Nebo při datové anlýze obecně se může hodit interaktivně v notebooku měnit nějaký parametr (třeba hyperparametr pro strojové učení). Anebo chceme dát výsledky naší skvělé analýzy k dispozici "netechnickým" kolegům nebo kamarádům, kteří (zatím) nedokáží Jupyter notebook spustit.
Tady si ukážeme, jak si s takovými úkoly poradit pomocí dvou nástrojů: plotly, resp. především plotly express, a streamlit.
Existují i další nástroje, které poskytují podobné možnosti. Podrobný přehled najdete na https://pyviz.org/tools.html. Na interaktivní vizualizace jsou to především holoviews nebo altair. Na "dashboarding" pak dash, panel, voila nebo justpy.
Každý z těchto nástrojů má, jako obvykle, své výhody a nevýhody. Nejrozšířenějším nástrojem je Dash ze stejné dílny jako plotly, který poskytuje i enterprise řešení pro provoz aplikací. Dash je určitě dobrou volbou, jak se můžete dozvědět i na přednášce z pražského PyData Meetupu. Panel (a také Voila) se od Dash liší tím, že je lze použít i v Jupyter notebooku a pak notebook použít přímo jako aplikaci. Největší přednost voila je jednoduchý způsob, jak udělat dashboard přímo z notebooku: viz dokumentace.
Dvě největší výhody Streamlitu jsou rychlost (jednoduchost) vývoje aplikace a atraktivní výchozí vzhled.
Pár článků či přednášek, které se tématu týkají:
Je potřeba ale říct, že všechny zmíněné přístupy mají své výrazné nevýhody a limity a nehodí se pro velké a složité aplikace. Možnosti interakcí v aplikaci jsou omezené a také mohou být pomalé. Robustní škálování pro mnoho uživatelů (velký provoz) je obecně složitější. Kdy tedy především použít, co si tady ukážeme?
A co když chceme budovat velkou (webovou) aplikaci?
Pokud nemáte nainstalovanou knihovnu plotly, odkomentujte a spusťte příslušné řádky.
# instalace plotly
# %pip install plotly
Pro plotly express se vžila zkratka px, kterou použijeme i my.
import plotly.express as px
Pojďme si zkusit trochu více prohlédnout data, se kterými jsme pracovali v předchozích lekcích na strojové učení.
Začněme rozměry ryb, na kterých jsme ukazovali regresi a klasifikaci. Určitě stojí za to si data nejprve trochu prohlédnout. (Jen si asi nenakreslíme přímo vzhled ryb, na to nám data nestačí :)
import pandas as pd
fish_data = pd.read_csv("fish_data.csv", index_col=0)
A místo klasického zobrazování čísel si zkusíme rovnou data vykreslit do grafu. Víme (tušíme), že v datech je spousta sloupců. Můžeme si je nechat vykreslit všechny pomocí scatter_matrix.
px.scatter_matrix(fish_data)
To vůbec není špatné na prvotní orientaci. Už teď je vidět, že tam máme katogorickou proměnnou Species, nějaké spojité proměnné s rozměry a nepodstatné ID. Vidíme také, že některé proměnné spolu hodně korelují.
Už teď bychom mohli využít interaktivních prvků: zkuste si najet kurzorem na body v grafu nebo použít nástroje na změnu měřítka nebo výběr dat, které se zobrazí v pravém horním rohu. Ještě lepší bude ale trochu graf zlepšit: Zahodit ID a druhy si označit barvou.
px.scatter_matrix(
fish_data,
dimensions=["Weight", "Length1", "Length2", "Length3", "Height", "Width"],
color="Species",
opacity=1,
hover_data=["Species"],
)
Tady nám kromě barevnosti přibyla vpravo legenda. A dokonce legenda interaktivní! Jednoduchým kliknutím můžeme schovat / zobrazit jednotlivé kategorie, dvouklikem můžeme zobrazit jen jednu kategorii. Zkuste si to! Užitečné může být i vybírání dat - Box Select nebo Lasso Select.
Úkol: Použijte pro barvu sloupec Weight, symboly udělejte částečně průhledné pomocí argumentu opacity (rozsah 0 - 1) a v legendě, zobrazované, když se najede kurzorem na určitý bod, nechť se zobrzují všechny sloupce (pomůže argument hover_data).
Když se pak chceme třeba podívat na statistické vlastnosti jedné konkrétní proměnné (sloupce), můžeme použít některou z funkcí na zobrazení rozdělovací funkce, resp. některých jejích vlastností (momentů).
Začít můžeme poměrně častým box plotem. Bonus plotly je hlavně v interaktivním zobrazení číselných hodnot: mediánu a kvantilů, a také identifikaci (pravděpodobně) odlehlých hodnot.
px.box(fish_data, x="Species", color="Species", y="Height", points="all", notched=False)
px.histogram(fish_data, color="Species", x="Height", opacity=0.5)
Pro zobrazení vztahu dvou proměnných může být ještě užitečné podívat se na hustotu bodů v ploše pomocí kontur. U tohoto grafu můžeme po stranách zobrazit i tzv. marginální rozdělení: nejpravděpodobnější rozdělení jedné proměnné v závislosti na druhé.
px.density_contour(
fish_data,
color="Species",
x="Height",
y="Length3",
marginal_x="histogram",
marginal_y="box",
)
Úkol: Zkuste si zobrazit v grafech jiné veličiny (jiné sloupce) než jen Height a Width. Zkuste změnit typ marginálních grafů.
Máme i kolegy, kteří (ještě) nepoužívají Python a přesto by ocenili, kdyby mohli místo statického reportu dostat report s takto krásnými a interaktivními vizualizacemi. Pro tento účel se hodí export notebooku do html pomocí nbconvert.
V příkazovém řádku spustíme nbconvert pomocí příkazu jupyter nbconvert. Pro export do html pak přidáme --to html, nesmíme zapomenout zadat který notebook (tj. soubor) chceme vlastně konvertovat.
# Odkomentováním se spustí příkaz v příkazové řádce (díky vykřičníku)
# Možná se seoubor u tebe jmenuje jinak než dashboardy-1, v takovém použij aktuální jméno souboru
# !jupyter nbconvert dashboardy-1.ipynb --to html
Můžeme také exportovat jen výstupy a "utajit" zdrojový kód pomocí --no-input:
# !jupyter nbconvert dashboardy-1.ipynb --to html --no-input
Všem se naše vizualizace líbily, a jelikož je potřeba analyzovat další data, dostali jsme to za úkol my. Tentokrát se nejedná o ryby, ale o tučňáky.
Úkol: Vyber si z grafů ten, který se ti nejvíc líbí, a místo rybích dat použij tučňáky.
penguins = pd.read_csv("penguins_size_nona.csv")
Z naší práce v notebooku vykrystalizoval velice častý vzor: Podobné vizualizace a analýzy, v nichž se mění data a několik klíčových parametrů. Příležitost vytvořit aplikaci, která toto umožní nám a okruhu poučených uživatelů.
Pojďme si nadefinovat naší jednoduchou aplikaci:
Pojďme to nejprve načrtnout tady v notebooku. Jako první si připravíme uživatelské vstupy.
# vstup 1: výběr datové sady
data_file_path = "penguins_size_nona.csv"
# vstup 2: výběr parametrů scatter matrix
dimensions = ['culmen_length_mm', 'culmen_depth_mm', 'flipper_length_mm', 'body_mass_g']
color = "sex"
opacity = 0.5
# výběr sloupce pro zobrazení rozdělení dat
interesting_column = "body_mass_g"
# výběr funkce pro zobrazení rozdělovací funkce
dist_plot = px.violin
A tohle už je pak naše aplikace: Použili jsme stejné funkce a parametry jako na začátku práce s plotly, jen jsme je parametrizovali pomocí vstupů z předchozího bloku.
# načtení dat
data = pd.read_csv(data_file_path)
# scatter matric plat
px.scatter_matrix(data, dimensions=dimensions, color=color, opacity=opacity)
# zobrazení rozdělovací funkce
dist_plot(data, x=interesting_column, color=color)
A teď z toho pojďme udělat interaktivní webovou aplikaci! To nebudeme dělat přímo tady v notebooku, ale v "obyčejném" .py souboru s Python kódem.
Aplikaci máme připravenou v souboru app.py, tady v notebooku si soubor můžeme prohlédnout:
%cat ../app.py
Základem je, že uživatelské vstupy jsme předělali z podoby proměnná = hodnota do podoby proměnná = st.vhodný_widget(...). Toto je způsob vytváření streamlit aplikace:
st.nějaký_widget, Streamlit se postará o to, aby widget správně fungoval a návratová hodnota byla vždy ta aktuální.st.write.Widgets - pomocné "věcičky": V uživatelských grafických rozhraních (GUI) se používají widgety: nástroje na vybrání možností, hodnoty proměnné, zadání textu nebo datumu apod.
Streamlit ještě nejspíš nemáš nainstalovaný. Instaluje se běžným způsobem přes pip:
pip install streamlit
případně pokud používáš conda
conda install -c conda-forge streamlit
Na svém počítači si pak apikaci spustíš příkazem streamlit run s názvem souboru s aplikací. V našem případě tedy
streamlit run app.py
Pokud je vše v pořádku, zobrazí se něco takovéhoto:
You can now view your Streamlit app in your browser.
Network URL: http://192.168.2.103:8800
External URL: http://85.207.123.46:8800Dle instrukcí otevři odkaz (ten první) v prohlížeči. Je velká pravděpodobnout, že se objeví naše právě vytvořená aplikace na vizualizaci dat.
V principu bychom mohli spustit aplikaci u sebe na počítači tak, aby ji mohli používat i další uživatelé. Na vnitřní síti (domácí, pracovní) by to bylo snadné (i když na pracovní síti a pracovním počítači by tomu mohla bránit bezpečnostní nastavení), přístup z vnějšího internetu by už byl komplikovanější.
Naštěstí nejsme v podobné situaci sami :) Takže existují více či méně složité a sofistikované způsoby, jak aplikaci spustit na nějakém serveru (v cloudu) a zpřístupnit z internetu. My si ukážeme, jak to funguje na Heroku. Podobné služby nabízí třeba AWS (Elastic Beanstalk), Google App Engine nebo Dokku on Digital Ocean. Výhodou Heroku je jednoduchost a možnost bezplatných služeb, nevýhodou pak rychle rostoucí cena a omezené možnosti.
Existuje také možnost publikovat aplikaci pomocí Streamlit Sharing. Tato služba nabízí ještě jednodušší publikaci z veřejných GitHub repozitářů, nemá ale tolik možností jako např. Heroku.
Budeme postupovat v podstatě podle průvodce Getting started with Python.
Než začneme, je potřeba:
git config --global user.name "Moje Jméno"
git config --global user.email "muj@email.com"Instalaci ověříme v příkazové řádce pomocí:
Git:
git config --listMělo by se objevit něco na způsob
user.name=Moje Jméno
user.email=muj@email.comHeroku:
heroku --versionTady by mělo být výstupem zhruba
heroku/7.39.2 darwin-x64 node-v12.13.0Teď budeme chvilku pracovat v příkazové řádce. Nejprve je potřeba vytvořit novou složku pro publikovanou aplikaci a nakopírovat tam soubory app.py, requirements.txt, runtime.txt a Procfile.
A teď už v příkazové řádce, kde aktuální složka musí být ta nově vytvořená, kam jsi zkopírovala soubory:
Vytvoř Git repozitář:
git initHeroku potřebuje soubor s názvem Procfile. Ten velice jednoduše říká, co že to vlastně chceme spustit. Bude tam příkaz streamlit run (tak jako jsme spouštěli aplikaci lokálně) s pár přepínači navíc. Pro Procfile musí obsahovat tento řádek:
web: streamlit run --server.headless 1 -server.port $PORT app.pyJe určitě dobré specifikovat verzi Pythonu, jinak se použije výchozí (v době psaní je to 3.6). V souboru runtime.txt na to stačí řádka python-3.8.10.
Dalším souborem, který potřebujeme, je requirements.txt. O tom jste už možná slyšeli(y) - obsahuje seznam Python balíčků, které potřebuje daný Python projekt. Heroku tento soubor použije, aby před spuštěním aplikace nainstaloval vše potřebné. Pro náš dashboard musí být v requirements.txt toto:
pandas==1.2.4
streamlit==0.82.0
plotly==4.14.3Soubory už máme připravené, potřebujeme je teď přidat do Git repozitáře. Na to použij tyto dva příkazy:
git add app.py Procfile runtime.txt requirements.txt
git commit -v -m "první verze dashboardu"A teď už můžeme publikovat. Tedy nejdříve se přihlásit pomocí
heroku login(Postupujte dle pokynů - otevře se přihlašovací stránka ve webovém prohlížeči, která vás vyzve k zadání přihlašovacích údajů.)
Pak ještě vytvořit Heroku aplikaci pomocí
heroku createA nakonec už opravdu vypustit aplikaci na internet pomocí
git push heroku masterPokud vše půjde dobře, tento krok bude chvíli trvat. Postupně se bude vypisovat, co pro nás Heroku dělá:
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 4 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 940.72 KiB | 2.40 MiB/s, done.
Total 4 (delta 2), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Python app detected
remote: -----> Installing python-3.8.6
remote: -----> Installing pip 20.1.1, setuptools 47.1.1 and wheel 0.34.2
remote: -----> Installing SQLite3
remote: -----> Installing requirements with pip
remote: Collecting pandas==1.1.4
remote: Downloading pandas-1.1.4-cp36-cp36m-manylinux1_x86_64.whl (9.5 MB)
remote: Collecting streamlit==0.71.0
remote: Downloading streamlit-0.71.0-py2.py3-none-any.whl (7.4 MB)
remote: Collecting plotly==4.13.0
remote: Downloading plotly-4.13.0-py2.py3-none-any.whl (13.1 MB)
...Nakonec by se mělo objevit něco jako
remote: -----> Launching...
remote: Released v6
remote: https://warm-sierra-79844.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/warm-sierra-79844.gitDůležitý je odkaz pod řádkem "Released v6". To je totiž adresa, na které je náš dashboard dostupný "odkudkoli z internetu". Buď si ji zkopírujte do prohlížeče nebo použijte příkaz heroku open.
Úkol 1: Pošli odkaz na tvou běžící aplikaci :)
Úkol 2: Pomocí st.title přidej titulek (název) aplikace. Vyzkoušej u sebe lokálně, pak změnu commituj do gitu a aktualizuj aplikaci na Heroku (pomocí git push heroku master).