Po hackathonu
Kapitola I - Nové MVP (minimum viable product)
Po hackathonu bylo jasné, že musíme naše téma trochu “polidštit”, tedy nesoustředit se pouze na procesní a odbornou část, ale najít i způsob, jak téma více objasnit všem. Hlavně najít nový přínos celého našeho počínání, protože původní zelené pole se stalo díky kvalitě zaznamenávání na hony vzdáleným. Po dvou téměř bezesných nocích přišel “spásný” nápad v podobě sledování doplatků.
Vždyť přece každý se dokáže ztotožnit se situací, že jde do lékárny pro lék a pořád po něm chtějí nějaké peníze.
Rozhodly jsme se tedy zanalyzovat teoretické doplatky na receptová léčiva v jednotlivých ATC (anatomicko-terapeuticko-chemické) skupinách, kde bychom potom vytipovaly takové léky, které mají vysoký teoretický doplatek a zároveň jsou hodně používané a u těch by se pak dala právě pomocí správních řízení (pokud už na daný kód neběží správní řízení stejného typu) zahájit změna maximální ceny tak, aby se snížil doplatek pro pacienty, pokud by z vnější cenové reference vycházely nižší ceny pro daný přípravek.
Pro splnění úkolu tedy bylo opět nutné “naskladnit” si tabulky do Kebooly, a to konkrétně aktuální SCAU (květen), pojmenování ATC skupin a počty vydaných balení za rok 2018 (DIS-13) a nahrát si je do transformace.
Opět bylo potřeba vyčistit data v souborech a provést výpočty, tentokrát ale byl tento krok jednodušší, protože jsme si ho už jednou vyzkoušely. To ovšem ničemu nevadilo a do cesty nám přišly nové datové pastičky a mimo ně i pastičky, u kterých vůbec netušíme důvod, jako třeba split window ve snowflaku a zmizení kurzoru. Naštěstí v devátém týdnu už není moc sil se rozčilovat a tak jste vděční, že můžete pracovat aspoň s půlkou okna a kurzor raději nepotřebujete. K tomuto rozhodnutí pak značně přispívá i fakt, že jakmile googlíte cokoliv se snowflakem, tak vám prohlížeč nabízí zpět povídání o sněhových vločkách a vánočních přáních.
Poté už stačilo jenom zavařit trochu mozeček nad joinováním a vytvořit finální tabulku pro vizualizaci a ověřit, že je vše na svém místě.
Po trablech na hackathonu už tato transformace proběhla zcela hladce a zbývalo si tedy nahrát výsledný soubor do writeru a udělat posledních pár úprav - vyfiltrovat si receptové léky (limit NULL, E a L) a typ cenové regulace MCV (to znamená, že lék je regulován maximální cenou). Dále si vybrat sloupce, které chceme a napojit je na tabulku správních řízení, abychom věděly, jestli u daného léku správní řízení o změně maximální ceny neprobíhá.
No a z writeru hurá do Tableau a vizualizovat zjištěné, kdy výsledkem jsou dva grafy. Na prvním můžeme vidět, ve kterých ATC skupinách jsou největší teoretické průměrné doplatky na receptové léky (Cytostatika a imunomodulační léčiva).
Na druhém znázornění si pak můžeme filtrovat a hledat v jednotlivých ATC skupinách, kdy v bublinovém grafu se nám při dostatečně jemném vyfiltrování ukáží i konkrétní léky s nejvyšším doplatkem, tedy kandidáti na snížení maximální ceny. Z důvodu velikosti je vizualizace dostupná v sekci Datovka -> Vizualizace nebo na Tableau Public.
Na závěr kapitoly bychom ještě chtěly podotknout, že v textu i vizualizacích je operováno se slovíčkem “teoretický” z důvodu, že SÚKL stanovuje strop pro maximální cenu. Za jakou cenu, jestli stejnou nebo nižší, bude reálně lék možné prodávat, je pak v rukou distributora a lékárny.
Kapitola II - My se nevzdáme
Na náš původní cíl jsme ale ani po všech lapáliích nezapomněly a rozhodly jsme se, že když nemáme data v podobě, v jaké chceme, tak si taková data vytvoříme. Ve výsledku pak budeme schopné získat potřebný obrázek o správních řízeních díky naší nově vytvořené databázi. Tím jsme vlastně zlehka navázaly i na původní myšlenky z fialového pole, kde by vytvoření nové databáze tvořilo základ pro možnost plánovaných notifikací.
Po konzultaci s Danem jsme věděly, že se vracíme zase zpátky k Pythonu a pro potřeby databázové a SQLkové budeme využívat SQLite tak, abychom byly schopné s naším výtvorem pracovat i po skončení DA. Novým cílem tedy bylo vytvořit si dvě databáze, které nám umožní sledovat stavy jednotlivých řízení v čase a ne pouhý konec a začátek, kdy vše mezitím je zpětně už neznámá. Přesně toto by pak v budoucnu vyřešilo problém s nemožností určení délky správního řízení, protože bychom znaly i historii řízení a data, kdy došlo ke změnám.
Nejprve jsme si tedy v SQLite vytvořily tabulku přehled_sř_základ, kde kombinace spisová značka a kód_LP (léčivého přípravku) tvoří unikátní index a ID představuje autoinkrementální primární klíč, a tabulku historie_stavu, která je přes index přehled_ID napojená na ID tabulky přehled_sř_základ, čímž je zajištěna provázanost tabulek.
Idea je taková, že vytvoříme prográmek v Pythonu, který každý den stáhne přehled sř ze stránek SÚKL, odzipuje soubor, porovná přírůstkové změny oproti minulému souboru, přírůstky zapíše do tabulky přehled_sř_základ a řádky, které se oproti minulému záznamu změnily přepíše (zejména sloupec datum_NPM). Poté se porovná změna stavu správního řízení (sloupec Stav v tabulce historie_stavu) a pokaždé, když dojde ke změně stavu u ID z tabulky přehled_sř, tak se nový stav zapíše do tabulky historie_stavu s datem dne, kdy ke změně došlo.
Právě díky tabulce historie_stavu bude možné sledovat v čase průběh správních řízení a umožní i do budoucna rozklíčovat, kdy bylo rozhodnutí předběžně vykonatelné, kdy došlo k odvolání na ministerstvo a další věci, které negativně ovlivňují délku správního řízení.

Poté, co jsme společně s Danem vytvořili postup, nás čekalo začít postupně kódit jednotlivé kroky. Po takové době strávené prací mimo Python to bylo zase trošku jako nové seznámení, když jsme na příkazovou řádku psaly věci určené spíš pro SQL. Brzy jsme se ale na Python zase naladily a mohly začít naplno.
K práci jsme používaly pouze zkušební vzorek přehledu sř a abychom mohly změny dobře pozorovat, pocházel náš původní soubor z měsíce dubna a změnový soubor z měsíce květen. Během práce se ale zase a zase projevovalo, že vůbec nemáme krásná, čistá data, jak jsme si myslely, a skoro každá část kódu, které měla potenciálně fungovat, na svém konci vyhodila špatný shape, kde neseděly počty řádků a sloupců.
Vzhledem k tomu, že po Hackathonu zbývaly na reálnou práci na projektu všehovšudy už jen tři týdny a to ještě s vnořenou pauzou na test a psaní blogu, nezbylo než ustoupit trochu ze své datové hrdosti a dát prostor i “prachobyčejnému” excelu, v němž jsme ověřovaly právě ony malé podivnůstky, jako třeba duplikáty v základních souborech nebo že v dubnovém souboru bylo 1241 řádků a v květnovém 1336. Po spojení těchto dvou tabulek a použití funkce dropduplicates ovšem zbylo 111 řádků místo 95 řádků, jak by velela odvěká logika odečítání. Takto padla naše jistota toho, že s každou novou verzí přehledu_sř budou řádky jedině přibývat a ne ubývat. Rozhodně to není něco, co chcete zjistit ani ne dva týdny do konce projektu!
Řešením tohoto problému se zdálo být přidání sloupce “Origin”, v kterém by bylo zaznamenáno, z jakého souboru záznam pochází, zda z původního (tedy pro nás sqlite) nebo z nového - tedy excel. Návazný logický krok pak byl najít funkci, která nám ze spojeného souboru původní a nové tabulky očištěné od duplikátů vymaže záznamy, které mají označení sqlite (tedy úbytkové řádky). Ani toto se ovšem neobešlo bez problému, protože jsme zjistily, že funkce odmazává řádky podle indexu a jeden index se v našem souboru mohl vyskytovat klidně vícekrát, protože při pandas.concat si python ponechá jako index původní označení indexů. Situace je to sice nemilá, ale ten pocit, že víte, co se děje, protože si pamatujete Martinovu lekci pandas: základní dotazy, kde byla o indexech řeč, je neuvěřitelný. Najednou se totiž zdá, že už to není tak, že jen někde z internetů splácáme dohromady kód a čekáme, co se stane, ale že si i začínáme jednotlivé dílky propojovat, i když samozřejmě pořád stojíme na prvním schůdku.
Za pomoci Dana pak dáváme dohromady celý fungující kód (tedy rozložený do několika, protože fáze učení musí probíhat po kouscích i přes nápadnou ošklivost vytvořených kódů) a dokonce stíháme i web scraping, abychom nemusely stahovat každý den soubor ručně.
Ukázka kódu zaznamenávajícího změnu stavu: zde

Zde je názorná ukázka naší databáze:
