Ovlivnění výsledku v řádku souhrnů v Power BI

Úvodní obrázek

Pokud použijeme v Power BI reportu vizuál Tabulka nebo vizuál Matice, může se v určitých situacích stát, že součet jednotlivých hodnot v řádcích nemusí vždy odpovídat hodnotě zobrazené v řádcích souhrnů. V takovýchto případech pracujeme s takzvaně neaditivním výpočty. Proč tomu tak je a jak případně udělat z neaditivního výpočtu výpočet aditivní si můžeme ukázat na jednoduchém příkladu.

Pozn.: K tomuto tématu je již k dispozici nový, aktualizovaný článek: Souhrn v Power BI vizuálu neodpovídá součtu hodnot v řádcích. Tento nový článek obsahuje více příkladů a také video návod. 

Výpočet počtu jedinečných zákazníků v letech

V prvním kroku si vytvoříme měřítko, které bude vracet jedinečný počet zákazníků, kteří zakoupili jeden nebo více produktů.

Měřítko:

Počet zákazníků = DISTINCTCOUNT(Sales[CustomerKey])

Toto měřítko bude vracet počet zákazníků v aktuálním kontextu vyhodnocení. Nové měřítko si můžeme vložit do vizuálu Tabulka, spolu s roky v řádcích.

Ovlivnění výsledku v řádku souhrnů v Power BI

Měřítko [Počet zákazníků] vrací v řádcích s jednotlivými roky počet zákazníků, kteří v daném roce zakoupili alespoň jeden produkt. V případě, že některý ze zákazníků nakupoval v daném roce vícekrát, je tento zákazník započítán pouze jednou.

Při pohledu na výše uvedený obrázek však uživatele reportu může zarazit, že jednotlivé hodnoty v řádcích s roky po sečtení neodpovídají součtu v posledním řádku tabulky, tedy v řádku souhrnů Total. To, že hodnota v řádku souhrnů neodpovídá součtu jednotlivých položek v řádcích ještě neznamená, že je výpočet špatně. Jako autoři bychom však měli být schopni správně interpretovat výsledky a v případě požadavku také vytvořit takový výpočet, ve kterém se bude součet jednotlivých položek v řádcích rovnat hodnotě v souhrnu.

Hodnoty v řádcích a hodnota v souhrnu

Pro pochopení neaditivních výpočtů, kde součet jednotlivých dílčích hodnot neodpovídá celku, musíme myslet na to, že každé měřítko je v každé buňce vizuálu vyhodnocena nezávisle na ostatních buňkách.

Měřítko použité ve vizuálu je vyhodnoceno v kontextu filtru roku v každém řádku zobrazené tabulky. V prvním řádku působí na měřítko filtr roku 2017. Pod tímto filtrem je vyhodnoceno měřítko [Počet zákazníků], které vrací počet jedinečných zákazníků z tabulky 'Sales' pro rok 2017. Obdobně pak výpočet probíhá i v dalších řádcích vizuálu pro všechny ostatní roky.

Ovlivnění výsledku v řádku souhrnů v Power BI 2

V řádku souhrnů již není aplikovaný na měřítko žádný filtr s roky. Měřítko je vyhodnoceno pro celou tabulku 'Sales'. Výsledné číslo v řádku souhrnů tedy vyjadřuje jedinečný počet zákazníků, kteří nakoupili nějaké zboží v kterémkoliv roce. 

Součet jednotlivých hodnot v řádcích neodpovídá hodnotě v řádku souhrnů proto, že stejní zákazníci nakupují zboží opakovaně v různých letech. Pokud jeden zákazník nakupoval ve všech letech, v řádku souhrnů je započítán pouze jednou, zatímco v jednotlivých letech se může vyskytovat vícekrát. Hodnota v řádku souhrnů by odpovídala součtu hodnot v řádcích pouze v situaci, kdy by v každém roce nakupovali zboží jiní zákazníci. Pokud bychom chtěli v řádku souhrnů i přesto vidět součet jednotlivých hodnot za každý rok, musíme použít jiný typ výpočtu.

Jak získat součet jedinečných hodnot z řádků do souhrnu

Měřítko, které bude vracet součet jedinečných zákazníků za jednotlivé roky v řádku souhrnů může vypadat následovně.

Měřítko:

Počet zákazníků 2 =
SUMX
(
    VALUES('Date'[Rok]),
    CALCULATE
    (
        DISTINCTCOUNT(Sales[CustomerKey])
    )
)

Měřítko [Počet zákazníků 2] si pro porovnání můžeme vložit do původního vizuálu.

Ovlivnění výsledku v řádku souhrnů v Power BI 3

Funkce SUMX() je iterační funkce, která pro každý řádek tabulky uvedené v prvním argumentu vyhodnotí výraz ve druhém argumentu funkce. Pokud probíhá výpočet v prvním řádku vizuálu tabulky, působí na tabulku  VALUES('Date'[Rok]) v prvním argumentu funkce filtr roku 2017. Tento filtr umožní provést výpočet druhého argumentu pouze pro rok 2017. Stejný princip je pak aplikován pro řádky s ostatními roky.

V řádku souhrnů pak tabulka VALUES('Date'[Rok]) obsahuje všechny roky, protože na ni nepůsobí žádný vnější filtr, jako tomu bylo s řádky s roky. Druhý argument ve funkci SUMX() je tedy postupně vyhodnocen každý jednotlivý rok, a funkce SUMX() jedinečné hodnoty za každý rok následně sečte. Výsledek v řádku souhrnů pak odpovídá součtu hodnot v jednotlivých letech.

Ačkoliv se může zdát, že měřítko [Počet zákazníků 2] nyní vrací v řádku souhrnů správnou hodnotu, opak je pravdou. V tomto konkrétním příkladě jsme programově udělali z neaditivního měřítka [Počet zákazníků] aditivní měřítko [Počet zákazníků 2]. Tímto krokem ale v řádku souhrnů zobrazujeme více zákazníků, než ve skutečnosti máme, protože jsme některé zákazníky započítali v řádku souhrnů vícekrát. Vícekrát jsou v řádku souhrnů započítáni ti zákazníci, kteří nakupovali produkty ve více letech.

V některých typech výpočtů může dávat smysl upravit neaditivní výpočet na aditivní výše uvedeným způsobem, nicméně vždy si musíme být v těchto typech výpočtů jistí, co počítáme a jaký význam má hodnota měřítka v daném kontextu.

Změna kontextu řádku na kontext filtru

Důležitou roli ve výpočtu měřítka [Počet zákazníků 2] je funkce CALCULATE(), do které je zabalena funkce DISTINCTCOUNT(). Pro zopakování se můžeme ještě jednou podívat na definici měřítka [Počet zákazníků 2]

Měřítko:

Počet zákazníků 2 =
SUMX
(
    VALUES('Date'[Rok]),
    CALCULATE
    (
        DISTINCTCOUNT(Sales[CustomerKey])
    )
)

Funkce SUMX() je iterační funkce, u které vzniká kontext řádku pro každý řádek tabulky uvedené jako první argument této funkce - výraz VALUES('Date'[Rok]). Druhý argument ve funkci SUMX() je vyhodnocen v kontextu každého řádku této tabulky, nicméně funkce DISTINCTCOUNT() kontext řádku ignoruje. Pokud bychom tedy nepoužili funkci CALCULATE(), tak by funkce DISTINCTCOUNT() vracela při výpočtu v řádku souhrnu v každém kroku iterace počet jedinečných hodnot za všechny roky, a ty by pak v rámci funkce SUMX() sčítala. Výsledek bez použití funkce CALCULATE() by představoval počet jedinečných zákazníků za všechny roky násobený počtem roků.

Funkce CALCULATE() ale změní kontext řádku na kontext filtru, a funkce DISTICNTCOUNT() je vyhodnocena v rámci iterace v kontextu filtru každého roku.

Shrnutí

Cílem této krátké ukázky bylo vysvětlit, proč v některých typech výpočtů v jazyku DAX neodpovídá součet jednotlivých hodnot v řádcích hodnotě zobrazené v řádku souhrnů. Těmto výpočtům se říká neaditivní a jde o výpočty, ve kterých součet dílčích hodnot neodpovídá celku. Pomocí jazyka DAX můžeme relativně jednoduše vytvořit z neaditivního výpočtu výpočet aditivní použitím některé z iteračních funkcí, jako je například funkce SUMX() použitá v příkladu v tomto příspěvku. Vytvořit z neaditivního výpočtu aditivní ovšem dává smysl pouze pro některé specifické typy výpočtů a příklad s počtem jedinečných zákazníků mezi ně nepatří. 

Pokud tedy narazíme na problém, kdy hodnota v souhrnu neodpovídá součtu dílčích hodnot v řádcích, je třeba se zamyslet nad významem jednotlivých hodnot v každém řádku vizuálu a rozhodnout, zda má být použité měřítko v aktuálním kontextu aditivní - má smysl sčítat dílčí hodnoty, nebo neaditivní - nemá smysl sčítat dílčí hodnoty. Pokud je daný výpočet neaditivní, je vždy lepší raději vysvětlit uživatelům reportu význam hodnoty v řádku souhrnů než zobrazovat špatné výsledky.

č.1

Komentáře