#!/usr/bin/env python # coding: utf-8 # *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.* # # # # Interaktivní vizualizace a aplikace # # Při práci s daty je mnoho příležitostí, kdy se hodí interaktivita. Při vizualici se hodí zvětšování / zmenšování měřítka, výběr podoblasti, ukázání vykreslených hodnot apod. Nebo při datové analý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](https://plotly.com/python/), resp. především [plotly express](https://plotly.com/python/plotly-express/), a [streamlit](https://www.streamlit.io/). # # 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](http://github.com/pyviz/holoviews) nebo [altair](http://github.com/altair-viz/altair). Na "dashboarding" pak [dash](http://github.com/plotly/dash), [panel](https://panel.holoviz.org/), [voila](http://github.com/QuantStack/voila), [vizro](https://github.com/mckinsey/vizro) nebo [justpy](https://justpy.io). # # Velmi atraktivní novinkami jsou [JupyterLite](https://github.com/jupyterlite/jupyterlite) a [PyScript](https://pyscript.net). Oba projekty těží z možnosti spustit Python kód přímo ve webovém prohlížeči, konkrétně v jeho virtuálním stroji, díky technologie Web Assembly. # * JupyteLite umožňuje spustit Jupyter notebooky v prohlížeči, bez nutnosti instalace Pythonu, a to včetně knihoven na zpracováni dat jako jsou NumPy, Pandas apod. Více se můžeš dozvědět také z přednášky na pražském PyData meetup: [Jeremy Tuloup - JupyterLite: Jupyter ❤️ WebAssembly ❤️ Python (slides, video)](https://pydata.cz/#jeremy-tuloup---jupyterlite-jupyter-%EF%B8%8F-webassembly-%EF%B8%8F-python-slides-video). # * PyScript umožňuje vložit Python kód přímo do HTML kódu a tímto způsobem vytvářet interaktivní webové aplikace přímo V Pythonu. PyScript tak vlastně "nahrazuje" JavaScript. # # Každý z těchto nástrojů má, jako obvykle, své výhody a nevýhody. Nejrozšířenějším nástrojem je [Dash](http://github.com/plotly/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](https://www.youtube.com/watch?v=dewrzMPPLDU). 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](https://voila.readthedocs.io/en/stable/using.html). # # Dvě největší výhody Streamlitu jsou rychlost (jednoduchost) vývoje aplikace a atraktivní výchozí vzhled. Streamlit také (nedávno) přidal možnost vzájemné interakce mezi widgety pomocí callback funkcí. Pro Streamlit lze také poměrně snadno vytvářet nové komponenty, důkazem toho budiž [galerie komponent](https://streamlit.io/components). # # Pár článků či přednášek, které se tématu týkají: # * [Dash, Voila, Panel, & Streamlit—Our Thoughts on the Big Four Dashboarding Tools](https://quansight.com/post/dash-voila-panel-streamlit-our-thoughts-on-the-big-four-dashboarding-tools) # * [Pure Python Web Development](https://metaperl.github.io/pure-python-web-development/intro.html) - velký přehled knihoven pro webový vývoj v Pythonu. # * [Streamlit - The fastest way to build and share data science apps](https://www.youtube.com/watch?v=sdgTYy3BJiM) # * [How to Build a Reporting Dashboard using Dash and Plotly](https://towardsdatascience.com/how-to-build-a-complex-reporting-dashboard-using-dash-and-plotl-4f4257c18a7f) # * [Turn any Notebook into a Deployable Dashboard | SciPy 2019 | James Bednar](https://www.youtube.com/watch?v=L91rd1D6XTA) # # ## Pro a proti # # 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? # * Na malou aplikaci pro omezený počet uživatelů (dashboard pro kolegy). # * Na rychlý vývoj prototypu. # # A co když chceme budovat velkou (webovou) aplikaci? # * Zadáme vývojářskému týmu, aby v moderních JavaScript nástrojích typu React nebo Vue.js pro nás vytvořil krásný a rychlý "front-end", zatímco my vytvoříme v Pythonu "back-end", který s front-endem bude komunikovat např. pomocí JSON API. To uvidíme i v naší lekci o API. # * Když takový tým nemáme, naučíme se programovat v JavaScriptu ... Ne, raději v TypeScriptu ... Zkusíme PyScript ... # * ... nakonec najmeme front-end vývojářský tým pokud je to možné :-) # # ## Instalace a import grafických knihoven # # Pokud nemáte nainstalovanou knihovnu plotly, odkomentujte a spusťte příslušné řádky. # In[1]: # instalace plotly # %pip install plotly # Pro plotly express se vžila zkratka `px`, kterou použijeme i my. # In[2]: import plotly.express as px # In[3]: import plotly.io as pio # from https://github.com/microsoft/vscode-jupyter/issues/6999 # This ensures Plotly output works in multiple places: # plotly_mimetype: VS Code notebook UI # notebook: "Jupyter: Export to HTML" command in VS Code # See https://plotly.com/python/renderers/#multiple-renderers pio.renderers.default = "plotly_mimetype+notebook" # notebook-only does not work in Jupyter Lab # pio.renderers.default = "notebook" # ## Interaktivní vizualizace dat # # 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í. # ### Rybí míry # # 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čí :) # In[4]: import pandas as pd # In[5]: fish_data = pd.read_csv("fish_data.csv", index_col=0) # In[6]: species_cs = { "Bream": "Cejn", "Roach": "Plotice", "Whitefish": "Bílá ryba", "Parkki": "Karas", "Perch": "Okoun", "Pike": "Štika", "Smelt": "Koruška", } fish_data = fish_data.assign(Species=fish_data["Species"].map(species_cs)) # 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`. # In[7]: px.scatter_matrix(fish_data) # To vůbec není špatné na prvotní orientaci. Už teď je vidět, že tam máme kategorickou 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. # In[8]: 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. # In[9]: px.box(fish_data, x="Species", color="Species", y="Height", points="all", notched=False) # In[10]: 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é. # In[11]: 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ž Height a Width. Zkuste změnit typ marginálních grafů. # ## Co s tím dál? # ### Report pro šéfa a šéfovou # # 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. # In[12]: # Odkomentováním se spustí příkaz v příkazové řádce (díky vykřičníku) # Možná se soubor 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`: # In[13]: # !jupyter nbconvert dashboardy-1.ipynb --to html --no-input # ### Analýza nových dat # # 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. # In[14]: penguins = pd.read_csv("penguins_size_nona.csv") # ## Vytváříme aplikaci # # 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: # 1. Načíst data z csv souboru. # 2. Vykreslit scatter matrix, kde budu moct zvolit dimenze, sloupec pro barvu a průhlednost. # 3. Pro vybraný sloupec zobrazit distribuci vybraného sloupce pomocí histogramu, box plotu nebo violin plotu. # ### Příprava v notebooku # # Pojďme to nejprve načrtnout tady v notebooku. Jako první si připravíme uživatelské vstupy. # In[15]: # 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. # In[16]: # načtení dat data = pd.read_csv(data_file_path) # In[17]: # scatter matric plat px.scatter_matrix(data, dimensions=dimensions, color=color, opacity=opacity) # In[18]: # 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: # In[19]: get_ipython().run_line_magic('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: # * Aplikaci píšeme v podstatě jako lineární skript (zdrojový kód samozřejmě můžeme strukturovat do funkcí / modulů / tříd dle vlastního uvážení, streamlit ale bude aplikaci vždy spouštět krok po kroku jako ten skript). # * Uživatelské vstupy načítáme z návratové hodnoty funkcí `st.nějaký_widget`, Streamlit se postará o to, aby widget správně fungoval a návratová hodnota byla vždy ta aktuální. # * Prvky aplikace (výstupy) zobrazíme uživateli pomocí `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. # # ### Spuštění # # Streamlit ještě nejspíš nemáš nainstalovaný. Instaluje se běžným způsobem přes pip: # # pip install streamlit==1.28.2 # # případně pokud používáš conda # # conda install -c conda-forge streamlit=1.28.2 # # Na svém počítači si pak aplikaci 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:8800 # ``` # # Dle 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. # ## Publikujeme na internet # # 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 [Streamlit Cloud](https://streamlit.io/cloud), což je možná nejjednodušší způsob publikace Streamlit aplikace z GitHub repozitáře. Oproti obecnějším službám má pochopitelně méně možností a funguje pouze pro Streamlit. # # Pro sofistikovanější aplikace je pak možné použít některou z PaaS (Platform as a Service) služeb typu Render, Heroku, AWS Elastic Beanstalk, Google App Engine, Digital Ocean Apps. Některé z těchto služeb mají i zajímavé bezplatné plány nebo kredit pro nové uživatele. # ### Registrace na Streamlit Cloud # # Než začneme, je potřeba: # 1. Github účet a Git klient: viz [README - Příprava](../README.md#příprava). # 2. Použij svůj GitHub účet pro registraci na Streamlit Cloud: https://share.streamlit.io/signup # # # # ### Specifikace prostředí # # Aby bylo jasné, jaké Python balíčky jsou potřeba pro naši aplikaci a tím si ji kdokoli mohl spustit, vytvoříme soubor [`requirements.txt`](https://pip.pypa.io/en/stable/reference/requirements-file-format/). Ten může použít buď lidský uživatel nebo platforma typu Streamlit Cloud. # # V souboru `requirements.txt` potřebujeme mít (alespoň) základní balíčky pro spuštění aplikace: # ``` # pandas==2.1.3 # streamlit==1.28.2 # plotly==5.18.0 # ``` # * Je lepší specifikovat konkrétní verzi, protože novější nebo starší verze nemusí být kompatibilní. # * Ideální je specifikovat všechny závislosti včetně "tranzitivních", tj. závislosti závislostí (... závislostí ...). Pro zjednodušení tohoto úkolu existují pomocné nástroje, např. [Poetry](https://python-poetry.org), [pip-tools](https://pypi.org/project/pip-tools) a další. My si zatím vystačíme s jednoduchým `requirements.txt` souborem. # # Tento soubor umí použít `pip`: Pro instalaci balíčků stačí spustit # ``` # python -m pip install -r requirements.txt # ``` # ### Publikace na GitHub # # #### 1. Vytvoř nový GitHub projekt: # # * Vytvoř nový projekt na [github.com](https://github.com) # # # # * Vyber vhodné jméno. # * Můžeš použít soukromý i veřejný projekt. # * Přidej Python `.gitignore` soubor z nabídky. # * Můžeš přidat i README soubor. # # #### 2. Naklonuj projekt k sobě na počítač # # Po vytvoření projektu se objeví instrukce na naklonování (nahrání) projektu na tvůj počítač. Použij například `gh` v příkazové řádce. # # #### 3. Přidej soubory s aplikací # # Do projektu přidej soubory s aplikací, tedy `app.py` a `requirements.txt`. Poté je přidej do Gitu a udělej commit: # # ``` # git add app.py requirements.txt # git commit -m "První verze aplikace" # ``` # # #### 4. Nahraj na GitHub # # Nahraj změny na GitHub pomocí `git push`. # ``` # git push # ``` # ### Go-live # # Jakmile máme projekt na GitHubu, je snadné ho publikovat na Streamlit Cloud. Protože jsme pro registraci na Streamlit Cloud použili náš GitHub účet, má Streamlit přístup k našim repozitářům. (Pokud ne, můžeme přístup udělit dodatečně.) # # Pro vytvoření nové aplikace klikni na „New app“, poté vyplň jaký repozitář se má použít a jméno souboru s aplikací - pro nás to je `app.py`. # # Vyber také v sekci Advanced settings verzi Pythonu 3.11. # # # # Podrobný návod najdeš na https://docs.streamlit.io/streamlit-cloud/get-started/deploy-an-app. # # Za chvilku by tvoje aplikace měla být dostupná na internetu 🎉 # # **Ú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 nahraj (`git push`) na GitHub. Tvoje změna by se měla (s drobným zpožděním) projevit i v online verzi.