<?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</title>
  <date>2025-04-23</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="Úvod">

    <p>
        Modul <a href="https://pandas.pydata.org" class="external">Pandas</a> je specializovaný nástroj na práci se dvěma typy dat:
    </p>
    <ul>
        <li>
            1D-pole dat libovolného typu (objekt <code>Series</code>);
        </li>
        <li>
            2D-tabulky dat libovolného typu (objekt <code>DataFrame</code>).
        </li>
    </ul>
    <p>
        Oboje využívá možností knihovny <a href="/materialy/python/numpy/overview.xml">Numpy</a>, konkrétně tedy její schopnosti zavedení libovolně složitého <a href="/materialy/python/numpy/arrays.creation.xml?slajd=38">strukturovaného typu</a>.
    </p>
    <p>
        PS: Asi úplně nejčastěji se tak s Pandas setkáte při zpracování tabulárních dat z Excelu, případně v podobě souborů CSV.
    </p>

</slide>
<slide title="Poznámka – Pandas je moloch">

    <p>
        Abychom si hned na začátku uvědomili, s jak velikým molochem se potkáváme, zde je kupříkladu plná verze funkce pro otevření CSV-souboru:
    </p>
    <pre>
pandas.read_csv(
    filepath_or_buffer, *, sep=&lt;no_default&gt;, delimiter=None, header='infer', names=&lt;no_default&gt;,
    index_col=None, usecols=None, dtype=None, engine=None, converters=None, true_values=None,
    false_values=None, skipinitialspace=False, skiprows=None, skipfooter=0, nrows=None,
    na_values=None, keep_default_na=True, na_filter=True, verbose=&lt;no_default&gt;,
    skip_blank_lines=True, parse_dates=None, infer_datetime_format=&lt;no_default&gt;,
    keep_date_col=&lt;no_default&gt;, date_parser=&lt;no_default&gt;, date_format=None, dayfirst=False,
    cache_dates=True, iterator=False, chunksize=None, compression='infer', thousands=None,
    decimal='.', lineterminator=None, quotechar='"', quoting=0, doublequote=True, escapechar=None,
    comment=None, encoding=None, encoding_errors='strict', dialect=None, on_bad_lines='error',
    delim_whitespace=&lt;no_default&gt;, low_memory=True, memory_map=False, float_precision=None,
    storage_options=None, dtype_backend=&lt;no_default&gt;
) </pre>
    <p>
        Asi už jenom z tohohle je celkem jasné, proč se na <em>Pandas</em> běžně vypisují (draze) placené kurzy, po jejichž úspěšném absolvování (snad) může účastník říci, že umí pomocí Pandas zpracovat libovolná tabulková data.
    </p>
    <note>
        S tím bohužel souvisí, že často účastníci kurzu získají pocit, že se zároveň s tím naučili i programovat v Python'u. A většinou to není pravda… (Často ani netuší, jak funguje a jak se píše smyčka <em>for-in</em>, protože zrovna ta se totiž v <em>Pandas</em> prakticky rozumně ani používat nedá.)
    </note>
    <p>
        Není tudíž divu, že v této sérii přednášek o knihovně <em>Pandas</em> si ukážeme jenom naprosté základy. Pro řešení konkrétních problémů si budete muset pomoci s vyhledáváním (s pomocí AI) nebo čtením <a href="https://pandas.pydata.org/docs/index.html#" class="external">originální dokumentace</a>.
    </p>

</slide>
<slide title="„DataFrame“ je slovník hodnot typu „Series“">

    <p>
        Jakkoliv to zní proti klasickému chápání 2D-tabulky kontraintuitivně, tak <strong><code>DataFrame</code> je v podstatě slovník sloupců, kde každý sloupec je pandí <code>Series</code></strong>. Klíči tohoto slovníku jsou názvy sloupečků a všechny sloupečky přitom sdílejí stejný (přístupový) index.
    </p>
    <note>
        S tím souvisí, že přidat sloupec je triviálně náročné (ekvivalent přidání nového klíče s hodnotou do slovníku), zatímco přidat řádek je masakr – vlastně musíme pro každý klíč ve slovníku přidat na konkrétní místo odpovídající <code>Series</code> další prvek. 
    </note>
    <p>
        Z toho je asi už jasné, že <strong>iterovat</strong> (ať už pomocí <em>for-in</em> nebo třeba metody <code>iterrows()</code>) <strong>po řádcích <em>DataFrame</em>u je těžce kontraproduktivní</strong> – snažíte se najednou vytáhnout hodnoty na stejném místě (konkrétní řádek <code>DataFrame</code>) z mnoha různých <code>Series</code> (sloupečky).
    </p>
    <note>
        Takže vlastně děláte něco jako <code>zip()</code> nad sloupečky, ale s konkrétním indexem daného <em>DataFrame</em>u.
    </note>
    <p>
        Pro většinu takových potřeb existuje v <em>Pandas</em> lepší řešení, většinou v podobě nějaké vektorizované (ve smyslu <em>Numpy</em>) metody. Naučit se efektivně používat <em>Pandas</em> pak v podstatě znamená naučit se myslet, jak se typické úlohy v <em>Pandas</em> nejlépe řeší. V dalším si ukážeme pár jednoduchých příkladů, ale na reálnou  práci s (velkými) daty to stačit nebude, to už si budete muset nastudovat sami.
    </p>

</slide>
<slide title="Instalace a import modulu „pandas“">

    <p>
        Modul <em>pandas</em> se instaluje klasicky, ať už <em>pip</em>em nebo třebas pomocí <em>Condy</em>:
    </p>
    <example lang="cmd">
        # instalace pomocí CheeseShop
        pip install pandas

        # instalace pomocí Condy
        conda install pandas
    </example>
    <note>
        Mezi instalované závislosti patří <em>numpy</em>, <em>python-dateutil</em>, <em>pytz</em>, <em>tzdata</em> a <em>six</em>. Pokud budete chtít pracovat se soubory MS Excel, vyžádá si <em>Pandas</em> i doinstalaci dalších závislostí (přinejmenším <em>openpyxl</em> a <em>et-xmlfile</em>).
    </note>
    <p>
        Do programů je pak zvykem importovat <em>Pandas</em> následujícím způsobem pod jménem <em>pd</em>:
    </p>
    <example lang="python">
        import pandas as pd
    </example>
    <note>
         Tedy podobně jako u <em>Numpy</em>, kde používáme <code>import numpy as np</code> .
    </note>

</slide>
<slide title="Příklad – práce s tabulárními daty v CSV">

    <p>
        Základy práce s knihovnou <em>Pandas</em> si ukážeme na následujících jednoduchých datech ve formátu CSV:
    </p>
    <example lang="txt" src="_files/overview/HP.csv"/>
    <note>
        Společný začátek názvů všech filmů <em>„Harry Potter and the“</em> pro přehlednost vynechán.
    </note>
    <p>
        Data se do programu načtou velmi jednoduše následujícím způsobem:
    </p>
    <example layout="vertical">
        <program src="_files/overview/01a.py" lang="python"/>
        <out src="_files/overview/01a.out" lang="text"/>
    </example>
    <note>
        Tato ukázková data jsou maličká a jsou tak vypsána celá, větší data by byla ořezána a vidět by byl pouze výřez jejich okrajů. Stejně jako u velkých polí v <em>Numpy</em>.
    </note>

</slide>
<slide title="PS: Technické informace o datech – „info()“">

    <p>
        Pokud byste potřebovali informace o načtených datech a jak je <em>Pandas</em> pochopil a zpracoval, pomůže vám metoda <code>info()</code>. Její výstup jde přímo na terminál:
    </p>
    <example layout="vertical">
        <program src="_files/overview/01b.py" lang="python"/>
        <out src="_files/overview/01b.out" lang="text"/>
    </example>
    <p>
        Vidíme, že <em>Pandas</em> správně naparsoval hlavičkovou řádku a příslušných pět sloupečků, přičemž odpovídajícím pěti <em>Series</em> přiřadil vyhovující <em>numpy</em>-typy (čtyřikrát obecný objekt, tedy řetězec, a jednou – pro rok – celé číslo v rozsahu <em>int64</em>).
    </p>

</slide>
<slide title="Rychlý náhled na data – „head()“ a „tail()“">

    <p>
        Jelikož typicky budete pomocí <em>Pandas</em> zpracovávat opravdu veliké datové soubory, často se budete chtít podívat, jak vypadá hlavička a její okolí a konec načtených dat. Metody <code>head()</code> a <code>tail()</code> vypisují pět řádek z odpovídajícího konce dat (plus pro přehlednost i hlavičku):
    </p>
    <example layout="vertical">
        <program src="_files/overview/02.py" lang="python"/>
        <out src="_files/overview/02.out" lang="text"/>
    </example>

</slide>
<slide title="Výpis vybraných sloupečků – „[[]]“">

    <p>
        Chcete-li ze všech dostupných dat vypsat pouze některé sloupečky, píše se to trochu překvapivě pomocí dvojtých hranatých závorek:
    </p>
    <example layout="vertical">
        <program src="_files/overview/07.py" lang="python"/>
        <out src="_files/overview/07.out" lang="text"/>
    </example>
    <p>
        Přitom, jak je vidět, na pořadí originálních dat nezáleží – co si zadáte, to se vypíše.
    </p>

</slide>
<slide title="Výběr hodnot – „[]“, „unique()“, „value_counts()“">

    <p>
        O sloupečcích můžeme snadno zjišťovat spoustu zajímavých věcí:
    </p>
    <example layout="vertical">
        <program src="_files/overview/04.py" lang="python"/>
        <out src="_files/overview/04.out" lang="text"/>
    </example>
    <note>
        Výstupem metody <code>unique()</code> není pythonovský seznam, ale numpyovské <em>ndarray</em>.
    </note>

</slide>
<slide title="Numpy „fancy indexing“">

    <p>
        Stejně jako v <em>Numpy</em> můžeme při výběru s výhodou využít <a href="/materialy/python/numpy/arrays.slicing.xml?slajd=7">„fancy indexing“</a>:
    </p>
    <example layout="vertical">
        <program src="_files/overview/05.py" lang="python"/>
        <out src="_files/overview/05.out" lang="text"/>
    </example>
    <note>
        A stejně jako v <em>Numpy</em> to není úplně nejrychlejší a paměťově nejméně náročný způsob.
    </note>

</slide>
<slide title="Logické skládání podmínek – „&amp;“ (AND), „|“ (OR) a „~“ (NOT)">

    <p>
        Podmínky pro výběr (nejen u „<em>fancy indexing</em>“) se dají skládat <a href="/materialy/python/types/numbers.xml?slajd=14">operátory pro bitovou logiku</a>:
    </p>
    <example layout="vertical">
        <program src="_files/overview/06.py" lang="python"/>
        <out src="_files/overview/06.out" lang="text"/>
    </example>
    <p>
        PS: Vlastnost <code>.str</code> na objektu typu <em>Series</em> je vektorizovaný (tedy přes všechny položky) přístup k řetězcovým operacím na příslušném (zde) sloupečku.
    </p>

</slide>
<slide title="Vektorizované operace přes sloupce">

    <p>
        Než náš rychloúvod opustíme, ukažme si ještě jednu pro <em>Pandas</em> zcela typickou operaci – skládání hodnot z vícero sloupců do výsledného nového sloupce:
    </p>
    <example layout="vertical">
        <program src="_files/overview/08.py" lang="python"/>
        <out src="_files/overview/08.out" lang="text"/>
    </example>
    <p>
        PS: Na těchto datech jde o zcela umělý příklad, ale pokud by to byly kupříkladu číselné řady a mohli byste takto třebas sečíst nebo vynásobit některé sloupce mezi sebou a výsledek zaznamenat do sloupce nového, hned by to dávalo větší smysl. O tom ale více až <a href="">v další přednášce</a>.
    </p>

</slide>
<slide title="PS: Konkrétní řádka(y) – „iloc[]“">

    <p>
        Konkrétní řádku (či řádky) – tedy vlastně výřezy ze všech odpovídajících sloupečků <em>Series</em> – získáte úplně stejně jako u výřezů v samotném Python'u pomocí pořadového čísla a výřezové notace <code>[:]</code>:
    </p>
    <example layout="vertical">
        <program src="_files/overview/03.py" lang="python"/>
        <out src="_files/overview/03.out" lang="text"/>
    </example>
    <p>
        Jak jsem ale <a href="?slajd=3">zmiňoval na začátku</a>, iterace po řádcích je v <em>Pandas</em> tzv. <strong>antipattern</strong>, takže chtít po <code>iloc[]</code> něco víc než občasný pohled na konkrétní data je cesta do pekel.
    </p>
    <p>
        PS: Kromě toho se můžete k datům dostat i jen pomocí <code>[]</code>, pak ale často operujete nad jejich kopií, nebo také pseudometody <code>.loc[]</code>, která operuje přímo nad originálními daty. Více viz <a href="https://stackoverflow.com/questions/48409128/what-is-the-difference-between-using-loc-and-using-just-square-brackets-to-filte" class="external">tato debata na SO</a>.
    </p>

</slide>


</lecture>
