Knihovna Polars: výkonnější alternativa ke knihovně Pandas (datové rámce)

17. 1. 2023
Doba čtení: 29 minut

Sdílet

 Autor: Polars team, podle licence: CC BY-NC 2.5
Ve druhé části seriálu o knihovně Polars, jejímž cílem je být výkonnější alternativou ke známé knihovně Pandas, se budeme převážně zabývat operacemi, které je možné provádět s datovými rámci (data frames).

Obsah

1. Knihovna Polars: výkonnější alternativa ke knihovně Pandas (datové rámce)

2. Zobrazení úvodních záznamů uložených v datovém rámci metodou head

3. Specifikace maximálního počtu zobrazených řádků s obsahem datového rámce

4. Volba naformátování datového rámce

5. Zobrazení naformátovaného datového rámce bez specifikace jeho tvaru

6. Seřazení záznamů v datovém rámci metodou sort

7. Odstranění duplicitních záznamů na základě hodnot ve specifikovaném sloupci

8. Zpracování jednotlivých sloupců v datových rámcích – map

9. Použití alternativní metody apply

10. Rozdělení a následná agregace údajů s využitím metody groupby

11. Praktická ukázka použití groupby

12. Seřazení hodnot v průběhu jejich agregace

13. Seřazení záznamů v datovém rámci před provedením operace groupby s následnou agregací

14. Výpočet celkového pořadí vítězných programovacích jazyků

15. Seřazení jazyků na základě jejich celkového pořadí

16. Dva způsoby korektního seřazení výsledků

17. Příklad na závěr – složitější „pipeline“, změna názvu sloupce

18. Obsah třetí části seriálu o knihovně Polars

19. Repositář s demonstračními příklady

20. Odkazy na Internetu

1. Knihovna Polars: výkonnější alternativa ke knihovně Pandas (datové rámce)

Na úvodní článek o knihovně Polars, jejímž cílem je být výkonnější alternativou ke známé knihovně Pandas, dnes navážeme. Ukážeme si některé další operace určené pro zpracování dat uložených v datových rámcích (data frame). V první řadě se jedná o seřazení dat, zobrazení určité části datového rámce, naformátování výstupu s datovým rámcem, získání prvků s unikátními hodnotami atd. Ovšem nesmíme zapomenout ani na velmi důležitou sekvenci operací: rozdělení vstupních záznamů do skupin na základě zadaného kritéria následovanému agregací dat (což může být například zjištění, kolik záznamů se v každé skupině nachází atd.). Všechny zmíněné operace je přitom možné různým způsobem kombinovat a zapsat tak do jediného výrazu i poměrně složité transformace dat.

2. Zobrazení úvodních záznamů uložených v datovém rámci metodou head

Ve skriptech uvedených minule jsme se většinou snažili zobrazit celý obsah datového rámce. Existují ovšem metody head a tail, které dokážou zobrazit pouze několik úvodních záznamů v datovém rámci, popř. naopak poslední záznamy v rámci. Nejdříve se podívejme na metodu head která, pokud se jí nepředají další parametry, zobrazí prvních pět úvodních záznamů:

print(df.head())

S výsledkem:

shape: (5, 2)
┌──────┬────────┐
│ Year ┆ Winner │
│ ---  ┆ ---    │
│ i64  ┆ str    │
╞══════╪════════╡
│ 2022 ┆ C++    │
│ 2021 ┆ Python │
│ 2020 ┆ Python │
│ 2019 ┆ C      │
│ 2018 ┆ Python │
└──────┴────────┘

Podobně lze použít metodu tail:

print(df.head())

S odlišným výsledkem:

shape: (5, 2)
┌──────┬────────┐
│ Year ┆ Winner │
│ ---  ┆ ---    │
│ i64  ┆ str    │
╞══════╪════════╡
│ 2007 ┆ Python │
│ 2006 ┆ Ruby   │
│ 2005 ┆ Java   │
│ 2004 ┆ PHP    │
│ 2003 ┆ C++    │
└──────┴────────┘

Celý skript může vypadat následovně:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# zobrazíme datový rámec, resp. jeho hlavičku
print(df.head())
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame12_head_A.py.

Pokud metodám head či tail předáme celočíselnou hodnotu, bude se jednat o počet záznamů, které se mají zobrazit. Ovšem je důležité dát si pozor na to, že existuje ještě dále popsané omezení maximálního počtu zobrazených řádků na terminálu.

Použití metody head s parametrem:

print(df.head(30))

Výsledek:

shape: (20, 2)
┌──────┬────────┐
│ Year ┆ Winner │
│ ---  ┆ ---    │
│ i64  ┆ str    │
╞══════╪════════╡
│ 2022 ┆ C++    │
│ 2021 ┆ Python │
│ 2020 ┆ Python │
│ 2019 ┆ C      │
│ ...  ┆ ...    │
│ 2006 ┆ Ruby   │
│ 2005 ┆ Java   │
│ 2004 ┆ PHP    │
│ 2003 ┆ C++    │
└──────┴────────┘

Použití metody tail s parametrem:

print(df.tail(30))

Výsledek:

shape: (20, 2)
┌──────┬────────┐
│ Year ┆ Winner │
│ ---  ┆ ---    │
│ i64  ┆ str    │
╞══════╪════════╡
│ 2022 ┆ C++    │
│ 2021 ┆ Python │
│ 2020 ┆ Python │
│ 2019 ┆ C      │
│ ...  ┆ ...    │
│ 2006 ┆ Ruby   │
│ 2005 ┆ Java   │
│ 2004 ┆ PHP    │
│ 2003 ┆ C++    │
└──────┴────────┘

Celý skript vypadá následovně:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# zobrazíme datový rámec, resp. jeho hlavičku
print(df.head(30))
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame13_head_B.py.

3. Specifikace maximálního počtu zobrazených řádků s obsahem datového rámce

Funkcí polars.Config.set_tbl_rows() je možné zvětšit či naopak zmenšit maximální počet řádků s obsahem datového rámce, které budou vypsány na terminál (resp. obecně na standardní výstup). V případě, že bude datový rámec obsahovat méně řádků, bude zobrazen celý, pokud bude obsahovat více řádků, bude datový rámec v polovině zkrácen:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
# zobrazíme datový rámec
print(df.head(30))
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame14_head_C.py.

Výsledek bude nyní vypadat následovně – zobrazí se všech dvacet řádků:

shape: (20, 2)
┌──────┬──────────────┐
│ Year ┆ Winner       │
│ ---  ┆ ---          │
│ i64  ┆ str          │
╞══════╪══════════════╡
│ 2022 ┆ C++          │
│ 2021 ┆ Python       │
│ 2020 ┆ Python       │
│ 2019 ┆ C            │
│ 2018 ┆ Python       │
│ 2017 ┆ C            │
│ 2016 ┆ Go           │
│ 2015 ┆ Java         │
│ 2014 ┆ JavaScript   │
│ 2013 ┆ Transact-SQL │
│ 2012 ┆ Objective-C  │
│ 2011 ┆ Objective-C  │
│ 2010 ┆ Python       │
│ 2009 ┆ Go           │
│ 2008 ┆ C            │
│ 2007 ┆ Python       │
│ 2006 ┆ Ruby         │
│ 2005 ┆ Java         │
│ 2004 ┆ PHP          │
│ 2003 ┆ C++          │
└──────┴──────────────┘

4. Volba naformátování datového rámce

Datové rámce je možné zobrazit mnoha různými způsoby. Volba formátování se provádí funkcí polars.Config.set_tbl_formatting, které se předává řetězcová konstanta (literál) s popisem formátu. Všechny v současnosti podporované formáty zobrazení naleznete v následujícím skriptu, konkrétně v n-tici formattings:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
formattings = (
        "ASCII_FULL",
        "ASCII_FULL_CONDENSED",
        "ASCII_NO_BORDERS",
        "ASCII_BORDERS_ONLY",
        "ASCII_BORDERS_ONLY_CONDENSED",
        "ASCII_HORIZONTAL_ONLY",
        "ASCII_MARKDOWN",
        "UTF8_FULL",
        "UTF8_FULL_CONDENSED",
        "UTF8_NO_BORDERS",
        "UTF8_BORDERS_ONLY",
        "UTF8_HORIZONTAL_ONLY",
        "NOTHING",
        )
 
for formatting in formattings:
    print()
    print(formatting)
    print()
 
    polars.Config.set_tbl_formatting(formatting)
 
    # zobrazíme datový rámec
    print(df)

Výsledné datové rámce zobrazené na terminálu jsou naformátovány takto: https://raw.githubusercon­tent.com/tisnik/most-popular-python-libs/master/polars/format­ted_data_frames_with_shapes­.txt.

Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame15_formatting_A.py.

5. Zobrazení naformátovaného datového rámce bez specifikace jeho tvaru

Alternativně je možné příkazem:

polars.Config.set_tbl_hide_dataframe_shape(True)

zakázat zobrazení tvaru (shape) datového rámce. Výsledné formy naformátování datových rámců naleznete na stránce https://raw.githubusercon­tent.com/tisnik/most-popular-python-libs/master/polars/format­ted_data_frames_without_sha­pes.txt a jsou výsledkem činnosti tohoto skriptu:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
# nezobrazovat tvar (shape) datových rámců
polars.Config.set_tbl_hide_dataframe_shape(True)
 
formattings = (
        "ASCII_FULL",
        "ASCII_FULL_CONDENSED",
        "ASCII_NO_BORDERS",
        "ASCII_BORDERS_ONLY",
        "ASCII_BORDERS_ONLY_CONDENSED",
        "ASCII_HORIZONTAL_ONLY",
        "ASCII_MARKDOWN",
        "UTF8_FULL",
        "UTF8_FULL_CONDENSED",
        "UTF8_NO_BORDERS",
        "UTF8_BORDERS_ONLY",
        "UTF8_HORIZONTAL_ONLY",
        "NOTHING",
        )
 
for formatting in formattings:
    print()
    print(formatting)
    print()
 
    polars.Config.set_tbl_formatting(formatting)
 
    # zobrazíme datový rámec
    print(df)
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame16_formatting_B.py.

6. Seřazení záznamů v datovém rámci metodou sort

Záznamy v datovém rámci je možné seřadit podle hodnot uložených ve vybraném sloupci. K tomuto účelu slouží metoda nazvaná sort, které se předá jméno sloupce. Důležité je, že původní datový rámec zůstane nezměněn, ale vytvoří a vrátí se rámec nový (podobně jako u standardní funkce sort). Takto například zajistíme seřazení hodnot v datovém rámci podle jména programovacího jazyka:

# seřadit a vytvořit nový datový rámec
df = df.sort("Winner")

S výsledkem:

shape: (20, 2)
┌──────┬──────────────┐
│ Year ┆ Winner       │
│ ---  ┆ ---          │
│ i64  ┆ str          │
╞══════╪══════════════╡
│ 2019 ┆ C            │
│ 2017 ┆ C            │
│ 2008 ┆ C            │
│ 2022 ┆ C++          │
│ 2003 ┆ C++          │
│ 2016 ┆ Go           │
│ 2009 ┆ Go           │
│ 2015 ┆ Java         │
│ 2005 ┆ Java         │
│ 2014 ┆ JavaScript   │
│ 2012 ┆ Objective-C  │
│ 2011 ┆ Objective-C  │
│ 2004 ┆ PHP          │
│ 2021 ┆ Python       │
│ 2020 ┆ Python       │
│ 2018 ┆ Python       │
│ 2010 ┆ Python       │
│ 2007 ┆ Python       │
│ 2006 ┆ Ruby         │
│ 2013 ┆ Transact-SQL │
└──────┴──────────────┘

Úplný skript, který načte, seřadí a zobrazí nový datový rámec, vypadá takto:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
# seřadit a vytvořit nový datový rámec
df = df.sort("Winner")
 
# zobrazíme datový rámec
print(df)
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame17_sort.py.

Pokud budeme potřebovat seřadit záznamy v opačném pořadí, nabízí se použití další metody nazvané reverse:

# seřadit a vytvořit nový datový rámec
df = df.sort("Winner").reverse()

S výsledky:

shape: (20, 2)
┌──────┬──────────────┐
│ Year ┆ Winner       │
│ ---  ┆ ---          │
│ i64  ┆ str          │
╞══════╪══════════════╡
│ 2013 ┆ Transact-SQL │
│ 2006 ┆ Ruby         │
│ 2007 ┆ Python       │
│ 2010 ┆ Python       │
│ 2018 ┆ Python       │
│ 2020 ┆ Python       │
│ 2021 ┆ Python       │
│ 2004 ┆ PHP          │
│ 2011 ┆ Objective-C  │
│ 2012 ┆ Objective-C  │
│ 2014 ┆ JavaScript   │
│ 2005 ┆ Java         │
│ 2015 ┆ Java         │
│ 2009 ┆ Go           │
│ 2016 ┆ Go           │
│ 2003 ┆ C++          │
│ 2022 ┆ C++          │
│ 2008 ┆ C            │
│ 2017 ┆ C            │
│ 2019 ┆ C            │
└──────┴──────────────┘

Opět si uveďme celý skript, který tuto operaci provede:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
# seřadit a vytvořit nový datový rámec
df = df.sort("Winner").reverse()
 
# zobrazíme datový rámec
print(df)
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame18_sort_reverse.py.

Rychlejší i paměťově méně náročné je ovšem předání nepovinného parametru reverse metodě Sort. Ušetří se tím vytvoření jednoho datového rámce navíc a současně i provedení operace reverse:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
# seřadit a vytvořit nový datový rámec
df = df.sort("Winner", reverse=True)
 
# zobrazíme datový rámec
print(df)

Výsledek bude totožný s výsledkem získaným z předchozího skriptu.

7. Odstranění duplicitních záznamů na základě hodnot ve specifikovaném sloupci

Metodou unique, která opět vytvoří nový datový rámec, je možné vybrat jen tolik záznamů z původního datového rámce, aby hodnoty ve vybraném sloupci byly unikátní. Co to například znamená v našem konkrétním případě? Názvy programovacích jazyků v původním datovém sloupci nejsou unikátní, protože se některé jazyky opakují:

shape: (20, 2)
┌──────┬──────────────┐
│ Year ┆ Winner       │
│ ---  ┆ ---          │
│ i64  ┆ str          │
╞══════╪══════════════╡
│ 2022 ┆ C++          │
│ 2021 ┆ Python       │
│ 2020 ┆ Python       │
│ 2019 ┆ C            │
│ 2018 ┆ Python       │
│ 2017 ┆ C            │
│ 2016 ┆ Go           │
│ 2015 ┆ Java         │
│ 2014 ┆ JavaScript   │
│ 2013 ┆ Transact-SQL │
│ 2012 ┆ Objective-C  │
│ 2011 ┆ Objective-C  │
│ 2010 ┆ Python       │
│ 2009 ┆ Go           │
│ 2008 ┆ C            │
│ 2007 ┆ Python       │
│ 2006 ┆ Ruby         │
│ 2005 ┆ Java         │
│ 2004 ┆ PHP          │
│ 2003 ┆ C++          │
└──────┴──────────────┘

Pokud ovšem vytvoříme nový datový rámec následující operací:

# vyfiltrovat a vytvořit nový datový rámec
df = df.unique(subset="Winner")

Bude ve výsledku každý jazyk reprezentován jediným záznamem:

shape: (10, 2)
┌──────┬──────────────┐
│ Year ┆ Winner       │
│ ---  ┆ ---          │
│ i64  ┆ str          │
╞══════╪══════════════╡
│ 2022 ┆ C++          │
│ 2021 ┆ Python       │
│ 2019 ┆ C            │
│ 2016 ┆ Go           │
│ 2015 ┆ Java         │
│ 2014 ┆ JavaScript   │
│ 2013 ┆ Transact-SQL │
│ 2012 ┆ Objective-C  │
│ 2006 ┆ Ruby         │
│ 2004 ┆ PHP          │
└──────┴──────────────┘

Opět si pro úplnost ukažme celý skript, který tuto operaci provádí:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
# seřadit a vytvořit nový datový rámec
df = df.unique(subset="Winner")
 
# zobrazíme datový rámec
print(df)
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame19_unique.py.

8. Zpracování jednotlivých sloupců v datových rámcích – map

Vyzkoušejme si nyní vytvoření nového sloupce pojmenovaného „Ratings as ratio“ a založeného na hodnotách z existujícího sloupce „Ratings“. Použijeme přitom metodu map, která postupně aplikuje zadanou funkci (v našem případě anonymní funkci zapsanou pomocí lambda) na hodnoty uložené ve vybraném sloupci. Zpracování hodnot je jednoduché – hodnoty v procentech se převedou na hodnoty ležící v rozsahu od 0,1 do 1,0, tedy na poměr popularity jednotlivých programovacích jazyků:

# převod na skutečný poměr <0, 1>
df2 = df.with_column(
    polars.col("Ratings").map(lambda x: x / 100.0).alias("Ratings as ratio")
)

Výsledkem by měl být nový datový rámec (df2) s novým sloupcem:

shape: (20, 7)
┌──────────┬──────────┬────────┬───────────────────┬─────────┬─────────┬──────────────────┐
│ Sep 2020 ┆ Sep 2019 ┆ Change ┆ Language          ┆ Ratings ┆ Changep ┆ Ratings as ratio │
│ ---      ┆ ---      ┆ ---    ┆ ---               ┆ ---     ┆ ---     ┆ ---              │
│ i64      ┆ i64      ┆ str    ┆ str               ┆ f64     ┆ f64     ┆ f64              │
╞══════════╪══════════╪════════╪═══════════════════╪═════════╪═════════╪══════════════════╡
│ 1        ┆ 2        ┆ change ┆ C                 ┆ 15.95   ┆ 0.74    ┆ 0.1595           │
│ 2        ┆ 1        ┆ change ┆ Java              ┆ 13.48   ┆ -3.18   ┆ 0.1348           │
│ 3        ┆ 3        ┆ null   ┆ Python            ┆ 10.47   ┆ 0.59    ┆ 0.1047           │
│ 4        ┆ 4        ┆ null   ┆ C++               ┆ 7.11    ┆ 1.48    ┆ 0.0711           │
│ 5        ┆ 5        ┆ null   ┆ C#                ┆ 4.58    ┆ 1.18    ┆ 0.0458           │
│ 6        ┆ 6        ┆ null   ┆ Visual Basic      ┆ 4.12    ┆ 0.83    ┆ 0.0412           │
│ 7        ┆ 7        ┆ null   ┆ JavaScript        ┆ 2.54    ┆ 0.41    ┆ 0.0254           │
│ 8        ┆ 9        ┆ change ┆ PHP               ┆ 2.49    ┆ 0.62    ┆ 0.0249           │
│ 9        ┆ 19       ┆ change ┆ R                 ┆ 2.37    ┆ 1.33    ┆ 0.0237           │
│ 10       ┆ 8        ┆ change ┆ SQL               ┆ 1.76    ┆ -0.19   ┆ 0.0176           │
│ 11       ┆ 14       ┆ change ┆ Go                ┆ 1.46    ┆ 0.24    ┆ 0.0146           │
│ 12       ┆ 16       ┆ change ┆ Swift             ┆ 1.38    ┆ 0.28    ┆ 0.0138           │
│ 13       ┆ 20       ┆ change ┆ Perl              ┆ 1.3     ┆ 0.26    ┆ 0.013            │
│ 14       ┆ 12       ┆ change ┆ Assembly language ┆ 1.3     ┆ -0.08   ┆ 0.013            │
│ 15       ┆ 15       ┆ null   ┆ Ruby              ┆ 1.24    ┆ 0.03    ┆ 0.0124           │
│ 16       ┆ 18       ┆ change ┆ MATLAB            ┆ 1.1     ┆ 0.04    ┆ 0.011            │
│ 17       ┆ 11       ┆ change ┆ Groovy            ┆ 0.99    ┆ -0.52   ┆ 0.0099           │
│ 18       ┆ 33       ┆ change ┆ Rust              ┆ 0.92    ┆ 0.55    ┆ 0.0092           │
│ 19       ┆ 10       ┆ change ┆ Objective-C       ┆ 0.85    ┆ -0.99   ┆ 0.0085           │
│ 20       ┆ 24       ┆ change ┆ Dart              ┆ 0.77    ┆ 0.13    ┆ 0.0077           │
└──────────┴──────────┴────────┴───────────────────┴─────────┴─────────┴──────────────────┘

Opět si pro úplnost ukažme celý skript:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
# přečtení zdrojových dat
df = polars.read_csv("tiobe.tsv", sep="\t")
 
# převod na skutečný poměr <0, 1>
df2 = df.with_column(
    polars.col("Ratings").map(lambda x: x / 100.0).alias("Ratings as ratio")
)
 
# datový rámec zobrazíme
print(df)
print()
 
# datový rámec zobrazíme
print(df2)
print()
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame20_map_conversion­.py.

9. Použití alternativní metody apply

Namísto metody map, která interně operuje vždy s celým sloupcem (tedy s datovou řadou) je možné použít metodu apply. Ta v tomto případě provádí (z pohledu uživatele) shodnou operaci (výsledek bude totožný), ovšem interně je výpočet proveden zcela odlišným způsobem:

# převod na skutečný poměr <0, 1>
df2 = df.with_column(
    polars.col("Ratings").apply(lambda x: x / 100.0).alias("Ratings as ratio")
)

Výsledkem bude v tomto konkrétním případě naprosto stejný datový rámec, jaký byl získán skriptem z předchozí kapitoly. Mohlo by se tedy zdát, že map a apply mají stejný význam, ale příště si ukážeme, že tomu tak vždy není:

shape: (20, 7)
┌──────────┬──────────┬────────┬───────────────────┬─────────┬─────────┬──────────────────┐
│ Sep 2020 ┆ Sep 2019 ┆ Change ┆ Language          ┆ Ratings ┆ Changep ┆ Ratings as ratio │
│ ---      ┆ ---      ┆ ---    ┆ ---               ┆ ---     ┆ ---     ┆ ---              │
│ i64      ┆ i64      ┆ str    ┆ str               ┆ f64     ┆ f64     ┆ f64              │
╞══════════╪══════════╪════════╪═══════════════════╪═════════╪═════════╪══════════════════╡
│ 1        ┆ 2        ┆ change ┆ C                 ┆ 15.95   ┆ 0.74    ┆ 0.1595           │
│ 2        ┆ 1        ┆ change ┆ Java              ┆ 13.48   ┆ -3.18   ┆ 0.1348           │
│ 3        ┆ 3        ┆ null   ┆ Python            ┆ 10.47   ┆ 0.59    ┆ 0.1047           │
│ 4        ┆ 4        ┆ null   ┆ C++               ┆ 7.11    ┆ 1.48    ┆ 0.0711           │
│ 5        ┆ 5        ┆ null   ┆ C#                ┆ 4.58    ┆ 1.18    ┆ 0.0458           │
│ 6        ┆ 6        ┆ null   ┆ Visual Basic      ┆ 4.12    ┆ 0.83    ┆ 0.0412           │
│ 7        ┆ 7        ┆ null   ┆ JavaScript        ┆ 2.54    ┆ 0.41    ┆ 0.0254           │
│ 8        ┆ 9        ┆ change ┆ PHP               ┆ 2.49    ┆ 0.62    ┆ 0.0249           │
│ 9        ┆ 19       ┆ change ┆ R                 ┆ 2.37    ┆ 1.33    ┆ 0.0237           │
│ 10       ┆ 8        ┆ change ┆ SQL               ┆ 1.76    ┆ -0.19   ┆ 0.0176           │
│ 11       ┆ 14       ┆ change ┆ Go                ┆ 1.46    ┆ 0.24    ┆ 0.0146           │
│ 12       ┆ 16       ┆ change ┆ Swift             ┆ 1.38    ┆ 0.28    ┆ 0.0138           │
│ 13       ┆ 20       ┆ change ┆ Perl              ┆ 1.3     ┆ 0.26    ┆ 0.013            │
│ 14       ┆ 12       ┆ change ┆ Assembly language ┆ 1.3     ┆ -0.08   ┆ 0.013            │
│ 15       ┆ 15       ┆ null   ┆ Ruby              ┆ 1.24    ┆ 0.03    ┆ 0.0124           │
│ 16       ┆ 18       ┆ change ┆ MATLAB            ┆ 1.1     ┆ 0.04    ┆ 0.011            │
│ 17       ┆ 11       ┆ change ┆ Groovy            ┆ 0.99    ┆ -0.52   ┆ 0.0099           │
│ 18       ┆ 33       ┆ change ┆ Rust              ┆ 0.92    ┆ 0.55    ┆ 0.0092           │
│ 19       ┆ 10       ┆ change ┆ Objective-C       ┆ 0.85    ┆ -0.99   ┆ 0.0085           │
│ 20       ┆ 24       ┆ change ┆ Dart              ┆ 0.77    ┆ 0.13    ┆ 0.0077           │
└──────────┴──────────┴────────┴───────────────────┴─────────┴─────────┴──────────────────┘

Opět se podívejme na úplný zdrojový kód skriptu, který vygeneroval předchozí datový rámec:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
# přečtení zdrojových dat
df = polars.read_csv("tiobe.tsv", sep="\t")
 
# převod na skutečný poměr <0, 1>
df2 = df.with_column(
    polars.col("Ratings").apply(lambda x: x / 100.0).alias("Ratings as ratio")
)
 
# datový rámec zobrazíme
print(df)
print()
 
# datový rámec zobrazíme
print(df2)
print()
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame21_apply_conversi­on.py.

10. Rozdělení a následná agregace údajů s využitím metody groupby

Ve druhé polovině dnešního článku si popíšeme způsob zpracování a agregace údajů v datových rámcích s využitím metody pojmenované groupby, což je velmi často využívaná operace (u níž by se navíc měly projevit výkonnostní rozdíly mezi Pandas a Polars). V případě groupby se jedná o metodu, která umožňuje údaje z datových rámců nejprve rozdělit do skupin (tedy vlastně seskupit) s tím, že se údaje z každé skupiny posléze nějakým způsobem agregují; například se zjistí jejich počet, součet hodnot ve vybraném sloupci atd.

Zpracovávat přitom budeme následující datový soubor, který obsahuje jména těch programovacích jazyků, které byly serverem Tiobe každý rok vybrány na základě aktivity jejich uživatelů (či naopak začátečníků) na webu. Tento datový soubor můžete nalézt na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/ha­ll_of_fame.csv. Jedná se o klasický CSV soubor s hlavičkami sloupců:

Year,Winner
2022,C++
2021,Python
2020,Python
2019,C
2018,Python
2017,C
2016,Go
2015,Java
2014,JavaScript
2013,Transact-SQL
2012,Objective-C
2011,Objective-C
2010,Python
2009,Go
2008,C
2007,Python
2006,Ruby
2005,Java
2004,PHP
2003,C++

Povšimněte si, že některé jazyky vyhrály vícekrát, což nám umožňuje analýzu těchto dat právě s využitím operace groupby.

11. Praktická ukázka použití groupby

Metoda groupby nám umožňuje s datovým rámcem provést následující operace:

  1. Rozdělení do skupin údajů v datovém rámci na základě zadané podmínky nebo jen podle uložených hodnot ve sloupci (rozdělení na základě hodnot je přímočaré a použijeme ho v demonstračních příkladech).
  2. Aplikace vybrané funkce na výsledný datový blok, resp. na jeh sloupce.
  3. Kombinace či agregace výsledků (součet všech sdružených záznamů, jejich počet atd.)
Poznámka: pokud má být výsledkem groupby nový datový rámec, musí se vždy použít dvojice operací: rozdělení do skupin a agregace s případnou transformací dat, kterou lze provést v mezikroku.

Příkladem může být vytvoření nového datového rámce, který bude pro každý programovací jazyk obsahovat počet let, v nichž tento jazyk zvítězil (resp. kdy byl vybrán). Jazyky tedy nejprve rozdělíme podle jejich jména (což jsou údaje uložené ve sloupci „Winner“). Nepovinným parametrem maintain_order se určuje, zda se má zachovat pořadí skupin při provádění operací; což je ovšem časově náročná operace:

df.groupby("Winner", maintain_order=True)

Výsledkem bude nový datový blok (ale ne datový rámec!), nad nímž můžeme provádět další operace, zejména již výše zmíněnou agregaci. Můžeme například zjistit, pro jaký rok se každý jazyk ve své skupině vyskytuje. K tomuto účelu se použije agregační metoda zavolaná na objekt, jenž je výsledkem volání groupby (výsledkem totiž není plnohodnotný datový rámec, ale instance třídy polars.internals.dataframe­.groupby.GroupBy):

df.groupby("Winner", maintain_order=True).agg([polars.col("Year")])
Poznámka: agregační funkci lze předat větší množství sloupců, což ovšem v našem konkrétním případě nedává smysl.

Výsledek agregace je reprezentován ve formě nového datového rámce, který lze zobrazit či dále zpracovat libovolným způsobem:

df = df.groupby("Winner", maintain_order=True).agg([polars.col("Year")])
 
print(df)

S tímto výsledkem:

shape: (10, 2)
┌──────────────┬────────────────────────┐
│ Winner       ┆ Year                   │
│ ---          ┆ ---                    │
│ str          ┆ list[i64]              │
╞══════════════╪════════════════════════╡
│ C++          ┆ [2022, 2003]           │
│ Python       ┆ [2021, 2020, ... 2007] │
│ C            ┆ [2019, 2017, 2008]     │
│ Go           ┆ [2016, 2009]           │
│ Java         ┆ [2015, 2005]           │
│ JavaScript   ┆ [2014]                 │
│ Transact-SQL ┆ [2013]                 │
│ Objective-C  ┆ [2012, 2011]           │
│ Ruby         ┆ [2006]                 │
│ PHP          ┆ [2004]                 │
└──────────────┴────────────────────────┘

Uveďme si úplný zdrojový kód skriptu, který rozdělení a agregaci dat provádí:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
# seskupení podle názvu jazyka
df = df.groupby("Winner", maintain_order=True).agg([polars.col("Year")])
 
# zobrazíme datový rámec
print(df)
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame22_group_by.py.

12. Seřazení hodnot v průběhu jejich agregace

Ve chvíli, kdy máme k dispozici objekt vzniklý po rozdělení hodnot ze vstupního datového rámce do skupin, můžeme v metodě agg specifikovat nejenom nový sloupec (který bude v našem případě obsahovat seznam let, kdy daný programovací jazyk vyhrál), ale navíc můžeme hodnoty uložené v tomto sloupci seřadit:

df = df.groupby("Winner", maintain_order=True).agg([polars.col("Year").sort()])

Povšimněte si, že metodu sort voláme pro definici sloupce „Year“ obsahujícího agregovaná data, konkrétně seznam s roky. To tedy znamená, že dojde k seřazení hodnot uložených v těchto seznamech, nikoli k seřazení jednotlivých řádků (záznamů) ve výsledném datovém rámci. Konkrétně bude výsledek vypadat takto:

shape: (10, 2)
┌──────────────┬────────────────────────┐
│ Winner       ┆ Year                   │
│ ---          ┆ ---                    │
│ str          ┆ list[i64]              │
╞══════════════╪════════════════════════╡
│ C++          ┆ [2003, 2022]           │
│ Python       ┆ [2007, 2010, ... 2021] │
│ C            ┆ [2008, 2017, 2019]     │
│ Go           ┆ [2009, 2016]           │
│ Java         ┆ [2005, 2015]           │
│ JavaScript   ┆ [2014]                 │
│ Transact-SQL ┆ [2013]                 │
│ Objective-C  ┆ [2011, 2012]           │
│ Ruby         ┆ [2006]                 │
│ PHP          ┆ [2004]                 │
└──────────────┴────────────────────────┘

Rozdíl mezi předchozím příkladem a tímto příkladem uvidíme na řádku s Pythonem:

# seskupení podle názvu jazyka
df1 = df.groupby("Winner", maintain_order=True).agg([polars.col("Year")])
df2 = df.groupby("Winner", maintain_order=True).agg([polars.col("Year").sort()])
 
# výběr řádků s Pythonem, výběr dat ze sloupce Year a převod na seznam
print(df1[1]["Year"].to_list()[0])
print(df2[1]["Year"].to_list()[0])

Ve druhém případě dojde k seřazení seznamu let:

[2021, 2020, 2018, 2010, 2007]
[2007, 2010, 2018, 2020, 2021]

Podívejme se na úplný zdrojový kód tohoto demonstračního příkladu:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
# seskupení podle názvu jazyka
df = df.groupby("Winner", maintain_order=True).agg([polars.col("Year").sort()])
 
# zobrazíme datový rámec
print(df)
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame23_group_by_sort.py.

13. Seřazení záznamů v datovém rámci před provedením operace groupby s následnou agregací

Podívejme se nyní na to, jak bude výsledný datový rámec vytvořený operací groupby následovanou agregací vypadat v případě, že zdrojový datový rámec nejprve seřadíme podle názvu programovacího jazyka, tj. podle položek uložených ve sloupci „Winner“. Celá operace se tedy skládá z několika podoperací:

  1. Seřazení zdrojového datového rámce podle vybraného sloupce; výsledkem bude nový datový rámec.
  2. Rozdělení datového rámce na základě jména programovacího jazyka.
  3. Agregace podle sloupce „Year“
  4. Seřazení hodnot v agregovaném sloupci „Year“

Všechny tři kroky výše popsané operace lze zapsat jediným (poměrně přímočarým) výrazem:

df = df.sort("Winner"). \
     groupby("Winner", maintain_order=True).agg([polars.col("Year").sort()])

Výsledný datový rámec bude v tomto případě vypadat následovně:

┌──────────────┬────────────────────────┐
│ Winner       ┆ Year                   │
│ ---          ┆ ---                    │
│ str          ┆ list[i64]              │
╞══════════════╪════════════════════════╡
│ C            ┆ [2008, 2017, 2019]     │
│ C++          ┆ [2003, 2022]           │
│ Go           ┆ [2009, 2016]           │
│ Java         ┆ [2005, 2015]           │
│ JavaScript   ┆ [2014]                 │
│ Objective-C  ┆ [2011, 2012]           │
│ PHP          ┆ [2004]                 │
│ Python       ┆ [2007, 2010, ... 2021] │
│ Ruby         ┆ [2006]                 │
│ Transact-SQL ┆ [2013]                 │
└──────────────┴────────────────────────┘

Opět si samozřejmě uvedeme úplný zdrojový kód upraveného skriptu, který tento datový rámec vytvoří a vypíše:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
# seskupení podle názvu jazyka
df = df.sort("Winner"). \
     groupby("Winner", maintain_order=True).agg([polars.col("Year").sort()])
 
# zobrazíme datový rámec
print(df)
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame24_sort_group_by_sor­t.py.

14. Výpočet celkového pořadí vítězných programovacích jazyků

Výsledkem agregace provedené v předchozím příkladu je seznam let, v nichž byl daný programovací jazyk vítězný. Vzhledem k tomu, že se vždy jedná o seznam let reprezentovaných seznamem (hodnot typu int64), můžeme velmi snadno příklad upravit takovým způsobem, aby vracel nikoli tento seznam, ale počet let, v nichž programovací jazyk vyhrál. V případě Pythonu by se tedy měla vypočítat hodnota 5, u C hodnota 3 atd. Tohoto cíle dosáhneme snadno – použitím metody len aplikované na agregované výsledky:

# seskupení podle názvu jazyka
df = df.groupby("Winner", maintain_order=True).agg([polars.col("Year").len()])

Výsledkem by měl být datový rámec, který obsahuje ve sloupci „Year“ celkový počet let, v nichž daný programovací jazyk vyhrál:

shape: (10, 2)
┌──────────────┬──────┐
│ Winner       ┆ Year │
│ ---          ┆ ---  │
│ str          ┆ u32  │
╞══════════════╪══════╡
│ C++          ┆ 2    │
│ Python       ┆ 5    │
│ C            ┆ 3    │
│ Go           ┆ 2    │
│ Java         ┆ 2    │
│ JavaScript   ┆ 1    │
│ Transact-SQL ┆ 1    │
│ Objective-C  ┆ 2    │
│ Ruby         ┆ 1    │
│ PHP          ┆ 1    │
└──────────────┴──────┘

Upravený skript, který vypočítal předchozí datový rámec, vypadá takto:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
# seskupení podle názvu jazyka
df = df.groupby("Winner", maintain_order=True).agg([polars.col("Year").len()])
 
# zobrazíme datový rámec
print(df)
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame25_group_by_len.py.

15. Seřazení jazyků na základě jejich celkového pořadí

Vzhledem k tomu, že jazyky (alespoň prozatím) nejsou seřazeny podle jejich celkového pořadí, musíme toto seřazení provést explicitním zavoláním metody sort na agregované výsledky reprezentované novým datovým rámcem. Povšimněte si, že jsme poměrně snadným způsobem nadefinovali „pipelinu“ s několika operacemi a poměrně sofistikovaným chováním:

# seskupení podle názvu jazyka
df = df.groupby("Winner", maintain_order=True).agg([polars.col("Year").len()]).sort("Year")

S tímto výsledkem:

shape: (10, 2)
┌──────────────┬──────┐
│ Winner       ┆ Year │
│ ---          ┆ ---  │
│ str          ┆ u32  │
╞══════════════╪══════╡
│ JavaScript   ┆ 1    │
│ Transact-SQL ┆ 1    │
│ Ruby         ┆ 1    │
│ PHP          ┆ 1    │
│ C++          ┆ 2    │
│ Go           ┆ 2    │
│ Java         ┆ 2    │
│ Objective-C  ┆ 2    │
│ C            ┆ 3    │
│ Python       ┆ 5    │
└──────────────┴──────┘

Upravený skript:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
# seskupení podle názvu jazyka
df = df.groupby("Winner", maintain_order=True).agg([polars.col("Year").len()]).sort("Year")
 
# zobrazíme datový rámec
print(df)
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame26_group_by_len_sor­t.py.

16. Dva způsoby korektního seřazení výsledků

Vzhledem k tomu, že nás v celkovém pořadí většinou zajímají vítězové a nikoli nutně dolní část žebříčku, je vhodnější provést seřazení jazyků na základě agregovaných počtů „vítězných let“ od nejvyšší hodnoty k hodnotě nejnižší. K tomuto účelu můžeme použít dvojici operací sort+reverse, kdy se však v paměti zbytečně vytvoří datový rámec, který je po provedení další operace zahozen:

# seskupení podle názvu jazyka
df = df.groupby("Winner", maintain_order=True).agg([polars.col("Year").len()]).sort("Year").reverse()

Paměťově i z hlediska potřebného výpočetního výkonu lepší varianta spočívá v použití metody sort, které se kromě názvu sloupce předá i nepovinný parametr reverse=True:

# seskupení podle názvu jazyka
df = df.groupby("Winner", maintain_order=True).agg([polars.col("Year").len()]).sort("Year", reverse=True)

V obou případech dostaneme naprosto stejný výsledek:

shape: (10, 2)
┌──────────────┬──────┐
│ Winner       ┆ Year │
│ ---          ┆ ---  │
│ str          ┆ u32  │
╞══════════════╪══════╡
│ Python       ┆ 5    │
│ C            ┆ 3    │
│ Objective-C  ┆ 2    │
│ Java         ┆ 2    │
│ Go           ┆ 2    │
│ C++          ┆ 2    │
│ PHP          ┆ 1    │
│ Ruby         ┆ 1    │
│ Transact-SQL ┆ 1    │
│ JavaScript   ┆ 1    │
└──────────────┴──────┘

Skript, který tento datový rámec vypočítá, vypadá následovně:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
# seskupení podle názvu jazyka
df = df.groupby("Winner", maintain_order=True).agg([polars.col("Year").len()]).sort("Year").reverse()
 
# zobrazíme datový rámec
print(df)
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame27_group_by_len_sor­t_reverse.py.

Alternativní varianta skriptu:

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
# seskupení podle názvu jazyka
df = df.groupby("Winner", maintain_order=True).agg([polars.col("Year").len()]).sort("Year", reverse=True)
 
# zobrazíme datový rámec
print(df)

17. Příklad na závěr – složitější „pipeline“, změna názvu sloupce

V knihovně Polars (a prakticky stejně dobře v knihovně Pandas) můžeme se znalostí již známých operací definovat i složitější „pipeline“, například pipeline, která provede seskupení záznamů, jejich agregaci, seřazení, otočení a výběr prvních pěti záznamů z výsledného datového rámce. Navíc pro zajímavost ještě přejmenujeme sloupec „Year“ na „Zvítězil“ (pochopitelně lze v tomto případě použít celé Unicode, nejsme tedy omezeni jen na ASCII znaky):

#!/usr/bin/env python3
# vim: set fileencoding=utf-8
 
import polars
 
# přečtení zdrojových dat
df = polars.read_csv("hall_of_fame.csv")
 
# maximální počet zobrazených řádků
polars.Config.set_tbl_rows(100)
 
# seskupení podle názvu jazyka
df = df.groupby("Winner", maintain_order=True).agg([polars.col("Year").len().alias("Zvítězil")]). \
        sort("Zvítězil"). \
        reverse(). \
        head(5)
 
# zobrazíme datový rámec
print(df)

S tímto výsledkem:

ict ve školství 24

shape: (5, 2)
┌─────────────┬──────────┐
│ Winner      ┆ Zvítězil │
│ ---         ┆ ---      │
│ str         ┆ u32      │
╞═════════════╪══════════╡
│ Python      ┆ 5        │
│ C           ┆ 3        │
│ Objective-C ┆ 2        │
│ Java        ┆ 2        │
│ Go          ┆ 2        │
└─────────────┴──────────┘
Poznámka: úplný zdrojový kód tohoto demonstračního příkladu získáte na adrese https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame28_group_by_len_sor­t_reverse_head.py.

18. Obsah třetí části seriálu o knihovně Polars

Jak jsme si již několikrát připomenuli v předchozím textu, je knihovna Polars navržena takovým způsobem, aby byly operace s daty uloženými v datových řadách nebo v datových rámcích realizovány co nejrychleji, ideálně s využitím souběžně běžících úloh, ale i s využitím moderních SIMD operací. Vzhledem k tomu, že se jedná o velmi důležitou vlastnost (a vlastně o jediný důvod, proč vlastně přejít od PandasPolars), budeme se touto velmi zajímavou problematikou zabývat v navazujícím článku.

19. Repositář s demonstračními příklady

Zdrojové kódy všech prozatím popsaných demonstračních příkladů určených pro programovací jazyk Python 3 (nikoli ovšem pro starší verze Pythonu 2!) byly uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/most-popular-python-libs. V případě, že nebudete chtít klonovat celý repositář (ten je ovšem stále velmi malý, dnes má velikost zhruba několik desítek kilobajtů), můžete namísto toho použít odkazy na jednotlivé příklady, které naleznete v následující tabulce:

# Demonstrační příklad Stručný popis příkladu Cesta
1 series01_from_list.py konstrukce datové řady ze seznamu https://github.com/tisnik/most-popular-python-libs/blob/master/polars/se­ries01_from_list.py
2 series02_from_tuple.py konstrukce datové řady z n-tice https://github.com/tisnik/most-popular-python-libs/blob/master/polars/se­ries02_from_tuple.py
3 series03_from_range.py konstrukce datové řady generátorem range https://github.com/tisnik/most-popular-python-libs/blob/master/polars/se­ries03_from_range.py
4 series04_from_other_type.py použití odlišných datových typů prvků v datové řadě https://github.com/tisnik/most-popular-python-libs/blob/master/polars/se­ries04_from_other_type.py
5 series05_strings.py datová řada obsahující řetězce https://github.com/tisnik/most-popular-python-libs/blob/master/polars/se­ries05_strings.py
6 series06_booleans.py datová řada obsahující pravdivostní hodnoty https://github.com/tisnik/most-popular-python-libs/blob/master/polars/se­ries06_booleans.py
7 series07_null_value.py datová řada obsahující prvky s hodnotou null https://github.com/tisnik/most-popular-python-libs/blob/master/polars/se­ries07_null_value.py
8 series08_type_specification.py explicitní specifikace datového typu https://github.com/tisnik/most-popular-python-libs/blob/master/polars/se­ries08_type_specification­.py
9 series09_select.py výběr prvků z datové řady pomocí indexu, indexů či řezu https://github.com/tisnik/most-popular-python-libs/blob/master/polars/se­ries09_select.py
10 series10_filter.py výběr prvků z datové řady pomocí filtru (podmínky) https://github.com/tisnik/most-popular-python-libs/blob/master/polars/se­ries10_filter.py
11 series11_from_arange.py konstrukce datové řady s využitím numpy.arange https://github.com/tisnik/most-popular-python-libs/blob/master/polars/se­ries11_from_arange.py
12 series12_from_linspace.py konstrukce datové řady s využitím numpy.linspace https://github.com/tisnik/most-popular-python-libs/blob/master/polars/se­ries12_from_linspace.py
       
13 data_frame01_load_csv.py načtení dat ze souboru typu CSV https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame01_load_csv.py
14 data_frame02_load_csv_no_header_A.py práce se soubory typu CSV bez hlavičky (nekorektní varianta) https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame02_load_csv_no_he­ader_A.py
15 data_frame03_load_csv_no_header_B.py práce se soubory typu CSV bez hlavičky (korektní varianta) https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame03_load_csv_no_he­ader_B.py
16 data_frame04_load_csv_no_header_C.py práce se soubory typu CSV bez hlavičky (korektní varianta s explicitními jmény sloupců) https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame04_load_csv_no_he­ader_B.py
17 data_frame05_load_tsv_A.py práce se soubory typu TSV (nekorektní varianta) https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame05_load_tsv_A.py
18 data_frame06_load_tsv_B.py práce se soubory typu TSV (korektní varianta) https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame06_load_tsv_B.py
19 data_frame07_describe.py získání metainformací o datovém rámci https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame07_describe.py
20 data_frame08_timestamps_A.py načtení dat obsahujících časová razítka https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame08_timestamps_A.py
21 data_frame09_timestamps_B.py načtení dat obsahujících časová razítka https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame09_timestamps_B.py
22 data_frame10_load_sql_A.py načtení dat z relační databáze s uložením výsledku ve formě datového rámce https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame10_load_sql_A.py
23 data_frame11_load_sql_B.py načtení dat z relační databáze s uložením výsledku ve formě datového rámce https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame11_load_sql_B.py
       
24 data_frame12_head_A.py zobrazení hlavičky datového rámce https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame12_head_A.py
25 data_frame13_head_B.py zobrazení hlavičky datového rámce se specifikací počtu řádků https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame13_head_B.py
26 data_frame14_head_C.py globální změna počtu zobrazených řádků u datového rámce https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame14_head_C.py
27 data_frame15_formatting_A.py různé způsoby naformátování obsahu datových rámců https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame15_formatting_A.py
28 data_frame16_formatting_B.py různé způsoby naformátování obsahu datových rámců https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame16_formatting_B.py
29 data_frame17_sort.py seřazení údajů v datovém rámci https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame17_sort.py
30 data_frame18_sort_reverse.py zpětné seřazení údajů v datovém rámci https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame18_sort_reverse.py
31 data_frame19_unique.py zajištění unikátnosti záznamů https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame19_unique.py
32 data_frame20_map_conversion.py konverze dat ve sloupci s využitím metody map https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame20_map_conversion­.py
33 data_frame21_apply_conversion.py konverze dat ve sloupci s využitím metody apply https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame21_apply_conversi­on.py
34 data_frame22_group_by.py seskupení údajů na základě zvoleného sloupce https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame22_group_by.py
35 data_frame23_group_by_sort.py seskupení a seřazení údajů při agregaci na základě hodnot ve zvoleném sloupci https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame23_group_by_sort.py
36 data_frame23_group_by_sort_B.py ukázka rozdílů mezi použitím a nepoužitím sort při agregaci https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame23_group_by_sort_B­.py
37 data_frame24_sort_group_by_sort.py kombinace sort a groupby https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame24_sort_group_by_sor­t.py
38 data_frame25_group_by_len.py jednoduchá agregace údajů při seskupení https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame25_group_by_len.py
39 data_frame26_group_by_len_sort.py jednoduchá agregace údajů při seskupení, kombinace se seřazením https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame26_group_by_len_sor­t.py
40 data_frame27_group_by_len_sor­t_reverse.py jednoduchá agregace údajů při seskupení, kombinace se seřazením https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame27_group_by_len_sor­t_reverse.py
41 data_frame28_group_by_len_sor­t_reverse_head.py kombinace předchozího s head https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame28_group_by_len_sor­t_reverse_head.py

20. Odkazy na Internetu

  1. Projekt Polars na GitHubu
    https://github.com/pola-rs/polars
  2. Dokumentace k projektu Polars (popis API)
    https://pola-rs.github.io/polars/py-polars/html/reference/index.html
  3. Polars: The Next Big Python Data Science Library… written in RUST?
    https://www.youtube.com/wat­ch?v=VHqn7ufiilE
  4. Polars API: funkce pro načtení datového rámce z CSV
    https://pola-rs.github.io/polars/py-polars/html/reference/api/po­lars.read_csv.html
  5. Polars API: funkce pro načtení datového rámce z relační databáze
    https://pola-rs.github.io/polars/py-polars/html/reference/api/po­lars.read_sql.html
  6. Python’s Pandas vs Polars: Who Wins this Fight in Library 
    https://analyticsindiamag.com/pythons-pandas-vs-polars-who-wins-this-fight-in-library/
  7. Polars vs Pandas: what is more convenient?
    https://medium.com/@ilia.oz­hmegov/polars-vs-pandas-what-is-more-convenient-331956742a69
  8. A Gentle Introduction to Pandas Data Analysis (on Kaggle)
    https://www.youtube.com/wat­ch?v=_Eb0utIRdkw&list=PL7RwtdVQXQ8o­YpuIIDWR0SaaSCe8ZeZ7t&index=4
  9. Speed Up Your Pandas Dataframes
    https://www.youtube.com/wat­ch?v=u4_c2LDi4b8&list=PL7RwtdVQXQ8o­YpuIIDWR0SaaSCe8ZeZ7t&index=5
  10. pandas.read_csv
    https://pandas.pydata.org/pandas-docs/stable/reference/api/pan­das.read_csv.html
  11. How to define format when using pandas to_datetime?
    https://stackoverflow.com/qu­estions/36848514/how-to-define-format-when-using-pandas-to-datetime
  12. Pandas : skip rows while reading csv file to a Dataframe using read_csv() in Python
    https://thispointer.com/pandas-skip-rows-while-reading-csv-file-to-a-dataframe-using-read_csv-in-python/
  13. Skip rows during csv import pandas
    https://stackoverflow.com/qu­estions/20637439/skip-rows-during-csv-import-pandas
  14. Denni kurz
    https://www.cnb.cz/cs/finan­cni_trhy/devizovy_trh/kur­zy_devizoveho_trhu/denni_kur­z.txt
  15. UUID objects according to RFC 4122 (knihovna pro Python)
    https://docs.python.org/3­.5/library/uuid.html#uuid­.uuid4
  16. Object identifier (Wikipedia)
    https://en.wikipedia.org/wi­ki/Object_identifier
  17. Digital object identifier (Wikipedia)
    https://en.wikipedia.org/wi­ki/Digital_object_identifi­er
  18. voluptuous na (na PyPi)
    https://pypi.python.org/py­pi/voluptuous
  19. Repositář knihovny voluptuous na GitHubu
    https://github.com/alectho­mas/voluptuous
  20. pytest-voluptuous 1.0.2 (na PyPi)
    https://pypi.org/project/pytest-voluptuous/
  21. pytest-voluptuous (na GitHubu)
    https://github.com/F-Secure/pytest-voluptuous
  22. schemagic 0.9.1 (na PyPi)
    https://pypi.python.org/py­pi/schemagic/0.9.1
  23. Schemagic / Schemagic.web (na GitHubu)
    https://github.com/Mechrop­hile/schemagic
  24. schema 0.6.7 (na PyPi)
    https://pypi.python.org/pypi/schema
  25. schema (na GitHubu)
    https://github.com/keleshev/schema
  26. KX v DBOps Benchmark Results by Ferenc Bodon
    https://community.kx.com/t5/Community-Blogs/KX-v-DBOps-Benchmark-Results-by-Ferenc-Bodon/ba-p/12182
  27. TIOBE Index for January 2023
    https://www.tiobe.com/tiobe-index/

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.