Knihovna Polars: problematika spojování datových rámců

31. 1. 2023
Doba čtení: 33 minut

Sdílet

 Autor: Polars team, podle licence: CC BY-NC 2.5
Před vlastní analýzou či statistickým zpracováním dat s využitím knihovny Polars je v mnoha případech nutné data získat z několika samostatných zdrojů, které je zapotřebí načíst a nějakým způsobem spojit.

Obsah

1. Knihovna Polars: problematika spojování datových rámců

2. Vertikální spojení datových rámců

3. Spojení datových rámců po řádcích funkcí concat

4. Explicitní specifikace vertikálního spojení ve funkci concat

5. Horizontální spojení datových rámců

6. První (nefunkční) skript pro vertikální spojení datových rámců

7. Explicitní výběr sloupců z druhého datového rámce pro operaci spojení

8. Spojení dvou datových rámců operací typu join

9. Datové soubory použité v příkladech ukazujících operaci join

10. Realizace operace inner join (vnitřního spojení)

11. Left join (vnější spojení „zleva“)

12. Outer join (vnější spojení)

13. Křížové spojení (kartézský součin)

14. Ukázka realizace kartézského součinu pro datové rámce s pěti a čtyřmi záznamy

15. Kartézský součin pro datové rámce použité v předchozích příkladech

16. Anti join

17. „Levý“ anti join

18. „Pravý“ anti join

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

20. Odkazy na Internetu

1. Knihovna Polars: problematika spojování datových rámců

Před vlastní datovou analýzou či před statistickým zpracováním dat s využitím knihovny Polars je v mnoha případech nutné data nejdříve získat z několika samostatných zdrojů. Vzhledem k tomu, že většina operací (transformace, selekce, filtrace, seskupení, agregace) probíhá nad jediným datovým rámcem, je zapotřebí datové rámce se zdrojovými daty nějakým způsobem spojit. A právě těmito mnohdy relativně složitými operacemi, mezi něž se řadí i různé varianty operace join, se budeme zabývat v dnešním článku o knihovně Polars, jenž je současně i článkem závěrečným.

2. Vertikální spojení datových rámců

V knihovně Polars je možné datové rámce spojit jak „po řádcích“, tak i „po sloupcích“ a popř. i vyřešit splynutí hodnot z těch sloupců, které si logicky odpovídají. Nejdříve si ukážeme, jakým způsobem je možné spojit dva datové rámce „po řádcích“. K tomu využijeme datové soubory tiobeC.tsv a tiobeD.tsv.

První z těchto souborů tiobeC.tsv obsahuje horní polovinu tabulky, konkrétně prvních deset řádků a současně i hlavičku sloupců:

Sep 2020          Sep 2019          Change            Language          Ratings           Changep
1                 2                 change            C                 15.95             +0.74
2                 1                 change            Java              13.48             -3.18
3                 3                                   Python            10.47             +0.59
4                 4                                   C++               7.11              +1.48
5                 5                                   C#                4.58              +1.18
6                 6                                   Visual Basic      4.12              +0.83
7                 7                                   JavaScript        2.54              +0.41
8                 9                 change            PHP               2.49              +0.62
9                 19                change            R                 2.37              +1.33
10                8                 change            SQL               1.76              -0.19

Druhý soubor tiobeD.tsv taktéž obsahuje hlavičky sloupců a dále spodní polovinu tabulky, tedy dolních dvacet řádků:

Sep 2020          Sep 2019          Change            Language          Ratings           Changep
11                14                change            Go                1.46              +0.24
12                16                change            Swift             1.38              +0.28
13                20                change            Perl              1.30              +0.26
14                12                change            Assembly language 1.30              -0.08
15                15                                  Ruby              1.24              +0.03
16                18                change            MATLAB            1.10              +0.04
17                11                change            Groovy            0.99              -0.52
18                33                change            Rust              0.92              +0.55
19                10                change            Objective-C       0.85              -0.99
20                24                change            Dart              0.77              +0.13
Poznámka: v těchto dvou datových souborech jsou jednotlivé položky odděleny znakem Tab, ovšem v textu článku se tento znak expanduje na mezery (už jen z důvodu větší čitelnosti).

3. Spojení datových rámců po řádcích funkcí concat

Spojení dvou nebo i většího množství datových rámců nabízí funkce nazvaná concat, která je aplikovatelná pro libovolný počet instancí třídy DataFrame. Tato funkce dokáže datové rámce spojit buď po sloupcích nebo po řádcích, a to v závislosti na hodnotě parametru how, který by měl obsahovat hodnotu „horizontal“ nebo „vertical“ (popř. nebýt vůbec uveden):

Vyzkoušejme si nejprve použití této funkce s neuvedením typu spojení:

#!/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
df1 = polars.read_csv("tiobeC.tsv", sep="\t")
df2 = polars.read_csv("tiobeD.tsv", sep="\t")
 
# datové rámce zobrazíme
print(df1)
print()
print(df2)
print()
 
# spojení obou datových rámců
# bez uvedení parametru „how“
concatenated = polars.concat([df1, df2])
 
# výpis výsledku
print(concatenated)

Výsledkem činnosti tohoto skriptu bude skutečně nový datový rámec, který vznikne spojením obou zdrojových datových rámců. Skript nejdříve vypíše obsah obou zdrojových rámců a pak i rámec cílový:

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

4. Explicitní specifikace vertikálního spojení ve funkci concat

Vzhledem k tomu, že funkce concat dokáže rámce spojit jak po řádcích, tak i po sloupcích, je vhodné vždy uvádět (nepovinný) parametr how a nastavit ho na hodnotu „vertical“ (po řádcích) nebo „horizontal“ (po sloupcích):

#!/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
df1 = polars.read_csv("tiobeC.tsv", sep="\t")
df2 = polars.read_csv("tiobeD.tsv", sep="\t")
 
# datové rámce zobrazíme
print(df1)
print()
print(df2)
print()
 
# spojení obou datových rámců
concatenated = polars.concat([df1, df2], how="vertical")
 
# výpis výsledku
print(concatenated)

Výsledek by měl být totožný s předchozím demonstračním příkladem:

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

5. Horizontální spojení datových rámců

V další části článku si vysvětlíme, jak probíhá spojování datových rámců „po sloupcích“ neboli horizontálně. K tomuto účelu budou použity odlišné datové soubory – tiobeE.tsv a tiobeF.tsv.

Soubor tiobeE.tsv obsahuje pouze tři vybrané sloupce z původního rámce (tabulky). Mimochodem – žádný z těchto sloupců by nemohl sloužit jako index resp. primární klíč:

Language            Ratings             Changep
C                   15.95               +0.74
Java                13.48               -3.18
Python              10.47               +0.59
C++                 7.11                +1.48
C#                  4.58                +1.18
Visual Basic        4.12                +0.83
JavaScript          2.54                +0.41
PHP                 2.49                +0.62
R                   2.37                +1.33
SQL                 1.76                -0.19
Go                  1.46                +0.24
Swift               1.38                +0.28
Perl                1.30                +0.26
Assembly language   1.30                -0.08
Ruby                1.24                +0.03
MATLAB              1.10                +0.04
Groovy              0.99                -0.52
Rust                0.92                +0.55
Objective-C         0.85                -0.99
Dart                0.77                +0.13

Soubor nazvaný tiobeF.tsv taktéž obsahuje pouze vybrané datové sloupce z původní tabulky:

Sep 2020            Sep 2019            Change              Language
1                   2                   change              C
2                   1                   change              Java
3                   3                                       Python
4                   4                                       C++
5                   5                                       C#
6                   6                                       Visual Basic
7                   7                                       JavaScript
8                   9                   change              PHP
9                   19                  change              R
10                  8                   change              SQL
11                  14                  change              Go
12                  16                  change              Swift
13                  20                  change              Perl
14                  12                  change              Assembly language
15                  15                                      Ruby
16                  18                  change              MATLAB
17                  11                  change              Groovy
18                  33                  change              Rust
19                  10                  change              Objective-C
20                  24                  change              Dart
Poznámka: povšimněte si, že sloupec „Language“ existuje v obou tabulkách. Toho bylo možné využít v knihovně Pandas pro transformaci těchto sloupců na indexy, ovšem v Polars tento trik nelze využít.

6. První (nefunkční) skript pro vertikální spojení datových rámců

Nejprve si ukažme, jak se teoreticky provede spojení dvou datových rámců (které nejsou dále upraveny) „po sloupcích“ s využitím funkce concat. V tomto případě je nutné funkci concat předat seznam nebo n-tici, jejímiž prvky jsou reference na spojované datové rámce. A samozřejmě nesmíme zapomenout na parametr how, kterým určujeme, zda se spojení má provést po řádcích nebo po sloupcích:

#!/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
df1 = polars.read_csv("tiobeE.tsv", sep="\t")
df2 = polars.read_csv("tiobeF.tsv", sep="\t")
 
# datové rámce zobrazíme
print(df1)
print()
print(df2)
print()
 
# spojení obou datových rámců
concatenated = polars.concat([df1, df2], how="horizontal")
 
# výpis výsledku
print(concatenated)

Tento skript po svém spuštění nejdříve zobrazí oba načtené zdrojové datové rámce:

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

V dalším kroku by mělo dojít ke spojení obou datových rámců. To se však nepovede, a to z toho důvodu, že oba spojované rámce obsahují stejný sloupec nazvaný „Language“:

Traceback (most recent call last):
  File "data_frame_concat_horizontally_1.py", line 32, in <module>
    concatenated = polars.concat([df1, df2], how="horizontal")
  File "/home/ptisnovs/.local/lib/python3.8/site-packages/polars/internals/functions.py", line 232, in concat
    out = pli.wrap_df(_hor_concat_df(items))
exceptions.DuplicateError: Cannot do hstack operation. Column with name: Language already exists

7. Explicitní výběr sloupců z druhého datového rámce pro operaci spojení

Oprava předchozího skriptu může proběhnout mnoha různými způsoby. Jeden z možných způsobů spočívá v tom, že z prvního nebo druhého datového rámce odstraníme sloupec „Language“. Například provedeme odstranění tohoto sloupce ze druhého datového rámce:

df2 = df2.select(["Sep 2020", "Sep 2019", "Change"])

Upravený skript vypadá následovně:

#!/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
df1 = polars.read_csv("tiobeE.tsv", sep="\t")
df2 = polars.read_csv("tiobeF.tsv", sep="\t")
 
df2 = df2.select(["Sep 2020", "Sep 2019", "Change"])
 
# datové rámce zobrazíme
print(df1)
print()
print(df2)
print()
 
# spojení obou datových rámců
concatenated = polars.concat([df1, df2], how="horizontal")
 
# výpis výsledku
print(concatenated)

Výsledek (zobrazíme si pouze výsledný datový rámec) již nyní odpovídá očekávání – skutečně došlo ke spojení obou zdrojových rámců po sloupcích:

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

8. Spojení dvou datových rámců operací typu join

Velmi často se setkáme s nutností spojit dvě tabulky, které sice obsahují shodné sloupce, ovšem ne všechny řádky (resp. záznamy) nalezneme v obou spojovaných tabulkách. Taková operace je zcela běžná v oblasti relačních databází (přesněji řečeno v SQL databázích), kde pro ni existuje i klauzule JOIN. Podle toho, jakým způsobem jsou do výsledku zařazeny ty záznamy, které nejsou nalezeny v obou spojovaných tabulkách, rozlišujeme:

  1. vnitřní spojení (inner join)
  2. vnější spojení (outer join)

Vnější spojení je dále děleno na:

  1. úplné vnější spojení (outer join)
  2. vnější spojení zleva (left join)
  3. vnější spojení zprava (right join)

Tato operace je v knihovně Polars realizována metodou datového rámce nazvanou join; současně se jedná o jednu z funkcí, která dokáže do značné míry konfigurovat přesný postup operace spojení dvou datových rámců.

class DataFrame:
 def join(
        self,
        other: DataFrame,
        left_on: str | pli.Expr | Sequence[str | pli.Expr] | None = None,
        right_on: str | pli.Expr | Sequence[str | pli.Expr] | None = None,
        on: str | pli.Expr | Sequence[str | pli.Expr] | None = None,
        how: JoinStrategy = "inner",
        suffix: str = "_right",
    ) -> DataFrame:

9. Datové soubory použité v příkladech ukazujících operaci join

Vzhledem k velké univerzálnosti metody

join

si ukážeme její použití na několika demonstračních příkladech. Použijeme přitom datové rámce, které vzniknou načtením dvojice tabulek, které mají některé řádky shodné a jiné naopak v první či druhé tabulce zcela chybí.

V první tabulce je uloženo patnáct řádků původně získaných z Tiobe indexu:

Sep 2019            Change              Language            Ratings             Changep
2                   change              C                   15.95               +0.74
1                   change              Java                13.48               -3.18
3                                       Python              10.47               +0.59
4                                       C++                 7.11                +1.48
5                                       C#                  4.58                +1.18
6                                       Visual Basic        4.12                +0.83
7                                       JavaScript          2.54                +0.41
9                   change              PHP                 2.49                +0.62
19                  change              R                   2.37                +1.33
8                   change              SQL                 1.76                -0.19
14                  change              Go                  1.46                +0.24
16                  change              Swift               1.38                +0.28
20                  change              Perl                1.30                +0.26
12                  change              Assembly language   1.30                -0.08
15                                      Ruby                1.24                +0.03

Ve druhé tabulce je taktéž patnáct řádků původně získaných z Tiobe indexu, ovšem posledních pět řádků je od předchozí tabulky odlišných:

Sep 2020            Change              Language            Ratings             Changep
1                   change              C                   15.95               +0.74
2                   change              Java                13.48               -3.18
3                                       Python              10.47               +0.59
4                                       C++                 7.11                +1.48
5                                       C#                  4.58                +1.18
6                                       Visual Basic        4.12                +0.83
7                                       JavaScript          2.54                +0.41
8                   change              PHP                 2.49                +0.62
9                   change              R                   2.37                +1.33
10                  change              SQL                 1.76                -0.19
16                  change              MATLAB              1.10                +0.04
17                  change              Groovy              0.99                -0.52
18                  change              Rust                0.92                +0.55
19                  change              Objective-C         0.85                -0.99
20                  change              Dart                0.77                +0.13

A takto vypadají datové rámce načtené demonstračními příklady z navazujících kapitol (už tyto výpisy nebudeme kvůli místu opakovat):

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

10. Realizace operace inner join (vnitřního spojení)

Operace vnitřního spojení neboli inner join dokáže automaticky spojit ty řádky tabulek, které mají totožný obsah vybraného sloupce nebo sloupců (tyto sloupce jsou tedy použity ve funkci klíčů). Současně jsou i identifikovány sloupce se shodným názvem a typem (pokud neurčíme jinak). Podívejme se nyní na způsob provedení této operace u datových rámců, které mají implicitní (celočíselné) indexy, což je ostatně v Polars jediná varianta (na rozdíl od knihovny Pandas):

#!/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
df1 = polars.read_csv("tiobeA.tsv", sep="\t")
df2 = polars.read_csv("tiobeB.tsv", sep="\t")
 
# datové rámce zobrazíme
print(df1)
print()
print(df2)
print()
 
# spojení obou datových rámců
merged = df1.join(df2, on="Language", how="inner")
 
# výpis výsledku
print(merged)

Výsledný datový rámec obsahuje pouze deset řádků obsažených v levém i pravém rámci vstupujícím do operace JOIN. Zbylých deset řádků (pět z levého rámce, jiných pět z rámce druhého) zde nenalezneme:

shape: (10, 9)
┌──────────┬────────┬──────────────┬─────────┬─────┬──────────┬──────────────┬───────────────┬───────────────┐
│ Sep 2019 ┆ Change ┆ Language     ┆ Ratings ┆ ... ┆ Sep 2020 ┆ Change_right ┆ Ratings_right ┆ Changep_right │
│ ---      ┆ ---    ┆ ---          ┆ ---     ┆     ┆ ---      ┆ ---          ┆ ---           ┆ ---           │
│ i64      ┆ str    ┆ str          ┆ f64     ┆     ┆ i64      ┆ str          ┆ f64           ┆ f64           │
╞══════════╪════════╪══════════════╪═════════╪═════╪══════════╪══════════════╪═══════════════╪═══════════════╡
│ 2        ┆ change ┆ C            ┆ 15.95   ┆ ... ┆ 1        ┆ change       ┆ 15.95         ┆ 0.74          │
│ 1        ┆ change ┆ Java         ┆ 13.48   ┆ ... ┆ 2        ┆ change       ┆ 13.48         ┆ -3.18         │
│ 3        ┆ null   ┆ Python       ┆ 10.47   ┆ ... ┆ 3        ┆ null         ┆ 10.47         ┆ 0.59          │
│ 4        ┆ null   ┆ C++          ┆ 7.11    ┆ ... ┆ 4        ┆ null         ┆ 7.11          ┆ 1.48          │
│ 5        ┆ null   ┆ C#           ┆ 4.58    ┆ ... ┆ 5        ┆ null         ┆ 4.58          ┆ 1.18          │
│ 6        ┆ null   ┆ Visual Basic ┆ 4.12    ┆ ... ┆ 6        ┆ null         ┆ 4.12          ┆ 0.83          │
│ 7        ┆ null   ┆ JavaScript   ┆ 2.54    ┆ ... ┆ 7        ┆ null         ┆ 2.54          ┆ 0.41          │
│ 9        ┆ change ┆ PHP          ┆ 2.49    ┆ ... ┆ 8        ┆ change       ┆ 2.49          ┆ 0.62          │
│ 19       ┆ change ┆ R            ┆ 2.37    ┆ ... ┆ 9        ┆ change       ┆ 2.37          ┆ 1.33          │
│ 8        ┆ change ┆ SQL          ┆ 1.76    ┆ ... ┆ 10       ┆ change       ┆ 1.76          ┆ -0.19         │
└──────────┴────────┴──────────────┴─────────┴─────┴──────────┴──────────────┴───────────────┴───────────────┘

11. Left join (vnější spojení „zleva“)

Ukažme si nyní způsob provedení vnějšího spojení dvou datových rámců zleva. Toto spojení je specifikováno parametrem how nastaveným na hodnotu „left“ (jedná se o řetězec). Ve výsledném datovém rámci budou za všech okolností všechny řádky z levého rámce, a to i ve chvíli, kdy k nim nebyly nalezeny odpovídající řádky v pravém rámci:

#!/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
df1 = polars.read_csv("tiobeA.tsv", sep="\t")
df2 = polars.read_csv("tiobeB.tsv", sep="\t")
 
# datové rámce zobrazíme
print(df1)
print()
print(df2)
print()
 
# spojení obou datových rámců
merged = df1.join(df2, on="Language", how="left")
 
# výpis výsledku
print(merged)

Ve výsledném datovém rámci je po spojení uloženo celkem patnáct řádků, protože byly přidány i všechny řádky z prvního (levého) datového rámce, které ovšem nemají všechny potřebné údaje ve sloupci Sep 2020. Proto je namísto těchto hodnot použita null, kterou Polars plně podporuje u všech datových typů:

shape: (15, 9)
┌──────────┬────────┬───────────────────┬─────────┬─────┬──────────┬──────────────┬───────────────┬───────────────┐
│ Sep 2019 ┆ Change ┆ Language          ┆ Ratings ┆ ... ┆ Sep 2020 ┆ Change_right ┆ Ratings_right ┆ Changep_right │
│ ---      ┆ ---    ┆ ---               ┆ ---     ┆     ┆ ---      ┆ ---          ┆ ---           ┆ ---           │
│ i64      ┆ str    ┆ str               ┆ f64     ┆     ┆ i64      ┆ str          ┆ f64           ┆ f64           │
╞══════════╪════════╪═══════════════════╪═════════╪═════╪══════════╪══════════════╪═══════════════╪═══════════════╡
│ 2        ┆ change ┆ C                 ┆ 15.95   ┆ ... ┆ 1        ┆ change       ┆ 15.95         ┆ 0.74          │
│ 1        ┆ change ┆ Java              ┆ 13.48   ┆ ... ┆ 2        ┆ change       ┆ 13.48         ┆ -3.18         │
│ 3        ┆ null   ┆ Python            ┆ 10.47   ┆ ... ┆ 3        ┆ null         ┆ 10.47         ┆ 0.59          │
│ 4        ┆ null   ┆ C++               ┆ 7.11    ┆ ... ┆ 4        ┆ null         ┆ 7.11          ┆ 1.48          │
│ 5        ┆ null   ┆ C#                ┆ 4.58    ┆ ... ┆ 5        ┆ null         ┆ 4.58          ┆ 1.18          │
│ 6        ┆ null   ┆ Visual Basic      ┆ 4.12    ┆ ... ┆ 6        ┆ null         ┆ 4.12          ┆ 0.83          │
│ 7        ┆ null   ┆ JavaScript        ┆ 2.54    ┆ ... ┆ 7        ┆ null         ┆ 2.54          ┆ 0.41          │
│ 9        ┆ change ┆ PHP               ┆ 2.49    ┆ ... ┆ 8        ┆ change       ┆ 2.49          ┆ 0.62          │
│ 19       ┆ change ┆ R                 ┆ 2.37    ┆ ... ┆ 9        ┆ change       ┆ 2.37          ┆ 1.33          │
│ 8        ┆ change ┆ SQL               ┆ 1.76    ┆ ... ┆ 10       ┆ change       ┆ 1.76          ┆ -0.19         │
│ 14       ┆ change ┆ Go                ┆ 1.46    ┆ ... ┆ null     ┆ null         ┆ null          ┆ null          │
│ 16       ┆ change ┆ Swift             ┆ 1.38    ┆ ... ┆ null     ┆ null         ┆ null          ┆ null          │
│ 20       ┆ change ┆ Perl              ┆ 1.3     ┆ ... ┆ null     ┆ null         ┆ null          ┆ null          │
│ 12       ┆ change ┆ Assembly language ┆ 1.3     ┆ ... ┆ null     ┆ null         ┆ null          ┆ null          │
│ 15       ┆ null   ┆ Ruby              ┆ 1.24    ┆ ... ┆ null     ┆ null         ┆ null          ┆ null          │
└──────────┴────────┴───────────────────┴─────────┴─────┴──────────┴──────────────┴───────────────┴───────────────┘

12. Outer join (vnější spojení)

Zbývá nám popis poslední klasické varianty spojení datových rámců – plný outer join specifikovaný hodnotou „outer“ předanou do pojmenovaného parametru how. Zdrojový kód příkladu tedy opět upravíme, a to konkrétně do této podoby:

#!/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
df1 = polars.read_csv("tiobeA.tsv", sep="\t")
df2 = polars.read_csv("tiobeB.tsv", sep="\t")
 
# datové rámce zobrazíme
print(df1)
print()
print(df2)
print()
 
# spojení obou datových rámců
merged = df1.join(df2, on="Language", how="outer")
 
# výpis výsledku
print(merged)

Nyní bude výsledný datový rámec obsahovat všech dvacet řádků, ovšem některé sloupce musely být doplněny hodnotami null, protože je nebylo možné získat ani z jednoho datového rámce:

shape: (20, 9)
┌──────────┬────────┬───────────────────┬─────────┬─────┬──────────┬──────────────┬───────────────┬───────────────┐
│ Sep 2019 ┆ Change ┆ Language          ┆ Ratings ┆ ... ┆ Sep 2020 ┆ Change_right ┆ Ratings_right ┆ Changep_right │
│ ---      ┆ ---    ┆ ---               ┆ ---     ┆     ┆ ---      ┆ ---          ┆ ---           ┆ ---           │
│ i64      ┆ str    ┆ str               ┆ f64     ┆     ┆ i64      ┆ str          ┆ f64           ┆ f64           │
╞══════════╪════════╪═══════════════════╪═════════╪═════╪══════════╪══════════════╪═══════════════╪═══════════════╡
│ 2        ┆ change ┆ C                 ┆ 15.95   ┆ ... ┆ 1        ┆ change       ┆ 15.95         ┆ 0.74          │
│ 1        ┆ change ┆ Java              ┆ 13.48   ┆ ... ┆ 2        ┆ change       ┆ 13.48         ┆ -3.18         │
│ 3        ┆ null   ┆ Python            ┆ 10.47   ┆ ... ┆ 3        ┆ null         ┆ 10.47         ┆ 0.59          │
│ 4        ┆ null   ┆ C++               ┆ 7.11    ┆ ... ┆ 4        ┆ null         ┆ 7.11          ┆ 1.48          │
│ 5        ┆ null   ┆ C#                ┆ 4.58    ┆ ... ┆ 5        ┆ null         ┆ 4.58          ┆ 1.18          │
│ 6        ┆ null   ┆ Visual Basic      ┆ 4.12    ┆ ... ┆ 6        ┆ null         ┆ 4.12          ┆ 0.83          │
│ 7        ┆ null   ┆ JavaScript        ┆ 2.54    ┆ ... ┆ 7        ┆ null         ┆ 2.54          ┆ 0.41          │
│ 9        ┆ change ┆ PHP               ┆ 2.49    ┆ ... ┆ 8        ┆ change       ┆ 2.49          ┆ 0.62          │
│ 19       ┆ change ┆ R                 ┆ 2.37    ┆ ... ┆ 9        ┆ change       ┆ 2.37          ┆ 1.33          │
│ 8        ┆ change ┆ SQL               ┆ 1.76    ┆ ... ┆ 10       ┆ change       ┆ 1.76          ┆ -0.19         │
│ null     ┆ null   ┆ MATLAB            ┆ null    ┆ ... ┆ 16       ┆ change       ┆ 1.1           ┆ 0.04          │
│ null     ┆ null   ┆ Groovy            ┆ null    ┆ ... ┆ 17       ┆ change       ┆ 0.99          ┆ -0.52         │
│ null     ┆ null   ┆ Rust              ┆ null    ┆ ... ┆ 18       ┆ change       ┆ 0.92          ┆ 0.55          │
│ null     ┆ null   ┆ Objective-C       ┆ null    ┆ ... ┆ 19       ┆ change       ┆ 0.85          ┆ -0.99         │
│ null     ┆ null   ┆ Dart              ┆ null    ┆ ... ┆ 20       ┆ change       ┆ 0.77          ┆ 0.13          │
│ 12       ┆ change ┆ Assembly language ┆ 1.3     ┆ ... ┆ null     ┆ null         ┆ null          ┆ null          │
│ 16       ┆ change ┆ Swift             ┆ 1.38    ┆ ... ┆ null     ┆ null         ┆ null          ┆ null          │
│ 20       ┆ change ┆ Perl              ┆ 1.3     ┆ ... ┆ null     ┆ null         ┆ null          ┆ null          │
│ 14       ┆ change ┆ Go                ┆ 1.46    ┆ ... ┆ null     ┆ null         ┆ null          ┆ null          │
│ 15       ┆ null   ┆ Ruby              ┆ 1.24    ┆ ... ┆ null     ┆ null         ┆ null          ┆ null          │
└──────────┴────────┴───────────────────┴─────────┴─────┴──────────┴──────────────┴───────────────┴───────────────┘

13. Křížové spojení (kartézský součin)

Další variantou operace join je takzvaný cross join neboli česky „křížové spojení“. Výsledkem křížového spojování je kartézský součin položek z obou vstupních datových rámců. Výsledný datový rámec bude obsahovat všechny uspořádané dvojice, ve kterých je první položka prvkem z prvního datového rámce (všechny sloupce) a druhá položka je prvkem druhého datového rámce. Kartézský součin obsahuje všechny takové kombinace těchto prvků, což znamená, že pokud má první rámec n záznamů a druhý rámec m záznamů, bude výsledný datový rámec obsahovat m×n záznamů.

14. Ukázka realizace kartézského součinu pro datové rámce s pěti a čtyřmi záznamy

Vyzkoušejme si nyní, jak vlastně bude vypadat kartézský součin dvou datových rámců, z nichž první rámec obsahuje pět záznamů (vlastnost jazyka) a druhý rámec obsahuje čtyři záznamy (jméno programovacího jazyka). Kartézským součinem by měl vzniknout nový datový rámec s 5×4=20 záznamy, tedy se všemi možnými kombinacemi vlastnost:jazyk:

#!/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
df1 = polars.DataFrame(["wonderful", "terible", "popular", "fast", "slow"])
df2 = polars.DataFrame(["Python", "Perl", "Java", "Go"])
 
# datové rámce zobrazíme
print(df1)
print()
print(df2)
print()
 
# spojení obou datových rámců
merged = df1.join(df2, on="Language", how="cross")
 
# výpis výsledku
print(merged)

Tento skript po svém spuštění nejdříve vypíše oba zdrojové datové rámce:

shape: (5, 1)
┌───────────┐
│ column_0  │
│ ---       │
│ str       │
╞═══════════╡
│ wonderful │
│ terible   │
│ popular   │
│ fast      │
│ slow      │
└───────────┘
 
shape: (4, 1)
┌──────────┐
│ column_0 │
│ ---      │
│ str      │
╞══════════╡
│ Python   │
│ Perl     │
│ Java     │
│ Go       │
└──────────┘

Následně se vypíše obsah datového rámce, který vznikl kartézským součinem obou zdrojových datových rámců:

shape: (20, 2)
┌───────────┬────────────────┐
│ column_0  ┆ column_0_right │
│ ---       ┆ ---            │
│ str       ┆ str            │
╞═══════════╪════════════════╡
│ wonderful ┆ Python         │
│ wonderful ┆ Perl           │
│ wonderful ┆ Java           │
│ wonderful ┆ Go             │
│ terible   ┆ Python         │
│ terible   ┆ Perl           │
│ terible   ┆ Java           │
│ terible   ┆ Go             │
│ popular   ┆ Python         │
│ popular   ┆ Perl           │
│ popular   ┆ Java           │
│ popular   ┆ Go             │
│ fast      ┆ Python         │
│ fast      ┆ Perl           │
│ fast      ┆ Java           │
│ fast      ┆ Go             │
│ slow      ┆ Python         │
│ slow      ┆ Perl           │
│ slow      ┆ Java           │
│ slow      ┆ Go             │
└───────────┴────────────────┘

15. Kartézský součin pro datové rámce použité v předchozích příkladech

Pro zajímavost si můžeme ukázat, jaký výsledek získáme po kartézském součinu (resp. křížovém spojení) dvou datových rámců používaných v předchozích kapitolách. Každý z těchto datových rámců obsahuje 15 záznamů, takže výsledkem by měl být datový rámec s 15×15=225 záznamy:

#!/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
df1 = polars.read_csv("tiobeA.tsv", sep="\t")
df2 = polars.read_csv("tiobeB.tsv", sep="\t")
 
# datové rámce zobrazíme
print(df1)
print()
print(df2)
print()
 
# spojení obou datových rámců
merged = df1.join(df2, on="Language", how="cross")
 
# výpis výsledku
print(merged)

Tento skript nejdříve vypíše oba zdrojové datové rámce, z nichž každý obsahuje již výše zmíněných patnáct záznamů:

shape: (15, 5)
┌──────────┬────────┬───────────────────┬─────────┬─────────┐
│ Sep 2019 ┆ Change ┆ Language          ┆ Ratings ┆ Changep │
│ ---      ┆ ---    ┆ ---               ┆ ---     ┆ ---     │
│ i64      ┆ str    ┆ str               ┆ f64     ┆ f64     │
╞══════════╪════════╪═══════════════════╪═════════╪═════════╡
│ 2        ┆ change ┆ C                 ┆ 15.95   ┆ 0.74    │
│ 1        ┆ change ┆ Java              ┆ 13.48   ┆ -3.18   │
│ 3        ┆ null   ┆ Python            ┆ 10.47   ┆ 0.59    │
│ 4        ┆ null   ┆ C++               ┆ 7.11    ┆ 1.48    │
│ 5        ┆ null   ┆ C#                ┆ 4.58    ┆ 1.18    │
│ 6        ┆ null   ┆ Visual Basic      ┆ 4.12    ┆ 0.83    │
│ 7        ┆ null   ┆ JavaScript        ┆ 2.54    ┆ 0.41    │
│ 9        ┆ change ┆ PHP               ┆ 2.49    ┆ 0.62    │
│ 19       ┆ change ┆ R                 ┆ 2.37    ┆ 1.33    │
│ 8        ┆ change ┆ SQL               ┆ 1.76    ┆ -0.19   │
│ 14       ┆ change ┆ Go                ┆ 1.46    ┆ 0.24    │
│ 16       ┆ change ┆ Swift             ┆ 1.38    ┆ 0.28    │
│ 20       ┆ change ┆ Perl              ┆ 1.3     ┆ 0.26    │
│ 12       ┆ change ┆ Assembly language ┆ 1.3     ┆ -0.08   │
│ 15       ┆ null   ┆ Ruby              ┆ 1.24    ┆ 0.03    │
└──────────┴────────┴───────────────────┴─────────┴─────────┘

a:

shape: (15, 5)
┌──────────┬────────┬──────────────┬─────────┬─────────┐
│ Sep 2020 ┆ Change ┆ Language     ┆ Ratings ┆ Changep │
│ ---      ┆ ---    ┆ ---          ┆ ---     ┆ ---     │
│ i64      ┆ str    ┆ str          ┆ f64     ┆ f64     │
╞══════════╪════════╪══════════════╪═════════╪═════════╡
│ 1        ┆ change ┆ C            ┆ 15.95   ┆ 0.74    │
│ 2        ┆ change ┆ Java         ┆ 13.48   ┆ -3.18   │
│ 3        ┆ null   ┆ Python       ┆ 10.47   ┆ 0.59    │
│ 4        ┆ null   ┆ C++          ┆ 7.11    ┆ 1.48    │
│ 5        ┆ null   ┆ C#           ┆ 4.58    ┆ 1.18    │
│ 6        ┆ null   ┆ Visual Basic ┆ 4.12    ┆ 0.83    │
│ 7        ┆ null   ┆ JavaScript   ┆ 2.54    ┆ 0.41    │
│ 8        ┆ change ┆ PHP          ┆ 2.49    ┆ 0.62    │
│ 9        ┆ change ┆ R            ┆ 2.37    ┆ 1.33    │
│ 10       ┆ change ┆ SQL          ┆ 1.76    ┆ -0.19   │
│ 16       ┆ change ┆ MATLAB       ┆ 1.1     ┆ 0.04    │
│ 17       ┆ change ┆ Groovy       ┆ 0.99    ┆ -0.52   │
│ 18       ┆ change ┆ Rust         ┆ 0.92    ┆ 0.55    │
│ 19       ┆ change ┆ Objective-C  ┆ 0.85    ┆ -0.99   │
│ 20       ┆ change ┆ Dart         ┆ 0.77    ┆ 0.13    │
└──────────┴────────┴──────────────┴─────────┴─────────┘

Křížovým spojením skutečně vznikne již relativně rozsáhlý datový rámec s 225 záznamy:

shape: (225, 10)
┌──────────┬────────┬──────────┬─────────┬─────┬────────────┬────────────┬────────────┬────────────┐
│ Sep 2019 ┆ Change ┆ Language ┆ Ratings ┆ ... ┆ Change_rig ┆ Language_r ┆ Ratings_ri ┆ Changep_ri │
│ ---      ┆ ---    ┆ ---      ┆ ---     ┆     ┆ ht         ┆ ight       ┆ ght        ┆ ght        │
│ i64      ┆ str    ┆ str      ┆ f64     ┆     ┆ ---        ┆ ---        ┆ ---        ┆ ---        │
│          ┆        ┆          ┆         ┆     ┆ str        ┆ str        ┆ f64        ┆ f64        │
╞══════════╪════════╪══════════╪═════════╪═════╪════════════╪════════════╪════════════╪════════════╡
│ 2        ┆ change ┆ C        ┆ 15.95   ┆ ... ┆ change     ┆ C          ┆ 15.95      ┆ 0.74       │
│ 2        ┆ change ┆ C        ┆ 15.95   ┆ ... ┆ change     ┆ Java       ┆ 13.48      ┆ -3.18      │
│ 2        ┆ change ┆ C        ┆ 15.95   ┆ ... ┆ null       ┆ Python     ┆ 10.47      ┆ 0.59       │
│ 2        ┆ change ┆ C        ┆ 15.95   ┆ ... ┆ null       ┆ C++        ┆ 7.11       ┆ 1.48       │
│ 2        ┆ change ┆ C        ┆ 15.95   ┆ ... ┆ null       ┆ C#         ┆ 4.58       ┆ 1.18       │
│ 2        ┆ change ┆ C        ┆ 15.95   ┆ ... ┆ null       ┆ Visual     ┆ 4.12       ┆ 0.83       │
│          ┆        ┆          ┆         ┆     ┆            ┆ Basic      ┆            ┆            │
│ 2        ┆ change ┆ C        ┆ 15.95   ┆ ... ┆ null       ┆ JavaScript ┆ 2.54       ┆ 0.41       │
│ 2        ┆ change ┆ C        ┆ 15.95   ┆ ... ┆ change     ┆ PHP        ┆ 2.49       ┆ 0.62       │
│ 2        ┆ change ┆ C        ┆ 15.95   ┆ ... ┆ change     ┆ R          ┆ 2.37       ┆ 1.33       │
│ 2        ┆ change ┆ C        ┆ 15.95   ┆ ... ┆ change     ┆ SQL        ┆ 1.76       ┆ -0.19      │
│ 2        ┆ change ┆ C        ┆ 15.95   ┆ ... ┆ change     ┆ MATLAB     ┆ 1.1        ┆ 0.04       │
│ 2        ┆ change ┆ C        ┆ 15.95   ┆ ... ┆ change     ┆ Groovy     ┆ 0.99       ┆ -0.52      │
│ 2        ┆ change ┆ C        ┆ 15.95   ┆ ... ┆ change     ┆ Rust       ┆ 0.92       ┆ 0.55       │
│ 2        ┆ change ┆ C        ┆ 15.95   ┆ ... ┆ change     ┆ Objective- ┆ 0.85       ┆ -0.99      │
│          ┆        ┆          ┆         ┆     ┆            ┆ C          ┆            ┆            │
│ 2        ┆ change ┆ C        ┆ 15.95   ┆ ... ┆ change     ┆ Dart       ┆ 0.77       ┆ 0.13       │
│ 1        ┆ change ┆ Java     ┆ 13.48   ┆ ... ┆ change     ┆ C          ┆ 15.95      ┆ 0.74       │
│ 1        ┆ change ┆ Java     ┆ 13.48   ┆ ... ┆ change     ┆ Java       ┆ 13.48      ┆ -3.18      │
│ 1        ┆ change ┆ Java     ┆ 13.48   ┆ ... ┆ null       ┆ Python     ┆ 10.47      ┆ 0.59       │
│ 1        ┆ change ┆ Java     ┆ 13.48   ┆ ... ┆ null       ┆ C++        ┆ 7.11       ┆ 1.48       │
│ 1        ┆ change ┆ Java     ┆ 13.48   ┆ ... ┆ null       ┆ C#         ┆ 4.58       ┆ 1.18       │
│ 1        ┆ change ┆ Java     ┆ 13.48   ┆ ... ┆ null       ┆ Visual     ┆ 4.12       ┆ 0.83       │
│          ┆        ┆          ┆         ┆     ┆            ┆ Basic      ┆            ┆            │
│ 1        ┆ change ┆ Java     ┆ 13.48   ┆ ... ┆ null       ┆ JavaScript ┆ 2.54       ┆ 0.41       │
│ 1        ┆ change ┆ Java     ┆ 13.48   ┆ ... ┆ change     ┆ PHP        ┆ 2.49       ┆ 0.62       │
│ 1        ┆ change ┆ Java     ┆ 13.48   ┆ ... ┆ change     ┆ R          ┆ 2.37       ┆ 1.33       │
│ 1        ┆ change ┆ Java     ┆ 13.48   ┆ ... ┆ change     ┆ SQL        ┆ 1.76       ┆ -0.19      │
│ 1        ┆ change ┆ Java     ┆ 13.48   ┆ ... ┆ change     ┆ MATLAB     ┆ 1.1        ┆ 0.04       │
│ 1        ┆ change ┆ Java     ┆ 13.48   ┆ ... ┆ change     ┆ Groovy     ┆ 0.99       ┆ -0.52      │
│ 1        ┆ change ┆ Java     ┆ 13.48   ┆ ... ┆ change     ┆ Rust       ┆ 0.92       ┆ 0.55       │
│ 1        ┆ change ┆ Java     ┆ 13.48   ┆ ... ┆ change     ┆ Objective- ┆ 0.85       ┆ -0.99      │
│          ┆        ┆          ┆         ┆     ┆            ┆ C          ┆            ┆            │
│ 1        ┆ change ┆ Java     ┆ 13.48   ┆ ... ┆ change     ┆ Dart       ┆ 0.77       ┆ 0.13       │
│ 3        ┆ null   ┆ Python   ┆ 10.47   ┆ ... ┆ change     ┆ C          ┆ 15.95      ┆ 0.74       │
│ 3        ┆ null   ┆ Python   ┆ 10.47   ┆ ... ┆ change     ┆ Java       ┆ 13.48      ┆ -3.18      │
│ 3        ┆ null   ┆ Python   ┆ 10.47   ┆ ... ┆ null       ┆ Python     ┆ 10.47      ┆ 0.59       │
│ 3        ┆ null   ┆ Python   ┆ 10.47   ┆ ... ┆ null       ┆ C++        ┆ 7.11       ┆ 1.48       │
│ 3        ┆ null   ┆ Python   ┆ 10.47   ┆ ... ┆ null       ┆ C#         ┆ 4.58       ┆ 1.18       │
│ 3        ┆ null   ┆ Python   ┆ 10.47   ┆ ... ┆ null       ┆ Visual     ┆ 4.12       ┆ 0.83       │
│          ┆        ┆          ┆         ┆     ┆            ┆ Basic      ┆            ┆            │
│ 3        ┆ null   ┆ Python   ┆ 10.47   ┆ ... ┆ null       ┆ JavaScript ┆ 2.54       ┆ 0.41       │
│ 3        ┆ null   ┆ Python   ┆ 10.47   ┆ ... ┆ change     ┆ PHP        ┆ 2.49       ┆ 0.62       │
│ 3        ┆ null   ┆ Python   ┆ 10.47   ┆ ... ┆ change     ┆ R          ┆ 2.37       ┆ 1.33       │
│ 3        ┆ null   ┆ Python   ┆ 10.47   ┆ ... ┆ change     ┆ SQL        ┆ 1.76       ┆ -0.19      │
│ 3        ┆ null   ┆ Python   ┆ 10.47   ┆ ... ┆ change     ┆ MATLAB     ┆ 1.1        ┆ 0.04       │
│ 3        ┆ null   ┆ Python   ┆ 10.47   ┆ ... ┆ change     ┆ Groovy     ┆ 0.99       ┆ -0.52      │
│ 3        ┆ null   ┆ Python   ┆ 10.47   ┆ ... ┆ change     ┆ Rust       ┆ 0.92       ┆ 0.55       │
│ 3        ┆ null   ┆ Python   ┆ 10.47   ┆ ... ┆ change     ┆ Objective- ┆ 0.85       ┆ -0.99      │
│          ┆        ┆          ┆         ┆     ┆            ┆ C          ┆            ┆            │
│ 3        ┆ null   ┆ Python   ┆ 10.47   ┆ ... ┆ change     ┆ Dart       ┆ 0.77       ┆ 0.13       │
│ 4        ┆ null   ┆ C++      ┆ 7.11    ┆ ... ┆ change     ┆ C          ┆ 15.95      ┆ 0.74       │
│ 4        ┆ null   ┆ C++      ┆ 7.11    ┆ ... ┆ change     ┆ Java       ┆ 13.48      ┆ -3.18      │
│ 4        ┆ null   ┆ C++      ┆ 7.11    ┆ ... ┆ null       ┆ Python     ┆ 10.47      ┆ 0.59       │
│ 4        ┆ null   ┆ C++      ┆ 7.11    ┆ ... ┆ null       ┆ C++        ┆ 7.11       ┆ 1.48       │
│ 4        ┆ null   ┆ C++      ┆ 7.11    ┆ ... ┆ null       ┆ C#         ┆ 4.58       ┆ 1.18       │
│ ...      ┆ ...    ┆ ...      ┆ ...     ┆ ... ┆ ...        ┆ ...        ┆ ...        ┆ ...        │
│ 16       ┆ change ┆ Swift    ┆ 1.38    ┆ ... ┆ change     ┆ MATLAB     ┆ 1.1        ┆ 0.04       │
│ 16       ┆ change ┆ Swift    ┆ 1.38    ┆ ... ┆ change     ┆ Groovy     ┆ 0.99       ┆ -0.52      │
│ 16       ┆ change ┆ Swift    ┆ 1.38    ┆ ... ┆ change     ┆ Rust       ┆ 0.92       ┆ 0.55       │
│ 16       ┆ change ┆ Swift    ┆ 1.38    ┆ ... ┆ change     ┆ Objective- ┆ 0.85       ┆ -0.99      │
│          ┆        ┆          ┆         ┆     ┆            ┆ C          ┆            ┆            │
│ 16       ┆ change ┆ Swift    ┆ 1.38    ┆ ... ┆ change     ┆ Dart       ┆ 0.77       ┆ 0.13       │
│ 20       ┆ change ┆ Perl     ┆ 1.3     ┆ ... ┆ change     ┆ C          ┆ 15.95      ┆ 0.74       │
│ 20       ┆ change ┆ Perl     ┆ 1.3     ┆ ... ┆ change     ┆ Java       ┆ 13.48      ┆ -3.18      │
│ 20       ┆ change ┆ Perl     ┆ 1.3     ┆ ... ┆ null       ┆ Python     ┆ 10.47      ┆ 0.59       │
│ 20       ┆ change ┆ Perl     ┆ 1.3     ┆ ... ┆ null       ┆ C++        ┆ 7.11       ┆ 1.48       │
│ 20       ┆ change ┆ Perl     ┆ 1.3     ┆ ... ┆ null       ┆ C#         ┆ 4.58       ┆ 1.18       │
│ 20       ┆ change ┆ Perl     ┆ 1.3     ┆ ... ┆ null       ┆ Visual     ┆ 4.12       ┆ 0.83       │
│          ┆        ┆          ┆         ┆     ┆            ┆ Basic      ┆            ┆            │
│ 20       ┆ change ┆ Perl     ┆ 1.3     ┆ ... ┆ null       ┆ JavaScript ┆ 2.54       ┆ 0.41       │
│ 20       ┆ change ┆ Perl     ┆ 1.3     ┆ ... ┆ change     ┆ PHP        ┆ 2.49       ┆ 0.62       │
│ 20       ┆ change ┆ Perl     ┆ 1.3     ┆ ... ┆ change     ┆ R          ┆ 2.37       ┆ 1.33       │
│ 20       ┆ change ┆ Perl     ┆ 1.3     ┆ ... ┆ change     ┆ SQL        ┆ 1.76       ┆ -0.19      │
│ 20       ┆ change ┆ Perl     ┆ 1.3     ┆ ... ┆ change     ┆ MATLAB     ┆ 1.1        ┆ 0.04       │
│ 20       ┆ change ┆ Perl     ┆ 1.3     ┆ ... ┆ change     ┆ Groovy     ┆ 0.99       ┆ -0.52      │
│ 20       ┆ change ┆ Perl     ┆ 1.3     ┆ ... ┆ change     ┆ Rust       ┆ 0.92       ┆ 0.55       │
│ 20       ┆ change ┆ Perl     ┆ 1.3     ┆ ... ┆ change     ┆ Objective- ┆ 0.85       ┆ -0.99      │
│          ┆        ┆          ┆         ┆     ┆            ┆ C          ┆            ┆            │
│ 20       ┆ change ┆ Perl     ┆ 1.3     ┆ ... ┆ change     ┆ Dart       ┆ 0.77       ┆ 0.13       │
│ 12       ┆ change ┆ Assembly ┆ 1.3     ┆ ... ┆ change     ┆ C          ┆ 15.95      ┆ 0.74       │
│          ┆        ┆ language ┆         ┆     ┆            ┆            ┆            ┆            │
│ 12       ┆ change ┆ Assembly ┆ 1.3     ┆ ... ┆ change     ┆ Java       ┆ 13.48      ┆ -3.18      │
│          ┆        ┆ language ┆         ┆     ┆            ┆            ┆            ┆            │
│ 12       ┆ change ┆ Assembly ┆ 1.3     ┆ ... ┆ null       ┆ Python     ┆ 10.47      ┆ 0.59       │
│          ┆        ┆ language ┆         ┆     ┆            ┆            ┆            ┆            │
│ 12       ┆ change ┆ Assembly ┆ 1.3     ┆ ... ┆ null       ┆ C++        ┆ 7.11       ┆ 1.48       │
│          ┆        ┆ language ┆         ┆     ┆            ┆            ┆            ┆            │
│ 12       ┆ change ┆ Assembly ┆ 1.3     ┆ ... ┆ null       ┆ C#         ┆ 4.58       ┆ 1.18       │
│          ┆        ┆ language ┆         ┆     ┆            ┆            ┆            ┆            │
│ 12       ┆ change ┆ Assembly ┆ 1.3     ┆ ... ┆ null       ┆ Visual     ┆ 4.12       ┆ 0.83       │
│          ┆        ┆ language ┆         ┆     ┆            ┆ Basic      ┆            ┆            │
│ 12       ┆ change ┆ Assembly ┆ 1.3     ┆ ... ┆ null       ┆ JavaScript ┆ 2.54       ┆ 0.41       │
│          ┆        ┆ language ┆         ┆     ┆            ┆            ┆            ┆            │
│ 12       ┆ change ┆ Assembly ┆ 1.3     ┆ ... ┆ change     ┆ PHP        ┆ 2.49       ┆ 0.62       │
│          ┆        ┆ language ┆         ┆     ┆            ┆            ┆            ┆            │
│ 12       ┆ change ┆ Assembly ┆ 1.3     ┆ ... ┆ change     ┆ R          ┆ 2.37       ┆ 1.33       │
│          ┆        ┆ language ┆         ┆     ┆            ┆            ┆            ┆            │
│ 12       ┆ change ┆ Assembly ┆ 1.3     ┆ ... ┆ change     ┆ SQL        ┆ 1.76       ┆ -0.19      │
│          ┆        ┆ language ┆         ┆     ┆            ┆            ┆            ┆            │
│ 12       ┆ change ┆ Assembly ┆ 1.3     ┆ ... ┆ change     ┆ MATLAB     ┆ 1.1        ┆ 0.04       │
│          ┆        ┆ language ┆         ┆     ┆            ┆            ┆            ┆            │
│ 12       ┆ change ┆ Assembly ┆ 1.3     ┆ ... ┆ change     ┆ Groovy     ┆ 0.99       ┆ -0.52      │
│          ┆        ┆ language ┆         ┆     ┆            ┆            ┆            ┆            │
│ 12       ┆ change ┆ Assembly ┆ 1.3     ┆ ... ┆ change     ┆ Rust       ┆ 0.92       ┆ 0.55       │
│          ┆        ┆ language ┆         ┆     ┆            ┆            ┆            ┆            │
│ 12       ┆ change ┆ Assembly ┆ 1.3     ┆ ... ┆ change     ┆ Objective- ┆ 0.85       ┆ -0.99      │
│          ┆        ┆ language ┆         ┆     ┆            ┆ C          ┆            ┆            │
│ 12       ┆ change ┆ Assembly ┆ 1.3     ┆ ... ┆ change     ┆ Dart       ┆ 0.77       ┆ 0.13       │
│          ┆        ┆ language ┆         ┆     ┆            ┆            ┆            ┆            │
│ 15       ┆ null   ┆ Ruby     ┆ 1.24    ┆ ... ┆ change     ┆ C          ┆ 15.95      ┆ 0.74       │
│ 15       ┆ null   ┆ Ruby     ┆ 1.24    ┆ ... ┆ change     ┆ Java       ┆ 13.48      ┆ -3.18      │
│ 15       ┆ null   ┆ Ruby     ┆ 1.24    ┆ ... ┆ null       ┆ Python     ┆ 10.47      ┆ 0.59       │
│ 15       ┆ null   ┆ Ruby     ┆ 1.24    ┆ ... ┆ null       ┆ C++        ┆ 7.11       ┆ 1.48       │
│ 15       ┆ null   ┆ Ruby     ┆ 1.24    ┆ ... ┆ null       ┆ C#         ┆ 4.58       ┆ 1.18       │
│ 15       ┆ null   ┆ Ruby     ┆ 1.24    ┆ ... ┆ null       ┆ Visual     ┆ 4.12       ┆ 0.83       │
│          ┆        ┆          ┆         ┆     ┆            ┆ Basic      ┆            ┆            │
│ 15       ┆ null   ┆ Ruby     ┆ 1.24    ┆ ... ┆ null       ┆ JavaScript ┆ 2.54       ┆ 0.41       │
│ 15       ┆ null   ┆ Ruby     ┆ 1.24    ┆ ... ┆ change     ┆ PHP        ┆ 2.49       ┆ 0.62       │
│ 15       ┆ null   ┆ Ruby     ┆ 1.24    ┆ ... ┆ change     ┆ R          ┆ 2.37       ┆ 1.33       │
│ 15       ┆ null   ┆ Ruby     ┆ 1.24    ┆ ... ┆ change     ┆ SQL        ┆ 1.76       ┆ -0.19      │
│ 15       ┆ null   ┆ Ruby     ┆ 1.24    ┆ ... ┆ change     ┆ MATLAB     ┆ 1.1        ┆ 0.04       │
│ 15       ┆ null   ┆ Ruby     ┆ 1.24    ┆ ... ┆ change     ┆ Groovy     ┆ 0.99       ┆ -0.52      │
│ 15       ┆ null   ┆ Ruby     ┆ 1.24    ┆ ... ┆ change     ┆ Rust       ┆ 0.92       ┆ 0.55       │
│ 15       ┆ null   ┆ Ruby     ┆ 1.24    ┆ ... ┆ change     ┆ Objective- ┆ 0.85       ┆ -0.99      │
│          ┆        ┆          ┆         ┆     ┆            ┆ C          ┆            ┆            │
│ 15       ┆ null   ┆ Ruby     ┆ 1.24    ┆ ... ┆ change     ┆ Dart       ┆ 0.77       ┆ 0.13       │
└──────────┴────────┴──────────┴─────────┴─────┴────────────┴────────────┴────────────┴────────────┘

16. Anti join

Posledním typem operace join, s níž se v dnešním článku alespoň ve stručnosti seznámíme, je takzvaný „anti join“. Tato operace opět porovná obsahy dvou (či většího množství) datových rámců, přičemž obsah zvoleného sloupce vystupuje v roli klíčů. Anti join vytvoří nový datový rámec obsahující ty záznamy, které jsou nalezeny v prvním vstupním datovém rámci, ale nikoli v ostatních rámcích. Touto operací tedy můžeme získat ty záznamy, které jsou odstraněny operací inner join, tedy klasickým vnitřním spojením.

17. „Levý“ anti join

V dnešním předposledním demonstračním příkladu je ukázán způsob realizace operace „levého“ anti joinu, tj. operace, která vrátí datový rámec s těmi záznamy, které jsou obsaženy pouze v levém zdrojovém rámci, ale nikoli v rámci pravém. Záznamy jsou přitom spojeny přes obsah sloupce Language, který zde vystupuje v roli primárního klíče:

#!/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
df1 = polars.read_csv("tiobeA.tsv", sep="\t")
df2 = polars.read_csv("tiobeB.tsv", sep="\t")
 
# datové rámce zobrazíme
print(df1)
print()
print(df2)
print()
 
# spojení obou datových rámců
merged = df1.join(df2, on="Language", how="anti")
 
# výpis výsledku
print(merged)

Výsledný datový rámec obsahuje pouze pět záznamů. Konkrétně se jedná o záznamy z prvního zdrojového datového rámce, které nejsou obsaženy v datovém rámci druhém:

shape: (5, 5)
┌──────────┬────────┬───────────────────┬─────────┬─────────┐
│ Sep 2019 ┆ Change ┆ Language          ┆ Ratings ┆ Changep │
│ ---      ┆ ---    ┆ ---               ┆ ---     ┆ ---     │
│ i64      ┆ str    ┆ str               ┆ f64     ┆ f64     │
╞══════════╪════════╪═══════════════════╪═════════╪═════════╡
│ 14       ┆ change ┆ Go                ┆ 1.46    ┆ 0.24    │
│ 16       ┆ change ┆ Swift             ┆ 1.38    ┆ 0.28    │
│ 20       ┆ change ┆ Perl              ┆ 1.3     ┆ 0.26    │
│ 12       ┆ change ┆ Assembly language ┆ 1.3     ┆ -0.08   │
│ 15       ┆ null   ┆ Ruby              ┆ 1.24    ┆ 0.03    │
└──────────┴────────┴───────────────────┴─────────┴─────────┘

18. „Pravý“ anti join

„Pravý“ anti join resp. anti join zprava lze realizovat snadno – pouze prohodíme první rámec s rámcem druhým při volání metody join. Tj. namísto:

merged = df1.join(df2, on="Language", how="anti")

použijeme volání:

merged = df2.join(df1, on="Language", how="anti")
Poznámka: změna spočívá v prohození df2 za df1 a naopak.

Celý skript provádějící tuto operaci vypadá následovně:

bitcoin_skoleni

#!/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
df1 = polars.read_csv("tiobeA.tsv", sep="\t")
df2 = polars.read_csv("tiobeB.tsv", sep="\t")
 
# datové rámce zobrazíme
print(df1)
print()
print(df2)
print()
 
# spojení obou datových rámců
merged = df2.join(df1, on="Language", how="anti")
 
# výpis výsledku
print(merged)

Výsledný datový rámec v tomto případě opět obsahuje pouze pět záznamů. Konkrétně se jedná o záznamy ze druhého zdrojového datového rámce, které nejsou obsaženy v datovém rámci prvním:

shape: (5, 5)
┌──────────┬────────┬─────────────┬─────────┬─────────┐
│ Sep 2020 ┆ Change ┆ Language    ┆ Ratings ┆ Changep │
│ ---      ┆ ---    ┆ ---         ┆ ---     ┆ ---     │
│ i64      ┆ str    ┆ str         ┆ f64     ┆ f64     │
╞══════════╪════════╪═════════════╪═════════╪═════════╡
│ 16       ┆ change ┆ MATLAB      ┆ 1.1     ┆ 0.04    │
│ 17       ┆ change ┆ Groovy      ┆ 0.99    ┆ -0.52   │
│ 18       ┆ change ┆ Rust        ┆ 0.92    ┆ 0.55    │
│ 19       ┆ change ┆ Objective-C ┆ 0.85    ┆ -0.99   │
│ 20       ┆ change ┆ Dart        ┆ 0.77    ┆ 0.13    │
└──────────┴────────┴─────────────┴─────────┴─────────┘

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
       
42 lazy_frame01_scan_csv.py líné načtení dat ze souboru typu CSV https://github.com/tisnik/most-popular-python-libs/blob/master/polars/la­zy_frame01_scan_csv.py
43 lazy_frame02_read_csv_and_convert.py načtení dat ze souboru typu CSV do datového rámce a konverze na líný datový rámec https://github.com/tisnik/most-popular-python-libs/blob/master/polars/la­zy_frame02_read_csv_and_con­vert.py
44 lazy_frame03_collect_to_df.py převod líného datového rámce na běžný datový rámec https://github.com/tisnik/most-popular-python-libs/blob/master/polars/la­zy_frame03_collect_to_df.py
45 lazy_frame04_lazy_sort.py operace sort aplikovaná líně https://github.com/tisnik/most-popular-python-libs/blob/master/polars/la­zy_frame04_lazy_sort.py
46 lazy_frame05_lazy_sort_reverse.py dvojice operací sort + reverse, taktéž aplikovaných líně https://github.com/tisnik/most-popular-python-libs/blob/master/polars/la­zy_frame05_lazy_sort_rever­se.py
47 lazy_frame06_describe_plan.py zobrazení informací o plánovaných operacích https://github.com/tisnik/most-popular-python-libs/blob/master/polars/la­zy_frame06_describe_plan.py
48 lazy_frame07_fetch.py přečtení výseku dat z líného datového rámce https://github.com/tisnik/most-popular-python-libs/blob/master/polars/la­zy_frame07_fetch.py
49 lazy_frame08_group_by.py operace groupby následovaná agregací pro líný datový rámec https://github.com/tisnik/most-popular-python-libs/blob/master/polars/la­zy_frame08_group_by.py
50 lazy_frame09_group_by_fetch2.py zjištění, jak vlastně přesně pracuje operace fetch https://github.com/tisnik/most-popular-python-libs/blob/master/polars/la­zy_frame09_group_by_fetch.py
51 lazy_frame10_group_by_len_sor­t_reverse_head.py „pipeline“ operací aplikovaných na líný datový rámec https://github.com/tisnik/most-popular-python-libs/blob/master/polars/la­zy_frame10_group_by_len_sor­t_reverse_head.py
52 lazy_frame11_branching.py rozvětvení plánů https://github.com/tisnik/most-popular-python-libs/blob/master/polars/la­zy_frame11_branching.py
53 lazy_frame12_visualization.py vizualizace plánů https://github.com/tisnik/most-popular-python-libs/blob/master/polars/la­zy_frame12_visualization.py
54 lazy_frame13_head_tail.py kombinace operací head a tail https://github.com/tisnik/most-popular-python-libs/blob/master/polars/la­zy_frame13_head_tail.py
55 lazy_frame14_head_tail_vi­sualization.py kombinace operací head a tail, vizualizace výsledného plánu https://github.com/tisnik/most-popular-python-libs/blob/master/polars/la­zy_frame14_head_tail_visu­alization.py
       
56 data_frame_concat.py vertikální spojení dvou datových rámců https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame_concat.py
57 data_frame_concat_vertically.py vertikální spojení dvou datových rámců https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame_concat_vertically­.py
58 data_frame_concat_horizontally1.py nekorektní horizontální spojení dvou datových rámců https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame_concat_horizonta­lly1.py
59 data_frame_concat_horizontally2.py korektní horizontální spojení dvou datových rámců https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame_concat_horizonta­lly2.py
60 data_frame_join01_inner_join.py inner join (vnitřní spojení) dvou datových rámců https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame_join01_inner_join­.py
61 data_frame_join02_left_join.py left join (vnější spojení „zleva“) dvou datových rámců https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame_join02_left_join­.py
62 data_frame_join03_outer_join.py outer join (vnější spojení) dvou datových rámců https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame_join03_outer_join­.py
63 data_frame_join04_cross_join_A.py křížové spojení (kartézský součin) dvou datových rámců https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame_join04_cross_join_A­.py
64 data_frame_join04_cross_join_B.py křížové spojení (kartézský součin) dvou datových rámců https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame_join04_cross_join_B­.py
65 data_frame_join05_anti_join_A.py „levý“ anti join https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame_join05_anti_join_A­.py
66 data_frame_join06_anti_join_B.py „pravý“ anti join https://github.com/tisnik/most-popular-python-libs/blob/master/polars/da­ta_frame_join06_anti_join_B­.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/
  28. Lazy evaluation
    https://en.wikipedia.org/wi­ki/Lazy_evaluation

Autor článku

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