Materiál k cvičení INS týdny #6-8, sezona 2023/2024
Vytvoření kvalitního a účelného datového modelu je jednou z nejdůležitějších úloh, který může datový analytik vykonat pro své kolegy a uživatele. Vhodný model usnadní orientaci v dostupných datech a značně zjednoduší tvorbu reportů a jejich interpretaci.
Následující text je pojat formou postupného rozšiřování příkladu z předchozích týdnů.
📝 Jako výchozí datový soubor je použit osoby.csv, ve kterém jsou jednotlivé záznamy o pacientech s COVID-19 v ČR. V datasetu jsou vybrány sloupce datum, vek, pohlavi, okres_lau_kod.
📝 Druhým datovým souborem, s kterým se bude pracovat, je číselník NUTS/LAU kódů cz-nuts prevodnik.pdf.
Jak již bylo demonstrováno v Načítání dat v Power BI, lze načíst některé PDF soubory obsahující tabulky a pokusit se data z nich zpracovat. V případě tohoto souboru je potřeba extrahovat dvě (případně tři, pokud chceme i hlavičku) části původní tabulky a spojit je do jedné.
Home → Get Data → More... → PDF File.Table001, Table002, Table004 obsahující hlavičku a dvě části datové matice.Transform Data otevřete okno Power Query editoru.Momentálně jsou data rozdělena do tří query a je potřeba je vhodně sloučit do jedné. Zkontrolujte, že všechny query obsahují stejný počet sloupců a jejich význam je stejný.
Home v sekci Combine zvolte Append Queries → Append Queries as New. Čímž vyvoláme operaci pro sloučení query poskládáním tabulek pod sebe (operace UNION v SQL)Append vyberte možnost spojit více query a do pravé části zvolte vhodné pořadí spojení. Query s hlavičkou Table001 by měla být první z nich.OK.Append1 odkazující na původní 3 zdrojové query.
※ Původní query jsou živé a nelze je odstranit. Změna v původních query se projeví i v odvozené query.
※ Pokud by bylo potřeba spojit tabulky vedle sebe (operace JOIN v SQL), je k dispozici operace Merge Queries.
Momentálně jsou názvy sloupců na druhé řádce sloučené tabulky. Je potřeba nejprve odstranit přebytečné řádky a následně názvy sloupců vynést z datové matice.
Table001 zanechte pouze druhý řádek obsahující názvy sloupců. Home → Keep Rows → Keep Range of Rows → (2, 1).Append1 převeďte první řádek na hlavičku sloupců. Home → Use First Row as Headers.NUTS kód.Pro další práci je potřeba převést číselník do stavu, že primárním klíčem bude sloupec s LAU kódy obsahující pouze okresy, resp. kraje. U každého bude informace o jeho názvu a názvu nadřazeného kraje.
stát, území, oblast.Následujícím krokem je odfiltrování záznamů, které neodpovídají okresu nebo kraji (to jsou takové, které nemají formát CZxxx nebo CZxxxy). Nejjednodušším kritériem bude počet znaků kódu, nicméně tato podmínka není v nabízeném seznamu filtrů. Bude potřeba založit nový odvozený sloupec, který naplníme vhodným výrazem pro výpočet délky kódu.
Append1 vytvořte nový sloupec Add Column → Custom Column.délka_kódu.len vyvolat seznam funkcí, které obsahují tento řetězec. Z nich by následně bylo vybráno Text.Length(). Po najetí kurzoru na název funkce vložené v poli pro výraz se zobrazí popis funkce a očekávané vstupní argumenty.= Text.Length([NUTS kód]).※ Pokud by došlo k problému při výpočtu, bude v příslušné buňce červený text Error a po jeho označení se zobrazí dole detailnější popis chyby.
délka_kódu použijte pro filtrování záznamů s délkou 5 a 6.délka_kódu odstraňte.※ Filtrace je stále platná, protože v posloupnosti operací proběhla v době, kdy sloupec existoval.
Q1: Zkuste pro vytvoření sloupce s délkou kódu použít možnost
Add Column → Column From Examples. Jaký je výsledek?
V dalším kroku je potřeba rozkopírovat název krajů do příslušných záznamů okresů. Abychom si ulehčili práci, je vhodné použít nástroj Transform → Fill → Down, který za každou prázdnou buňku doplní hodnotu nejbližší buňky s existující hodnotu ve stejném sloupci v řádku nad ní. Aby toto v našem případě zapracovalo, je potřeba nahradit prázdný text v buňkách za klíčové slovo "null".
Append1 označte sloupec kraj a pomocí Transform → Replace Values nahraďte prázdné hodnoty za null.kraj a pomocí Transform → Fill → Down doplňte hodnoty do prázdných buněk.Posledním problémem je neaktuálnost dat. Kódy CZ061x a CZ062x již neexistují a byly nahrazeny kódy CZ063x a CZ064x. Jelikož nejsou u nástroje Replace Values k dispozici regulární výrazy, je potřeba si pomoci vytvořením odvozeného sloupce a volbou vhodné funkce Text.Replace(input, old, new).
Append1 vytvořte nový sloupec Add Column → Custom Column.id.= Text.Replace(Text.Replace([NUTS kód], "CZ062", "CZ064" ), "CZ061", "CZ063").※ Výraz nejprve nahradí všechny výskyty CZ062 za CZ064 a následně je aplikována stejná funkce nad novými daty pro záměnu výskytů CZ061 za CZ063.
NUTS kód odstraňte.Append1 na NUTS číselníkClose & Apply v horní části editoru.Nyní by v prostředí PowerBI měla v pravé části být vidět datová tabulka s názvem NUTS číselník obsahující 3 atributy. Kromě toho jsou v modelu vidět i pomocné tabulky. Tyto tabulky lze skrýt kontextovou volbou Enable load nad příslušnou query v Power Query Editoru.
Ze znalosti dat víme, že mezi načtenými tabulkami existuje logická vazba. Konkrétně se jedná o NUTS/LAU kód, který se vyskytuje v obou tabulkách. Abychom tuto expertní znalost předali Power BI, je potřeba přejít do Model view (3. ikona v levém sloupci v hlavním Power BI oknu). Zde vidíme schema ERA modelu. Pro zavedení relace je potřeba přetáhnout název atributu z jedné tabulky na příslušný atribut v tabulce druhé. Většinou se tímto relace vhodně nastaví. Manuálně lze v případě problémů změnit zvolené atributy a kardinalitu relace.
[NUTS číselník].id na atribut osoby.okres_lau_kod.PowerBI by měl automaticky detekovat, že se jedná o 1:N relaci a nastavit ji jako aktivní.
Po zavedení relace je možné ve vizualizaci použít atributy z obou tabulek a příslušné spojení (JOIN) proběhne na pozadí. Lze tedy například vizualizovat počet případů dle názvu kraje či okresu.
Q2: Sestavte vizuál vykreslující počty případů dle názvu kraje. Jsou data vykreslena správně?
Q3: Porovnejte, jak se změní vizuál, pokud by se vazba nastavila jako neaktivní.
Atributy kraj a okres mají v tomto případě zvláštní vzájemný význam - hierarchii. Podobně jako Power BI vytváří automaticky hierarchické členění pro atributy typu datum (rok, kvartál, měsíc, den v měsíci), lze manuálně podobnou hierarchickou strukturu vytvořit i pro tento případ. Vyvoláním kontextové nabídky nad hierarchicky nejvyšším atributem (v tomto případě kraj) a výběrem New Hierarchy se založí pseudoatribut ve stejné tabulce, do kterého lze tažením přiřadit hierarchicky nižší atributy.
※ I když je tato možnost na všech pohledech, z nějakého důvodu funguje přetahování atributů do hierarchie pouze v model view.

Pokud vytvořený pseudoatribut použijeme ve vizualizaci, v její horní části se zobrazí několik nových ikon. První z nich zapíná tzv. drill down mód, což je běžná OLAP operace. V tomto režimu se po kliknutí do vizualizace provede drill down na zvolené podmnožině dat. Například lze takto detailněji zkoumat rozdělení pacientů po jednotlivých okresech Plzeňského kraje. Alternativou k tomuto (ikona dvou paralelních šipek dolů) je hierarchicky sestoupit u všech hodnot, nikoliv pouze u vybrané.
Patrně jste ve vizualizaci zaznamenali výskyt sloupce s popiskem (Blank) při vizualizaci dle krajů či okresů. Jedná se o problém v datech, který nehledě na to, které strana má morální odpovědnost za nesrovnalost, je nutné námi vyřešit. V datech o COVID se udává kód CZ0100 ve smyslu "okres Praha" a tento kód není číselníkem respektován. Ten uvádí pouze kódy CZ0101, CZ0102,... pro městské části Praha 1, Praha 2, ...
Jelikož nemůžeme jednoduše v PDF souboru zavést kód CZ0100, ani není možné rozlišit v COVID datech, do jaké městské části nakažený spadá, je nejpřímočařejší operace založit novou tabulku o rozměrech 1x3 obsahující identické názvy sloupců jako číselník a jednu řádku popisující CZ0100.
Home → Enter Data vytvořte tabulku s názvem praha obsahující sloupce id, kraj, okres a jediný řádek s hodnotami CZ0100, Hl. m. Praha, Praha.NUTS číselník zvolte Append Queries → Append Queries a vyberte query praha pro připojení.praha zrušte možnost enable load.Power Query Editor → Home → Enter Data. Po vytvoření je nutné tabulku připojit k stávajícímu číselníku Power Query Editor → Home → Append Queries.
Q4: Jak se změní vizualizace po přidání nového záznamu do číselníku? Kolik záznamů je nyní v kategorii
(Blank)?
※ Jednotlivé záznamy započítané ve vybraném sloupci lze zobrazit kliknutím na sloupec, nebo obecně prvek vizuálu, a zvolením kontextové nabídky Show data point as table. Tím se otevře nová tabulka, z které se lze vrátit zpět do vizualizace tlačítkem Back to report.
Při řešení datových skladů často dochází, mnohdy spontánně, k tvorbě ERA modelu s paradigmatem hvězdicového, resp. vločkového schematu. V tomto paradigmatu existuje jedna centrální tabulka faktů, které je obklopena tabulkami dimenzí. V našem případě roli faktové tabulky zastupuje seznam COVID případů a první z dimenzních tabulek je dimenze lokační - číselník krajů/okresů. Pokud bychom chtěli pokračovat s modelováním v tomto paradigmatu, je vhodné agregovat data v tabulce faktů. Zde se konkrétně nabízí možnost uvádět souhrnné počty pacientů dle dne, věku, pohlaví a okresu. Transformaci do této podoby je možné provést vhodným provedením Power Query Editor → Home → Group By.
Druhým krokem by bylo převedení hodnot datumu, věku a pohlaví jako reference do dimenzních tabulek.
Běžným postupem bývá pro projekt vytvořit jednu sdílenou dimenzní tabulku obsahující jako záznamy jednotlivé dny a příslušná metadata k nim — například o jaký kvartál se jedná, jestli to je víkend či svátek, atd. Některá z těchto metadat jsou implicitně dostupná v Power BI samotnou volbou datového typu datum.
Pro vyzkoušení vygenerujeme kalendář s informací o tom, zda daný den byl víkendový. Ze znalosti kontextu lze tušit, že tato informace může být v analýze těchto dat významná, protože se o víkendech méně testuje.
Na hlavní obrazovce v report view je možnost založit novou tabulku Modeling → New Table. V příkazovém řádku je potřeba definovat, o jakou tabulku se jedná. Vhodným pozorováním nabízených funkčních volání (případně konzultací manuálu) lze nalézt podezřele pojmenovanou funkci Calendar(). Ta slouží k vygenerování tabulky o jednom sloupci, ve kterém bude posloupnost datumů dle volby uživatele. Konkrétně příkaz cal = CALENDAR("2020-01-01", "2023-12-31") vygeneruje 1461 záznamů odpovídajících datům v letech 2020-2023.
S tabulkou je možné dále pracovat. Při volbě Table Tools → New Column je možné zadat vzorec podobný excelovému víkend = WEEKDAY([Date], 2) > 5, který vrátí pravdivostní hodnotu pravda pro soboty a neděle.
Po nastavení relace v schematu je možné s atributem víkend pracovat ve vizualizacích.
Q5: Vytvořte sloupec
den_v_týdnuobsahující pořadové číslo dne v týdnu. Přidejte možnost zobrazení textového přepisu těchto hodnot.
Q6: Vytvořte vizuál popisující počet případů dle dne v týdnu a barevně rozlišující víkendové dny. Prvky vizuálu intuitivně seřaďte.
Možné řešení je na obrázku níže. Řazení prvků lze provést v kontextové nabídce Sort Axis schované za ikonou nad vizualizací. Řadit lze jen podle dat obsažených ve vizualizaci, v tomto případě počtu případů a názvu dne v týdnu. K řazení podle pořadí dnů v týdnu je potřeba přidat do vizualizace pomocný sloupec obsahující ordinální čísla dnů v týdnu a řadit dle něj. Jelikož se vnitřně jedná o agregaci několika stejných čísel, je potřeba u pomocného sloupce volit funkci Min nebo Max.
Fig — Vizualizace počtu případů dle dne v týdnu. Barevně označená ikona umožňující nastavit pořadí sloupců. Dále označen prostor, do kterého umístit data, podle kterých má být řazeno.
U věků bývá častou operací zařazení záznamu do nějaké věkové skupiny. Tento koncept se často označuje v angličtině jako binning. V Power BI lze tento koncept realizovat pomocí vytvoření nového sloupce, který bude obsahovat výslednou věkovou skupinu. Resp. vhodnějším přístupem bude chápání celočíselného věku jako indexu do dimenzní (převodní) tabulky s věkovými skupinami.
Prvním krokem je založení nové tabulky Modeling → New Table a pomocí volání funkce GENERATESERIES(0, 120, 1) lze poměrně jednoduše naplnit sloupec nově vytvořené tabulky posloupností čísel 0-120 s inkrementem 1.
※ Volba 120 je zvolena jako horní mez věku, protože v datech se vyskytuje nejvyšší hodnota 120.
Přes kontextové menu nad atributem nově vytvořené tabulky v pravé části Power BI rozhraní lze volbou New Group otevřít dialog pro nastavení způsobu seskupení numerických hodnot. Power BI nabízí dva způsoby seskupení — binování a vlastní seznam. Při volbě Group type: Bin lze dále nastavit, kolik rovnoměrných skupin se má vytvořit, případně jak velký má být interval čísel ve skupinách. V našem případě dává smysl vytvořit 12 skupin s intervaly 10 let.
Druhou možností je Group type: List, kdy lze ručně vybrat skupiny z výčtu všech možných hodnot. Bylo by tedy možné tímto způsobem například vytvořit skupiny 0-18, 19-25, 26-40, 41-60, 61-120.
Skupiny lze vytvořit i pomocí vlastní funkce při vytvoření nového sloupce.
Výsledný model by mohl vypadat následovně. 
Kromě informace o tom, zda je den všední nebo víkendový, by mohlo být zajímavé mít informaci o státních svátcích a jiných dnech volna. V tomto případě je potřeba využít externí zdroj informací a vytvořit tabulku, která bude obsahovat dny, které jsou nějakým způsobem výjimečné. Tabulka bude následně napojena na tabulku kalendáře.
※ Jelikož byla tabulka kalendáře vytvořena pomocí DAX příkazu, nelze s ní pracovat v Power Query editoru.
📝 Datový zdroj: https://www.kurzy.cz/kalendar/statni-svatky/2023/
Načteme zdroj jako webovou stránku pomocí Home → Get Data → Web. V dialogu zadáme URL zdroje a potvrdíme. V dialogu ohledně přihlášení zvolíme Anonymous a potvrdíme. V náhledu jsou požadovaná data v Table 1.
Fig — Načtená tabulka, z které budou dále použity první dva sloupce.
V prvním sloupci jsou data v textovém formátu 31.12.2023, neděle. Prvním krokem tedy bude převod do formátu datumu. Nejprve rozdělíme hodnotu na dvě části podle čárky.
Nástrojem Home → Split Column → By Delimiter rozdělíme sloupec datum podle čárky na sloupec obsahující 31.12.2023 a na sloupec obsahující neděle.
Odstraníme první řádku obsahující názvy sloupců. Home → Remove Rows → Remove Top Rows → (1)
Změníme datový typ prvního sloupce na Date.
V tomto kroku možná došlo k problému se zpracováním textu, když se Power Query editor snažil pochopit text jako datum ve formátu MM.DD.YYYY. V takovém případě je potřeba u datového typu zvolit poslední možnost Using locale... a v dialogu vybrat Date a Czech (Czech Republic).
Jelikož jsou v datech i významné dny, ve kterých není volno, filtrujeme pouze hodnoty Státní svátek a Ostatní svátky v příslušném sloupci.
Dle uvážení odstraňte nepotřebné sloupce.
Jelikož jsou kalendářní data některých svátků různá v různých letech, je potřeba využít tento postup i pro ostatní roky. Jednou z cest by mohlo být query rozkopírovat a upravit URL, z které se data načítají. Následně všechny tyto query spojit dohromady. Všimněte si, že URL obsahuje přímo rok, pro který se mají data načíst.
https://www.kurzy.cz/kalendar/statni-svatky/{rok}/
V tomto případě je ale vhodnější vytvořit parametr, který bude obsahovat číslo roku, pro který se mají data načíst, a s ním pracovat v query pro usnadnění práce.
Home → Manage Parameters → New Parameter s názvem svatky_rok a typem Text a výchozí hodnotou 2023.svatky upravte první operaci Source pomocí ikony ozubeného kola.Advanced Editor přidejte vytvořený parametr jako další položku adresy a odstraňte pevně zadaný rok. V náhledu by mělo být vidět https://www.kurzy.cz/kalendar/statni-svatky/{svatky_rok}Done.
Takto upravenou query převedeme na funkci, která bude přijímat parametr rok a vracet tabulku s daty pro daný rok.
svatky vyberte Create function... a pojmenujte funkci např. svatky.※ Po této operaci bude založena nová složka v seznamu query obsahující původní tabulku, parametr a funkční volání.
Nyní je potřeba vytvořit v Power Query editoru tabulku, která bude obsahovat seznam roků, ke kterým se mají dohledat informace o svátcích. Nejjednodušší bude vytvořit seznam čísel, seznam následně převést na tabulku a pro každou položku zavolat nově vytvořenou funkci svatky.
Home → New Source → Blank Query a pojmenujte ji např. svatky_all.= {2020..2023}. Tím se vytvoří seznam čísel 2020, 2021, 2022, 2023.Transform → To Table.rok a nastavte datový typ text.svatky Add Column → Invoke Custom Function.V tento moment by měla tabulka obsahovat dva sloupce — rok a Custom. Ve sloupci Custom jsou získané tabulky s daty o svátcích pro jednotlivé roky.
Expand (v hlavičce sloupce) a vyberte sloupce, které se hodí. Tím se vytvoří nové řádky pro každý záznam v tabulkách.V model view v hlavním okně projektu lze propojit vytvořenou tabulku s tabulkou kalendáře. Jedná se o 1:1 vazbu mezi tabulkou vytvořenou v Power Query editoru a tabulkou kalendáře vytvořenou pomocí DAX příkazu.
Power BI nabízí vizuál určený pro tvorbu choropleth map, který se nazývá Shape map. Vizuál potřebuje informaci o území, ke kterému má data přiřadit, a o hodnotě, které tam na barevné škále vykreslit. Ze základu je možné pracovat pouze s omezeným výběrem územních jednotek, nicméně lze dodat definici jiné mapy z externího zdroje.
※ Vizuál je dostupný jako preview feature a může být potřeba ho v instalaci PowerBi povolit v nastavení. File → Options and settings → Options → Preview features → Shape map visual.
Q7 Zkuste vykreslit Shape map za použití sloupce
nakaza_zeme_csu_koda počtu případů. Jaké území je vykresleno?
Vykreslené území lze změnit v nastavení vizuálu Format your visual → Visual → Map settings → Map type. Kromě předdefinovaných možností je možné vybrat i vlastní definici mapy (Custom map a příslušný soubor v Add a map type).
※ Dle GitHub Copilot LLM je "tento vizuál dostupný pouze v Power BI Desktop a není možné jej publikovat do Power BI Service." Tvrzení nebylo ověřeno, ale obecně mohou nastat problémy s vizuály, které využívají externí zdroje dat.
Vizualizace vyžaduje podkladové mapy v GeoJSON formátu. Taková data lze najít například v projektu World Atlas TopoJSON. Pro naše účely postačí data v měřítku 1:110m.
📝 Datový zdroj: countries-110m.json
V readme projektu je zmínka o tom, že země jsou identifikované podle číselného kódu ISO 3166-1 numeric.
Custom map a vyberte soubor countries-110m.json.View map type keyManual zoom a vypnout Auto zoom.Nyní je potřeba propojit stávající covid data s nově načtenými geodaty. V našem případě obsahuje sloupec nakaza_zeme_csu_kod kód příslušné země, ale je v nevhodném formátu ISO 3166-1 alpha-2 (např. IT místo 380). Je tedy potřeba vytvořit nový sloupec, který bude obsahovat kód země ve správném formátu, případně připojit převodní tabulku.
Nejbližší zdroj dat pro tento problém by mohl být oficiální číselník ISO 3166-1, který je dostupný na https://www.iso.org/obp/ui/#search/code/. Ten ale kvůli svému provedení nelze v PowerBI zpracovat.
Alternativou by mohlo být důvěřovat Wikipedii nebo projektu udržujícímu informace z číselníku.
📝 Datový zdroj: ISO-3166-Countries-with-Regional-Codes (all)
Home → Get Data → Text/CSV.country-code nastavte datový typ Text.nakaza_zeme_csu_kod a sloupce alpha-2.※ Alternativním řešením by bylo nová data připojit k tabulce osoby v Power Query Editoru pomocí Home → Merge Queries. V dialogu by se označily primární a cizí klíče a vybral vhodný outer join operátoru. Následně by se odstranily přebytečné sloupce.
Nyní by již mělo být možné data vykreslit.
Shape map zvolte datové atributy Location: country-code a Color-saturation: Count of id.Format your visual → Visual → Fill colors vyberte gradient s vhodnou barevnou paletou. Dále zde nastavte vhodný definiční obor číselné metriky.
Fig — Choropletová mapa zobrazující importované počty nákaz dle země původu. Vpravo jsou stejná data zobrazena v seřazené tabulce.
※ U kartogramů bývá zvykem přepočítávat hodnoty na počet obyvatel, rozlohu nebo jinou charakteristiku daného území. To v rámci tohoto cvičení nebude demonstrováno.
Q8: Proč je jako 12. nejčastější země původu nákazy ze zahraničí uváděno Česko?