<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xml" href="/cjs/screen.xsl" media="screen"?>
<lecture>

<meta>
  <maintitle>Python</maintitle>
  <author>Jiří Znamenáček</author>
  <title>Pandas – Pozorování vodních ptáků</title>
  <date>2025-06-12</date>
  <link><!--a href="http://vyuka.ookami.cz" rel="external">http://vyuka.ookami.cz</a--></link>
  <!--
  <style>
    /* CSSka */
  </style>
  <use-math/>
  <use-x3dom/>
  -->
</meta>
<!--
  „“–…
  ←→ ↑↓ ↔↕
  ↵ aneb &#x21B5; aneb \r aneb CR aneb CarriageReturn
-->


<slide title="Zadání příkladu">

    <p>
        Jako další praktický příklad na použití knihovny <em>Pandas</em> si zpracujeme pozorování vodních ptáků na rybnících v jižních Čechách (konkrétně jde o vybranou podmnožinu rybníků z jara 2025). Struktura dat je následující:
    </p>
    <pre>
        RYBNÍK    DRUH_CZ              SAMCI    SAMICE    DOSPĚLCI    MLÁĎATA
        ...
        3133      kachna divoká        8        5         13          
        3133      polák chocholačka    6        5         11          
        3132      labuť velká                             3           2
        3132      kachna divoká        14       5         19          
        ...
    </pre>
    <p>
        Tj. pro každý rybník (uvedený číselným kódem) jsou zapsány počty dospělých ptáků a mláďat daného druhu a dá-li se snadno rozlišit samce a samice, jsou zapsány i jejich počty.
    </p>
    <note>
        Ve skutečnosti v datech mláďata skoro vůbec nejsou a počet dospělců by měl odpovídat součtu samic a samců. Navíc jsou některé druhy na některých rybnících pozorovány – a tím pádem i zapsány – vícekrát na různých místech.
    </note>
    <p>
        Naším úkolem je do nového excelovského souboru vypsat všechny druhy spolu s počtem dospělých jedinců a počtem rybníků, na nichž byl uvedený druh pozorován.
    </p>

</slide>
<slide title="Chybějící data I">

    <p>
        Vidíme, že v datech chybí spousta hodnot:
    </p>
    <example layout="vertical">
        <program src="_files/birds/01.py" lang="python"/>
        <out src="_files/birds/01.out" lang="text"/>
    </example>
    <p>
        Přestože v excelovském souboru je pro tyto buňky předepsán typ <em>číslo</em>, <em>Pandas</em> chybějící hodnoty nahrazuje různými svými vlastními konstantami – pro číselné hodnoty <code>np.nan</code>, pro časové údaje <code>pd.NaT</code> a pro pole a další <code>pd.NA</code>. Především u celých čísel pak základní problém spočívá v tom, že <strong>přítomnost <code>np.nan</code> způsobí přetypování celého sloupečku na <code>np.float64</code></strong> (případně <code>object</code>)!
    </p>

</slide>
<slide title="Chybějící data II">

    <p>
        Současná (a zpětně kompatibilní) výchozí pravidla pro určení typu hodnot můžete obejít, pokud pro problémové sloupce předepíšete typy ručně rovnou při importu:
    </p>
    <example layout="vertical">
        <program src="_files/birds/02.py" lang="python"/>
        <out src="_files/birds/02.out" lang="text"/>
    </example>
    <p>
        Řetězec <code>'Int64'</code> je alias na rozšiřující pandí typ <code>pd.Int64Dtype()</code>. Ve výpise se pak takovéto hodnoty hlásí jako <code>&lt;NA&gt;</code>.
    </p>
    <note>
        První sloupeček byl automaticky rozpoznán jako <code>np.int64</code>. Proto začíná pandí alias na velké <em>I</em>, aby se to nepletlo.
    </note>

</slide>
<slide title="Chybějící data – „fillna()“">

    <p>
        Protože v datech chybí hodnoty mezi samci a samicemi nepravidelně a protože numerické operace zahrnující <code>&lt;NA&gt;</code> vrací také <code>&lt;NA&gt;</code>, je snažší nahradit chybějící hodnoty nulou a teprve pak zkontrolovat správnost čísel ve sloupci <em>DOSPĚLCI</em>:
    </p>
    <example layout="vertical">
        <program src="_files/birds/03.py" lang="python"/>
        <out src="_files/birds/03.out" lang="text"/>
    </example>

</slide>
<slide title="Jedinečné hodnoty – „unique()“">

    <p>
        Jelikož máme vypsat celkové počty dospělců a obsazené rybníky pro každý druh, musíme nejdříve získat seznam všech druhů:
    </p>
    <example layout="vertical">
        <program src="_files/birds/04.py" lang="python"/>
        <out src="_files/birds/04.out" lang="text"/>
    </example>
    <note>
        PS: Jelikož sloupce <em>SAMCI</em> a <em>SAMICE</em> již pro další výpočty nepotřebujeme, vypustil jsem pro přehlednost jejich přetypovávání na <code>"Int64"</code>.
    </note>
    <p>
        Jak je vidět, na některých rybnících nebyl pozorován žádný pták, řádky s hodnotou <code>'bez ptáků'</code> tak musíme z dalšího zpracování vynechat.
    </p>

</slide>
<slide title="Kontrola pro jeden druh">

    <p>
        Ověřme si nejdříve například pro <em>racka chcechtavého</em>, jak vypadají jeho data:
    </p>
    <example layout="vertical">
        <program src="_files/birds/05.py" lang="python"/>
        <out src="_files/birds/05.out" lang="text"/>
    </example>
    <p>
        Vidíme, že na rybníce <em>2923</em> byl pozorován – a zapsán – na dvou různých místech. Odpovídající záznam ve výsledné tabulce pro něj tudíž musí obsahovat 4 rybníky (a ne pět) a celkem 14 dospělých jedinců.
    </p>

</slide>
<slide title="Prodloužení dat o jeden řádek – „df.loc[len(df)] = …“">

    <p>
        Nyní tedy již víme, že pro každý druh musíme spočítat jeho jedinečné rybníky a sečíst všechna čísla pro dospělce. Procyklíme tudíž data přes všechny druhy a zjištěné údaje přidáme do nového <em>DataFrame</em>u (<code>output</code>), který na konci zapíšeme do souboru:
    </p>
    <example src="_files/birds/06.py" lang="python" />
    <note>
        Kód se také trošku zesložitil přidáním řazení podle pravidel českého jazyka, protože jinak by <em>čáp</em> s <em>čírkou</em> byli až úplně na konci.
    </note>
    <p>
        Jelikož <em>Pandas</em> vyexportuje data včetně indexového sloupce (zde je jím výchozí číslování celými čísly od 0), je tento v Excelu potlačen volbou parametru <code>output.to_excel('…', index=False)</code>.
    </p>

</slide>
<slide title="Výsledek">

    <p>
        Výstup <a href="?slajd=7">předchozího programu</a> na konzoli je následující:
    </p>
    <example src="_files/birds/06.out" lang="text" />

</slide>


</lecture>
