diff --git a/course.yml b/course.yml
index 0b9a039..e3dea16 100644
--- a/course.yml
+++ b/course.yml
@@ -45,6 +45,7 @@ plan:
slug: eda4
date: 2023-10-09
materials:
+ - lesson: pydata/pandas_joins
- lesson: pydata/pandas_correlations
- title: "Svátky klidu a konce kurzu"
diff --git a/lessons/pydata/pandas_correlations/index.ipynb b/lessons/pydata/pandas_correlations/index.ipynb
index aabdc5e..7151d89 100644
--- a/lessons/pydata/pandas_correlations/index.ipynb
+++ b/lessons/pydata/pandas_correlations/index.ipynb
@@ -4,6100 +4,36 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "# Pandas - spojování tabulek a vztahy mezi více proměnnými\n",
- "\n",
- "Tato lekce se nese ve znamení mnohosti a propojování - naučíš se:\n",
- "\n",
- "- pracovat s více tabulkami najednou\n",
- "- nacházet spojitosti mezi dvěma (a více) proměnnými\n",
- "\n",
- "Při tom společně projdeme (ne poprvé a ne naposledy) čištění reálných datových sad."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [],
- "source": [
- "# Importy jako obvykle\n",
- "import pandas as pd\n",
- "import matplotlib.pyplot as plt\n",
- "import seaborn as sns\n",
- "\n",
- "%matplotlib inline"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "toc-hr-collapsed": false
- },
- "source": [
- "## Spojování tabulek\n",
- "\n",
- "V lekci, kde jsme zpracovávali data o počasí, jsme ti ukázali, že je pomocí funkce `concat` možné slepit dohromady několik objektů `DataFrame` či `Series`, pokud mají \"kompatibilní\" index. Nyní se na problematiku podíváme trochu blíže a ukážeme si, jak spojovat tabulky na základě různých sloupců, a co dělat, když řádky z jedné tabulky nepasují přesně na tabulku druhou.\n",
- "\n",
- "Obecně pro spojování `pandas` nabízí čtyři funkce / metody, z nichž každá má svoje typické využití (možnostmi se ovšem překrývají):\n",
- "\n",
- "- [`concat`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.concat.html) je univerzální funkce pro slepování dvou či více tabulek / sloupců - pod sebe, vedle sebe, s přihlédnutím k indexům i bez něj. \n",
- "- [`append`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.append.html) (metoda) je jednodušší alternativou `concat`, pokud jen chceš do nějaké tabulky přidat pár řádků.\n",
- "- [`merge`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.merge.html) je univerzální funkce pro spojování tabulek na základě vazby mezi indexy nebo sloupci.\n",
- "- [`join`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.join.html) (metoda) zjednodušuje práci, když chceš spojit dvě tabulky na základě indexu.\n",
- "\n",
- "Detailní rozbor toho, co která umí, najdeš v [dokumentaci](https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html). My si je také postupně ukážeme."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Jednoduché skládání"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Pod sebou\n",
- "\n",
- "To je asi ten nejjednodušší případ - máme dva objekty `Series` nebo dva kusy tabulky se stejnými sloupci a chceme je spojit pod sebou. Na to se používá funkce [`concat`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.concat.html):"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [],
- "source": [
- "a = pd.Series([\"jedna\", \"dvě\", \"tři\"])\n",
- "b = pd.Series([\"čtyři\", \"pět\", \"šest\"])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0 jedna\n",
- "1 dvě\n",
- "2 tři\n",
- "0 čtyři\n",
- "1 pět\n",
- "2 šest\n",
- "dtype: object"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "pd.concat([a, b])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "💡 Vidíš, že se index opakuje? Vytvořili jsme dvě `Series`, u kterých jsme index neřešili. Jenže `pandas` na rozdíl od nás ano, a tak poslušně oba indexy spojil, i za cenu duplicitních hodnot. Za cenu použití dodatečného argumentu `ignore_index=True` se tomu lze vyhnout, což si ukážeme na příklady spojování dvou tabulek o stejných sloupcích:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0 jedna\n",
- "1 dvě\n",
- "2 tři\n",
- "3 jedna\n",
- "4 dvě\n",
- "5 tři\n",
- "6 jedna\n",
- "7 dvě\n",
- "8 tři\n",
- "9 jedna\n",
- "10 dvě\n",
- "11 tři\n",
- "12 jedna\n",
- "13 dvě\n",
- "14 tři\n",
- "dtype: object"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "pd.concat([a, a, a, a, a], ignore_index=True)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### Vedle sebe\n",
- "\n",
- "Toto asi použijete zřídka, ale když chceme \"lepit\" doprava (třeba deset `Series`), stačí přidat nám dobře známý argument `axis`:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
\n",
- "\n",
- "
\n",
- " \n",
- "
\n",
- "
\n",
- "
0
\n",
- "
1
\n",
- "
2
\n",
- "
3
\n",
- "
4
\n",
- "
\n",
- " \n",
- " \n",
- "
\n",
- "
0
\n",
- "
jedna
\n",
- "
jedna
\n",
- "
jedna
\n",
- "
jedna
\n",
- "
jedna
\n",
- "
\n",
- "
\n",
- "
1
\n",
- "
dvě
\n",
- "
dvě
\n",
- "
dvě
\n",
- "
dvě
\n",
- "
dvě
\n",
- "
\n",
- "
\n",
- "
2
\n",
- "
tři
\n",
- "
tři
\n",
- "
tři
\n",
- "
tři
\n",
- "
tři
\n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " 0 1 2 3 4\n",
- "0 jedna jedna jedna jedna jedna\n",
- "1 dvě dvě dvě dvě dvě\n",
- "2 tři tři tři tři tři"
- ]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "pd.concat([a, a, a, a, a], axis=\"columns\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**Příklad:** Jak co nejrychleji \"nakreslit prázdnou šachovnici\" (obě slova jsou v uvozovkách)?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
\n",
- "\n",
- "
\n",
- " \n",
- "
\n",
- "
\n",
- "
A
\n",
- "
B
\n",
- "
C
\n",
- "
D
\n",
- "
E
\n",
- "
F
\n",
- "
G
\n",
- "
H
\n",
- "
\n",
- " \n",
- " \n",
- "
\n",
- "
8
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
\n",
- "
\n",
- "
7
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
\n",
- "
\n",
- "
6
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
\n",
- "
\n",
- "
5
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
\n",
- "
\n",
- "
4
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
\n",
- "
\n",
- "
3
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
\n",
- "
\n",
- "
2
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
\n",
- "
\n",
- "
1
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
⬛
\n",
- "
⬜
\n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " A B C D E F G H\n",
- "8 ⬜ ⬛ ⬜ ⬛ ⬜ ⬛ ⬜ ⬛\n",
- "7 ⬛ ⬜ ⬛ ⬜ ⬛ ⬜ ⬛ ⬜\n",
- "6 ⬜ ⬛ ⬜ ⬛ ⬜ ⬛ ⬜ ⬛\n",
- "5 ⬛ ⬜ ⬛ ⬜ ⬛ ⬜ ⬛ ⬜\n",
- "4 ⬜ ⬛ ⬜ ⬛ ⬜ ⬛ ⬜ ⬛\n",
- "3 ⬛ ⬜ ⬛ ⬜ ⬛ ⬜ ⬛ ⬜\n",
- "2 ⬜ ⬛ ⬜ ⬛ ⬜ ⬛ ⬜ ⬛\n",
- "1 ⬛ ⬜ ⬛ ⬜ ⬛ ⬜ ⬛ ⬜"
- ]
- },
- "execution_count": 6,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "sachy = pd.concat(\n",
- " [\n",
- " pd.concat( \n",
- " [pd.DataFrame([[\"⬜\", \"⬛\"], [\"⬛\", \"⬜\"]])] * 4,\n",
- " axis=1)\n",
- " ] * 4\n",
- ")\n",
- "sachy.index = list(range(8, 0, -1))\n",
- "sachy.columns = list(\"ABCDEFGH\")\n",
- "sachy"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### Spojování různorodých tabulek"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "🎦 Pro spojování heterogenních dat (v datové hantýrce \"joinování\") sáhneme po trochu komplexnějších filmových datech..."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Máme staženo několik souborů, načteme si je (zatím hrubě, \"raw\") - s přihlédnutím k tomu, že první dva nejsou v pravém slova smyslu \"comma-separated\", ale používají k oddělení hodnot tabulátor (tady pomůže argument `sep`). Také zohledníme, že v nich řetězec `\"\\N\"` představuje chybějící hodnoty (pomůže argument `na_values`):"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [],
- "source": [
- "imdb_titles_raw = pd.read_csv(\"title.basics.tsv.gz\", sep=\"\\t\", na_values=\"\\\\N\")\n",
- "imdb_ratings_raw = pd.read_csv(\"title.ratings.tsv.gz\", sep=\"\\t\", na_values=\"\\\\N\")\n",
- "boxoffice_raw = pd.read_csv(\"boxoffice_march_2019.csv.gz\")\n",
- "rotten_tomatoes_raw = pd.read_csv(\"rotten_tomatoes_top_movies_2019-01-15.csv\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Co který soubor obsahuje? \n",
- "\n",
- "- První dva soubory obsahují volně dostupná (byť \"jen\" pro nekomerční použití) data o filmech z IMDb (Internet Movie Database). My jsme si zvolili obecné informace a uživatelská (číselná) hodnocení. Detailní popis souborů, stejně jako odkazy na další soubory, najdeš na https://www.imdb.com/interfaces/. Z důvodů paměťové náročnosti jsme datovou sadu ořezali o epizody seriálů, protože nás nebudou zajímat a s trochu štěstí přežijeme i na počítačích s menší operační pamětí.\n",
- "\n",
- "- Soubor `boxoffice_march_2019.csv.gz` obsahuje informace o výdělcích jednotlivých filmů. Pochází z ukázkového datasetu pro soutěž \"TMDB Box Office Prediction\" na serveru Kaggle: https://www.kaggle.com/c/tmdb-box-office-prediction/data\n",
- "\n",
- "- Soubor `rotten_tomatoes_top_movies_2019-01-15.csv` obsahuje procentuální hodnocení filmů ze serveru Rotten Tomatoes, které se počítá jako podíl pozitivních hodnoceních od filmových kritiku (je to tedy jiný princip než na IMDb). Staženo z: https://data.world/prasert/rotten-tomatoes-top-movies-by-genre\n",
- "\n",
- "Pojďme se podívat na nedostatky těchto souborů a postupně je skládat dohromady. Zajímalo by nás (a snad i tebe!), jak souvisí hodnocení s komerční úspěšností filmu, jak se liší hodnocení rotten tomatoes od těch na IMDb."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
\n",
- "\n",
- "
\n",
- " \n",
- "
\n",
- "
\n",
- "
tconst
\n",
- "
titleType
\n",
- "
primaryTitle
\n",
- "
originalTitle
\n",
- "
isAdult
\n",
- "
startYear
\n",
- "
endYear
\n",
- "
runtimeMinutes
\n",
- "
genres
\n",
- "
\n",
- " \n",
- " \n",
- "
\n",
- "
0
\n",
- "
tt0000001
\n",
- "
short
\n",
- "
Carmencita
\n",
- "
Carmencita
\n",
- "
0
\n",
- "
1894.0
\n",
- "
NaN
\n",
- "
1.0
\n",
- "
Documentary,Short
\n",
- "
\n",
- "
\n",
- "
1
\n",
- "
tt0000002
\n",
- "
short
\n",
- "
Le clown et ses chiens
\n",
- "
Le clown et ses chiens
\n",
- "
0
\n",
- "
1892.0
\n",
- "
NaN
\n",
- "
5.0
\n",
- "
Animation,Short
\n",
- "
\n",
- "
\n",
- "
2
\n",
- "
tt0000003
\n",
- "
short
\n",
- "
Pauvre Pierrot
\n",
- "
Pauvre Pierrot
\n",
- "
0
\n",
- "
1892.0
\n",
- "
NaN
\n",
- "
4.0
\n",
- "
Animation,Comedy,Romance
\n",
- "
\n",
- "
\n",
- "
3
\n",
- "
tt0000004
\n",
- "
short
\n",
- "
Un bon bock
\n",
- "
Un bon bock
\n",
- "
0
\n",
- "
1892.0
\n",
- "
NaN
\n",
- "
NaN
\n",
- "
Animation,Short
\n",
- "
\n",
- "
\n",
- "
4
\n",
- "
tt0000005
\n",
- "
short
\n",
- "
Blacksmith Scene
\n",
- "
Blacksmith Scene
\n",
- "
0
\n",
- "
1893.0
\n",
- "
NaN
\n",
- "
1.0
\n",
- "
Comedy,Short
\n",
- "
\n",
- "
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
\n",
- "
\n",
- "
1783511
\n",
- "
tt9916734
\n",
- "
video
\n",
- "
Manca: Peleo
\n",
- "
Manca: Peleo
\n",
- "
0
\n",
- "
2018.0
\n",
- "
NaN
\n",
- "
NaN
\n",
- "
Music,Short
\n",
- "
\n",
- "
\n",
- "
1783512
\n",
- "
tt9916754
\n",
- "
movie
\n",
- "
Chico Albuquerque - Revelações
\n",
- "
Chico Albuquerque - Revelações
\n",
- "
0
\n",
- "
2013.0
\n",
- "
NaN
\n",
- "
NaN
\n",
- "
Documentary
\n",
- "
\n",
- "
\n",
- "
1783513
\n",
- "
tt9916756
\n",
- "
short
\n",
- "
Pretty Pretty Black Girl
\n",
- "
Pretty Pretty Black Girl
\n",
- "
0
\n",
- "
2019.0
\n",
- "
NaN
\n",
- "
NaN
\n",
- "
Short
\n",
- "
\n",
- "
\n",
- "
1783514
\n",
- "
tt9916764
\n",
- "
short
\n",
- "
38
\n",
- "
38
\n",
- "
0
\n",
- "
2018.0
\n",
- "
NaN
\n",
- "
NaN
\n",
- "
Short
\n",
- "
\n",
- "
\n",
- "
1783515
\n",
- "
tt9916856
\n",
- "
short
\n",
- "
The Wind
\n",
- "
The Wind
\n",
- "
0
\n",
- "
2015.0
\n",
- "
NaN
\n",
- "
27.0
\n",
- "
Short
\n",
- "
\n",
- " \n",
- "
\n",
- "
1783516 rows × 9 columns
\n",
- "
"
- ],
- "text/plain": [
- " tconst titleType primaryTitle \\\n",
- "0 tt0000001 short Carmencita \n",
- "1 tt0000002 short Le clown et ses chiens \n",
- "2 tt0000003 short Pauvre Pierrot \n",
- "3 tt0000004 short Un bon bock \n",
- "4 tt0000005 short Blacksmith Scene \n",
- "... ... ... ... \n",
- "1783511 tt9916734 video Manca: Peleo \n",
- "1783512 tt9916754 movie Chico Albuquerque - Revelações \n",
- "1783513 tt9916756 short Pretty Pretty Black Girl \n",
- "1783514 tt9916764 short 38 \n",
- "1783515 tt9916856 short The Wind \n",
- "\n",
- " originalTitle isAdult startYear endYear \\\n",
- "0 Carmencita 0 1894.0 NaN \n",
- "1 Le clown et ses chiens 0 1892.0 NaN \n",
- "2 Pauvre Pierrot 0 1892.0 NaN \n",
- "3 Un bon bock 0 1892.0 NaN \n",
- "4 Blacksmith Scene 0 1893.0 NaN \n",
- "... ... ... ... ... \n",
- "1783511 Manca: Peleo 0 2018.0 NaN \n",
- "1783512 Chico Albuquerque - Revelações 0 2013.0 NaN \n",
- "1783513 Pretty Pretty Black Girl 0 2019.0 NaN \n",
- "1783514 38 0 2018.0 NaN \n",
- "1783515 The Wind 0 2015.0 NaN \n",
- "\n",
- " runtimeMinutes genres \n",
- "0 1.0 Documentary,Short \n",
- "1 5.0 Animation,Short \n",
- "2 4.0 Animation,Comedy,Romance \n",
- "3 NaN Animation,Short \n",
- "4 1.0 Comedy,Short \n",
- "... ... ... \n",
- "1783511 NaN Music,Short \n",
- "1783512 NaN Documentary \n",
- "1783513 NaN Short \n",
- "1783514 NaN Short \n",
- "1783515 27.0 Short \n",
- "\n",
- "[1783516 rows x 9 columns]"
- ]
- },
- "execution_count": 8,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "imdb_titles_raw"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "648.8971881866455"
- ]
- },
- "execution_count": 9,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# Kolik tabulka zabírá megabajtů paměti? (1 MB = 2**20 bajtů)\n",
- "imdb_titles_raw.memory_usage(deep=True).sum() / 2**20 "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Jistě budeme chtít převést sloupce na správné typy. Jaké jsou v základu?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "tconst object\n",
- "titleType object\n",
- "primaryTitle object\n",
- "originalTitle object\n",
- "isAdult int64\n",
- "startYear float64\n",
- "endYear float64\n",
- "runtimeMinutes float64\n",
- "genres object\n",
- "dtype: object"
- ]
- },
- "execution_count": 10,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "imdb_titles_raw.dtypes"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Na co budeme převádět?\n",
- "\n",
- "- `tconst` je řetězec, který posléze použijeme jako index, protože představuje unikátní identifikátor v databázi IMDb.\n",
- "- `titleType`:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "titleType\n",
- "short 676930\n",
- "movie 514654\n",
- "video 227582\n",
- "tvSeries 162781\n",
- "tvMovie 126507\n",
- "tvMiniSeries 25574\n",
- "videoGame 23310\n",
- "tvSpecial 17007\n",
- "tvShort 9171\n",
- "Name: count, dtype: int64"
- ]
- },
- "execution_count": 11,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "imdb_titles_raw[\"titleType\"].value_counts()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Jen devět různých hodnot ve skoro 2 milionech řádků? To je ideální kandidát na převedení na typ `\"category\"`.\n",
- "\n",
- "- `primaryTitle` a `originalTitle` vypadají jako obyčejné řetězce (pokud možno anglický a pokud možno původní název)\n",
- "- `isAdult` určuje, zda se jedná o dílo pro dospělé. Tento sloupec bychom nejspíše měli převést na `bool`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "isAdult\n",
- "0 1692292\n",
- "1 91224\n",
- "Name: count, dtype: int64"
- ]
- },
- "execution_count": 12,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "imdb_titles_raw[\"isAdult\"].value_counts()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "- `startYear` a `endYear` obsahují roky, t.j. celá čísla, ovšem kvůli chybějícím hodnotám je pro ně zvolen typ `float64`. V `pandas` raději zvolíme tzv. \"nullable integer\", který se zapisuje s velkým \"I\". Když nevíš, jaký podtyp konkrétně, sáhni po `Int64`.\n",
- "- totéž platí pro `runtimeMinutes`."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "startYear 2115.0\n",
- "endYear 2027.0\n",
- "runtimeMinutes 125156.0\n",
- "dtype: float64"
- ]
- },
- "execution_count": 13,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "imdb_titles_raw[[\"startYear\", \"endYear\", \"runtimeMinutes\"]].max()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Mimochodem všimli jste si, že máme díla z budoucnosti (rok 2115)?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "startYear\n",
- "2020.0 340\n",
- "2021.0 36\n",
- "2022.0 14\n",
- "2023.0 1\n",
- "2024.0 2\n",
- "2025.0 1\n",
- "2115.0 1\n",
- "Name: count, dtype: int64"
- ]
- },
- "execution_count": 14,
- "metadata": {},
- "output_type": "execute_result"
- },
- {
- "data": {
- "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAGsCAYAAAAhYYazAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAqCElEQVR4nO3de1zVdZ7H8fcB5SApqCHghcR7FxXJC8OkTU4kKg83c2bXtUxjtFnLGpKspAuMNSOaydqumpPrJXe2vOya06RihprrxOaKUNl6N8MLoKZyFAuQ89s/fHjqBCocjhz4+no+Hufx6HzP9/c7n9/3ceS8+57v7/ezWZZlCQAAwBB+vi4AAADAmwg3AADAKIQbAABgFMINAAAwCuEGAAAYhXADAACMQrgBAABGIdwAAACjEG4AAIBRCDcAAMAoN3W42bZtm0aMGKF27drJZrNp7dq1td6HZVl644031L17d9ntdrVv315//OMfvV8sAACokSa+LsCXSktLFR0drd/85jcaNWqUR/tITk7WRx99pDfeeEO9evXSmTNndObMGS9XCgAAasrGjTMvs9lsev/99zVy5EhXW1lZmV566SW99957OnfunHr27KlZs2bpvvvukyTt2bNHvXv31u7du9WjRw/fFA4AANzc1D9LXc9TTz2lnJwcrVixQl988YX+/u//XkOHDtWBAwckSX/961/VuXNnffjhh+rUqZOioqI0ceJEZm4AAPAhws1VFBQUaOnSpVq9erUGDRqkLl26aOrUqRo4cKCWLl0qSTp8+LC++eYbrV69WsuXL9eyZcuUm5urX//61z6uHgCAm9dNvebmWr788ktVVlaqe/fubu1lZWW69dZbJUlOp1NlZWVavny5q9/ixYvVt29f7du3j5+qAADwAcLNVVy4cEH+/v7Kzc2Vv7+/22vNmzeXJLVt21ZNmjRxC0B33HGHpMszP4QbAADqH+HmKmJiYlRZWamTJ09q0KBB1fa55557dOnSJR06dEhdunSRJO3fv1+S1LFjx3qrFQAA/OCmPlvqwoULOnjwoKTLYSYzM1ODBw9W69atddttt2ns2LH629/+pjlz5igmJkanTp1Sdna2evfurcTERDmdTvXv31/NmzfX3Llz5XQ6NXnyZAUHB+ujjz7y8dEBAHBzuqnDzdatWzV48OAq7ePHj9eyZctUUVGhP/zh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",
- "text/plain": [
- "
"
- ],
- "text/plain": [
- " title \\\n",
- "tconst \n",
- "tt0000009 Miss Jerry \n",
- "tt0000147 The Corbett-Fitzsimmons Fight \n",
- "tt0000335 Soldiers of the Cross \n",
- "tt0000502 Bohemios \n",
- "tt0000574 The Story of the Kelly Gang \n",
- "... ... \n",
- "tt9916622 Rodolpho Teóphilo - O Legado de um Pioneiro \n",
- "tt9916680 De la ilusión al desconcierto: cine colombiano... \n",
- "tt9916706 Dankyavar Danka \n",
- "tt9916730 6 Gunn \n",
- "tt9916754 Chico Albuquerque - Revelações \n",
- "\n",
- " original_title is_adult year \\\n",
- "tconst \n",
- "tt0000009 Miss Jerry False 1894 \n",
- "tt0000147 The Corbett-Fitzsimmons Fight False 1897 \n",
- "tt0000335 Soldiers of the Cross False 1900 \n",
- "tt0000502 Bohemios False 1905 \n",
- "tt0000574 The Story of the Kelly Gang False 1906 \n",
- "... ... ... ... \n",
- "tt9916622 Rodolpho Teóphilo - O Legado de um Pioneiro False 2015 \n",
- "tt9916680 De la ilusión al desconcierto: cine colombiano... False 2007 \n",
- "tt9916706 Dankyavar Danka False 2013 \n",
- "tt9916730 6 Gunn False 2017 \n",
- "tt9916754 Chico Albuquerque - Revelações False 2013 \n",
- "\n",
- " length genres imdb_rating imdb_votes \n",
- "tconst \n",
- "tt0000009 45 Romance 5.5 77.0 \n",
- "tt0000147 20 Documentary,News,Sport 5.2 289.0 \n",
- "tt0000335 Biography,Drama 6.3 39.0 \n",
- "tt0000502 100 NaN NaN NaN \n",
- "tt0000574 70 Biography,Crime,Drama 6.2 505.0 \n",
- "... ... ... ... ... \n",
- "tt9916622 Documentary NaN NaN \n",
- "tt9916680 100 Documentary NaN NaN \n",
- "tt9916706 Comedy NaN NaN \n",
- "tt9916730 116 NaN NaN NaN \n",
- "tt9916754 Documentary NaN NaN \n",
- "\n",
- "[514654 rows x 8 columns]"
- ]
- },
- "execution_count": 23,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "movies.join(ratings)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "K tabulce se nenápadně přidaly dva sloupce z tabulky `ratings`, a to takovým způsobem, že se porovnaly hodnoty indexu (tedy `tconst`) a spárovaly se ty části řádku, kde se tento index shoduje.\n",
- "\n",
- "💡 Uvědom si (ačkoliv z volání funkcí v `pandas` to není úplně zřejmé), že se tady děje něco fundamentálně odlišného od \"nalepení doprava\" - tabulky tu nejsou chápány jako čtverečky, které jde skládat jako lego, nýbrž jako zdroj údajů o jednotlivých objektech, které je potřeba spojit sémanticky.\n",
- "\n",
- "Jak ale vidíš, tabulka obsahuje spoustu řádků, kde ve sloupcích s hodnocením chybí hodnoty (respektive nachází se `NaN`). To vychází ze způsobu, jakým metoda `join` ve výchozím nastavení \"joinuje\" - použije všechny řádky z levé tabulky bez ohledu na to, jestli jim odpovídá nějaký protějšek v tabulce pravé. Naštěstí lze pomocí argumentu `how` specifikovat i jiné způsoby spojování:\n",
- "\n",
- "- `left` (výchozí pro metodu `join`) - vezmou se všechny prvky z levé tabulky a jim odpovídající prvky z pravé tabulky (kde nejsou, doplní se `NaN`)\n",
- "- `right` - vezmou se všechny prvky z pravé tabulky a jim odpovídající prvky z levé tabulky (kde nejsou, doplní se `NaN`)\n",
- "- `inner` (výchozí pro funkci `merge`) - vezmou se jen ty prvky, které jsou v levé i pravé tabulce.\n",
- "- `outer` (výchozí pro funkci `concat`) - vezmou se všechny prvky, z levé i pravé tabulky, kde něco chybí, doplní se `NaN`.\n",
- "\n",
- "V podobě Vennově diagramu, kde kruhy představují množiny řádků v obou zdrojových tabulkách a modrou barvou jsou zvýrazněny řádky v tabulce cílové:\n",
- "\n",
- "![Typy joinů](static/joins.svg)\n",
- "\n",
- "*Obrázek adaptován z https://upload.wikimedia.org/wikipedia/commons/9/9d/SQL_Joins.svg (autor: Arbeck)*\n",
- "\n",
- "💡 Až budeme probírat databáze, tyto čtyři typu joinů se nám znovu vynoří.\n",
- "\n",
- "Následující výpis ukáže, kolik řádků bychom dostali při použití různých hodnot `how`:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 24,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "movies.join(ratings, how=\"left\"): 514654 řádků.\n",
- "movies.join(ratings, how=\"right\"): 923696 řádků.\n",
- "movies.join(ratings, how=\"inner\"): 232496 řádků.\n",
- "movies.join(ratings, how=\"outer\"): 1205854 řádků.\n"
- ]
- }
- ],
- "source": [
- "for how in [\"left\", \"right\", \"inner\", \"outer\"]:\n",
- " print(f\"movies.join(ratings, how=\\\"{how}\\\"):\", movies.join(ratings, how=how).shape[0], \"řádků.\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "A teď tedy ty tři alternativy:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 25,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
\n",
- "\n",
- "
\n",
- " \n",
- "
\n",
- "
\n",
- "
title
\n",
- "
original_title
\n",
- "
is_adult
\n",
- "
year
\n",
- "
length
\n",
- "
genres
\n",
- "
imdb_rating
\n",
- "
imdb_votes
\n",
- "
\n",
- "
\n",
- "
tconst
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- " \n",
- " \n",
- "
\n",
- "
tt0000009
\n",
- "
Miss Jerry
\n",
- "
Miss Jerry
\n",
- "
False
\n",
- "
1894
\n",
- "
45
\n",
- "
Romance
\n",
- "
5.5
\n",
- "
77
\n",
- "
\n",
- "
\n",
- "
tt0000147
\n",
- "
The Corbett-Fitzsimmons Fight
\n",
- "
The Corbett-Fitzsimmons Fight
\n",
- "
False
\n",
- "
1897
\n",
- "
20
\n",
- "
Documentary,News,Sport
\n",
- "
5.2
\n",
- "
289
\n",
- "
\n",
- "
\n",
- "
tt0000335
\n",
- "
Soldiers of the Cross
\n",
- "
Soldiers of the Cross
\n",
- "
False
\n",
- "
1900
\n",
- "
<NA>
\n",
- "
Biography,Drama
\n",
- "
6.3
\n",
- "
39
\n",
- "
\n",
- "
\n",
- "
tt0000574
\n",
- "
The Story of the Kelly Gang
\n",
- "
The Story of the Kelly Gang
\n",
- "
False
\n",
- "
1906
\n",
- "
70
\n",
- "
Biography,Crime,Drama
\n",
- "
6.2
\n",
- "
505
\n",
- "
\n",
- "
\n",
- "
tt0000615
\n",
- "
Robbery Under Arms
\n",
- "
Robbery Under Arms
\n",
- "
False
\n",
- "
1907
\n",
- "
<NA>
\n",
- "
Drama
\n",
- "
4.8
\n",
- "
14
\n",
- "
\n",
- "
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
\n",
- "
\n",
- "
tt9910930
\n",
- "
Jeg ser deg
\n",
- "
Jeg ser deg
\n",
- "
False
\n",
- "
2019
\n",
- "
75
\n",
- "
Crime,Documentary
\n",
- "
4.6
\n",
- "
5
\n",
- "
\n",
- "
\n",
- "
tt9911774
\n",
- "
Padmavyuhathile Abhimanyu
\n",
- "
Padmavyuhathile Abhimanyu
\n",
- "
False
\n",
- "
2019
\n",
- "
130
\n",
- "
Drama
\n",
- "
8.5
\n",
- "
363
\n",
- "
\n",
- "
\n",
- "
tt9913056
\n",
- "
Swarm Season
\n",
- "
Swarm Season
\n",
- "
False
\n",
- "
2019
\n",
- "
86
\n",
- "
Documentary
\n",
- "
6.2
\n",
- "
5
\n",
- "
\n",
- "
\n",
- "
tt9913084
\n",
- "
Diabolik sono io
\n",
- "
Diabolik sono io
\n",
- "
False
\n",
- "
2019
\n",
- "
75
\n",
- "
Documentary
\n",
- "
6.2
\n",
- "
6
\n",
- "
\n",
- "
\n",
- "
tt9914286
\n",
- "
Sokagin Çocuklari
\n",
- "
Sokagin Çocuklari
\n",
- "
False
\n",
- "
2019
\n",
- "
98
\n",
- "
Drama,Family
\n",
- "
9.8
\n",
- "
72
\n",
- "
\n",
- " \n",
- "
\n",
- "
232496 rows × 8 columns
\n",
- "
"
- ],
- "text/plain": [
- " title original_title \\\n",
- "tconst \n",
- "tt0000009 Miss Jerry Miss Jerry \n",
- "tt0000147 The Corbett-Fitzsimmons Fight The Corbett-Fitzsimmons Fight \n",
- "tt0000335 Soldiers of the Cross Soldiers of the Cross \n",
- "tt0000574 The Story of the Kelly Gang The Story of the Kelly Gang \n",
- "tt0000615 Robbery Under Arms Robbery Under Arms \n",
- "... ... ... \n",
- "tt9910930 Jeg ser deg Jeg ser deg \n",
- "tt9911774 Padmavyuhathile Abhimanyu Padmavyuhathile Abhimanyu \n",
- "tt9913056 Swarm Season Swarm Season \n",
- "tt9913084 Diabolik sono io Diabolik sono io \n",
- "tt9914286 Sokagin Çocuklari Sokagin Çocuklari \n",
- "\n",
- " is_adult year length genres imdb_rating \\\n",
- "tconst \n",
- "tt0000009 False 1894 45 Romance 5.5 \n",
- "tt0000147 False 1897 20 Documentary,News,Sport 5.2 \n",
- "tt0000335 False 1900 Biography,Drama 6.3 \n",
- "tt0000574 False 1906 70 Biography,Crime,Drama 6.2 \n",
- "tt0000615 False 1907 Drama 4.8 \n",
- "... ... ... ... ... ... \n",
- "tt9910930 False 2019 75 Crime,Documentary 4.6 \n",
- "tt9911774 False 2019 130 Drama 8.5 \n",
- "tt9913056 False 2019 86 Documentary 6.2 \n",
- "tt9913084 False 2019 75 Documentary 6.2 \n",
- "tt9914286 False 2019 98 Drama,Family 9.8 \n",
- "\n",
- " imdb_votes \n",
- "tconst \n",
- "tt0000009 77 \n",
- "tt0000147 289 \n",
- "tt0000335 39 \n",
- "tt0000574 505 \n",
- "tt0000615 14 \n",
- "... ... \n",
- "tt9910930 5 \n",
- "tt9911774 363 \n",
- "tt9913056 5 \n",
- "tt9913084 6 \n",
- "tt9914286 72 \n",
- "\n",
- "[232496 rows x 8 columns]"
- ]
- },
- "execution_count": 25,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# Alternativa 1 (preferovaná)\n",
- "movies_with_rating = movies.join(ratings, how=\"inner\")\n",
- "movies_with_rating"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 26,
- "metadata": {
- "scrolled": true
- },
- "outputs": [
- {
- "data": {
- "text/html": [
- "
\n",
- "\n",
- "
\n",
- " \n",
- "
\n",
- "
\n",
- "
title
\n",
- "
original_title
\n",
- "
is_adult
\n",
- "
year
\n",
- "
length
\n",
- "
genres
\n",
- "
imdb_rating
\n",
- "
imdb_votes
\n",
- "
\n",
- "
\n",
- "
tconst
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- " \n",
- " \n",
- "
\n",
- "
tt0000009
\n",
- "
Miss Jerry
\n",
- "
Miss Jerry
\n",
- "
False
\n",
- "
1894
\n",
- "
45
\n",
- "
Romance
\n",
- "
5.5
\n",
- "
77
\n",
- "
\n",
- "
\n",
- "
tt0000147
\n",
- "
The Corbett-Fitzsimmons Fight
\n",
- "
The Corbett-Fitzsimmons Fight
\n",
- "
False
\n",
- "
1897
\n",
- "
20
\n",
- "
Documentary,News,Sport
\n",
- "
5.2
\n",
- "
289
\n",
- "
\n",
- "
\n",
- "
tt0000335
\n",
- "
Soldiers of the Cross
\n",
- "
Soldiers of the Cross
\n",
- "
False
\n",
- "
1900
\n",
- "
<NA>
\n",
- "
Biography,Drama
\n",
- "
6.3
\n",
- "
39
\n",
- "
\n",
- "
\n",
- "
tt0000574
\n",
- "
The Story of the Kelly Gang
\n",
- "
The Story of the Kelly Gang
\n",
- "
False
\n",
- "
1906
\n",
- "
70
\n",
- "
Biography,Crime,Drama
\n",
- "
6.2
\n",
- "
505
\n",
- "
\n",
- "
\n",
- "
tt0000615
\n",
- "
Robbery Under Arms
\n",
- "
Robbery Under Arms
\n",
- "
False
\n",
- "
1907
\n",
- "
<NA>
\n",
- "
Drama
\n",
- "
4.8
\n",
- "
14
\n",
- "
\n",
- "
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
\n",
- "
\n",
- "
tt9910930
\n",
- "
Jeg ser deg
\n",
- "
Jeg ser deg
\n",
- "
False
\n",
- "
2019
\n",
- "
75
\n",
- "
Crime,Documentary
\n",
- "
4.6
\n",
- "
5
\n",
- "
\n",
- "
\n",
- "
tt9911774
\n",
- "
Padmavyuhathile Abhimanyu
\n",
- "
Padmavyuhathile Abhimanyu
\n",
- "
False
\n",
- "
2019
\n",
- "
130
\n",
- "
Drama
\n",
- "
8.5
\n",
- "
363
\n",
- "
\n",
- "
\n",
- "
tt9913056
\n",
- "
Swarm Season
\n",
- "
Swarm Season
\n",
- "
False
\n",
- "
2019
\n",
- "
86
\n",
- "
Documentary
\n",
- "
6.2
\n",
- "
5
\n",
- "
\n",
- "
\n",
- "
tt9913084
\n",
- "
Diabolik sono io
\n",
- "
Diabolik sono io
\n",
- "
False
\n",
- "
2019
\n",
- "
75
\n",
- "
Documentary
\n",
- "
6.2
\n",
- "
6
\n",
- "
\n",
- "
\n",
- "
tt9914286
\n",
- "
Sokagin Çocuklari
\n",
- "
Sokagin Çocuklari
\n",
- "
False
\n",
- "
2019
\n",
- "
98
\n",
- "
Drama,Family
\n",
- "
9.8
\n",
- "
72
\n",
- "
\n",
- " \n",
- "
\n",
- "
232496 rows × 8 columns
\n",
- "
"
- ],
- "text/plain": [
- " title original_title \\\n",
- "tconst \n",
- "tt0000009 Miss Jerry Miss Jerry \n",
- "tt0000147 The Corbett-Fitzsimmons Fight The Corbett-Fitzsimmons Fight \n",
- "tt0000335 Soldiers of the Cross Soldiers of the Cross \n",
- "tt0000574 The Story of the Kelly Gang The Story of the Kelly Gang \n",
- "tt0000615 Robbery Under Arms Robbery Under Arms \n",
- "... ... ... \n",
- "tt9910930 Jeg ser deg Jeg ser deg \n",
- "tt9911774 Padmavyuhathile Abhimanyu Padmavyuhathile Abhimanyu \n",
- "tt9913056 Swarm Season Swarm Season \n",
- "tt9913084 Diabolik sono io Diabolik sono io \n",
- "tt9914286 Sokagin Çocuklari Sokagin Çocuklari \n",
- "\n",
- " is_adult year length genres imdb_rating \\\n",
- "tconst \n",
- "tt0000009 False 1894 45 Romance 5.5 \n",
- "tt0000147 False 1897 20 Documentary,News,Sport 5.2 \n",
- "tt0000335 False 1900 Biography,Drama 6.3 \n",
- "tt0000574 False 1906 70 Biography,Crime,Drama 6.2 \n",
- "tt0000615 False 1907 Drama 4.8 \n",
- "... ... ... ... ... ... \n",
- "tt9910930 False 2019 75 Crime,Documentary 4.6 \n",
- "tt9911774 False 2019 130 Drama 8.5 \n",
- "tt9913056 False 2019 86 Documentary 6.2 \n",
- "tt9913084 False 2019 75 Documentary 6.2 \n",
- "tt9914286 False 2019 98 Drama,Family 9.8 \n",
- "\n",
- " imdb_votes \n",
- "tconst \n",
- "tt0000009 77 \n",
- "tt0000147 289 \n",
- "tt0000335 39 \n",
- "tt0000574 505 \n",
- "tt0000615 14 \n",
- "... ... \n",
- "tt9910930 5 \n",
- "tt9911774 363 \n",
- "tt9913056 5 \n",
- "tt9913084 6 \n",
- "tt9914286 72 \n",
- "\n",
- "[232496 rows x 8 columns]"
- ]
- },
- "execution_count": 26,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# Alternativa 2 (taky dobrá)\n",
- "pd.merge(movies, ratings, left_index=True, right_index=True)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 27,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
\n",
- "\n",
- "
\n",
- " \n",
- "
\n",
- "
\n",
- "
title
\n",
- "
original_title
\n",
- "
is_adult
\n",
- "
year
\n",
- "
length
\n",
- "
genres
\n",
- "
imdb_rating
\n",
- "
imdb_votes
\n",
- "
\n",
- "
\n",
- "
tconst
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- "
\n",
- " \n",
- " \n",
- "
\n",
- "
tt0000009
\n",
- "
Miss Jerry
\n",
- "
Miss Jerry
\n",
- "
False
\n",
- "
1894
\n",
- "
45
\n",
- "
Romance
\n",
- "
5.5
\n",
- "
77
\n",
- "
\n",
- "
\n",
- "
tt0000147
\n",
- "
The Corbett-Fitzsimmons Fight
\n",
- "
The Corbett-Fitzsimmons Fight
\n",
- "
False
\n",
- "
1897
\n",
- "
20
\n",
- "
Documentary,News,Sport
\n",
- "
5.2
\n",
- "
289
\n",
- "
\n",
- "
\n",
- "
tt0000335
\n",
- "
Soldiers of the Cross
\n",
- "
Soldiers of the Cross
\n",
- "
False
\n",
- "
1900
\n",
- "
<NA>
\n",
- "
Biography,Drama
\n",
- "
6.3
\n",
- "
39
\n",
- "
\n",
- "
\n",
- "
tt0000574
\n",
- "
The Story of the Kelly Gang
\n",
- "
The Story of the Kelly Gang
\n",
- "
False
\n",
- "
1906
\n",
- "
70
\n",
- "
Biography,Crime,Drama
\n",
- "
6.2
\n",
- "
505
\n",
- "
\n",
- "
\n",
- "
tt0000615
\n",
- "
Robbery Under Arms
\n",
- "
Robbery Under Arms
\n",
- "
False
\n",
- "
1907
\n",
- "
<NA>
\n",
- "
Drama
\n",
- "
4.8
\n",
- "
14
\n",
- "
\n",
- "
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
\n",
- "
\n",
- "
tt9910930
\n",
- "
Jeg ser deg
\n",
- "
Jeg ser deg
\n",
- "
False
\n",
- "
2019
\n",
- "
75
\n",
- "
Crime,Documentary
\n",
- "
4.6
\n",
- "
5
\n",
- "
\n",
- "
\n",
- "
tt9911774
\n",
- "
Padmavyuhathile Abhimanyu
\n",
- "
Padmavyuhathile Abhimanyu
\n",
- "
False
\n",
- "
2019
\n",
- "
130
\n",
- "
Drama
\n",
- "
8.5
\n",
- "
363
\n",
- "
\n",
- "
\n",
- "
tt9913056
\n",
- "
Swarm Season
\n",
- "
Swarm Season
\n",
- "
False
\n",
- "
2019
\n",
- "
86
\n",
- "
Documentary
\n",
- "
6.2
\n",
- "
5
\n",
- "
\n",
- "
\n",
- "
tt9913084
\n",
- "
Diabolik sono io
\n",
- "
Diabolik sono io
\n",
- "
False
\n",
- "
2019
\n",
- "
75
\n",
- "
Documentary
\n",
- "
6.2
\n",
- "
6
\n",
- "
\n",
- "
\n",
- "
tt9914286
\n",
- "
Sokagin Çocuklari
\n",
- "
Sokagin Çocuklari
\n",
- "
False
\n",
- "
2019
\n",
- "
98
\n",
- "
Drama,Family
\n",
- "
9.8
\n",
- "
72
\n",
- "
\n",
- " \n",
- "
\n",
- "
232496 rows × 8 columns
\n",
- "
"
- ],
- "text/plain": [
- " title original_title \\\n",
- "tconst \n",
- "tt0000009 Miss Jerry Miss Jerry \n",
- "tt0000147 The Corbett-Fitzsimmons Fight The Corbett-Fitzsimmons Fight \n",
- "tt0000335 Soldiers of the Cross Soldiers of the Cross \n",
- "tt0000574 The Story of the Kelly Gang The Story of the Kelly Gang \n",
- "tt0000615 Robbery Under Arms Robbery Under Arms \n",
- "... ... ... \n",
- "tt9910930 Jeg ser deg Jeg ser deg \n",
- "tt9911774 Padmavyuhathile Abhimanyu Padmavyuhathile Abhimanyu \n",
- "tt9913056 Swarm Season Swarm Season \n",
- "tt9913084 Diabolik sono io Diabolik sono io \n",
- "tt9914286 Sokagin Çocuklari Sokagin Çocuklari \n",
- "\n",
- " is_adult year length genres imdb_rating \\\n",
- "tconst \n",
- "tt0000009 False 1894 45 Romance 5.5 \n",
- "tt0000147 False 1897 20 Documentary,News,Sport 5.2 \n",
- "tt0000335 False 1900 Biography,Drama 6.3 \n",
- "tt0000574 False 1906 70 Biography,Crime,Drama 6.2 \n",
- "tt0000615 False 1907 Drama 4.8 \n",
- "... ... ... ... ... ... \n",
- "tt9910930 False 2019 75 Crime,Documentary 4.6 \n",
- "tt9911774 False 2019 130 Drama 8.5 \n",
- "tt9913056 False 2019 86 Documentary 6.2 \n",
- "tt9913084 False 2019 75 Documentary 6.2 \n",
- "tt9914286 False 2019 98 Drama,Family 9.8 \n",
- "\n",
- " imdb_votes \n",
- "tconst \n",
- "tt0000009 77 \n",
- "tt0000147 289 \n",
- "tt0000335 39 \n",
- "tt0000574 505 \n",
- "tt0000615 14 \n",
- "... ... \n",
- "tt9910930 5 \n",
- "tt9911774 363 \n",
- "tt9913056 5 \n",
- "tt9913084 6 \n",
- "tt9914286 72 \n",
- "\n",
- "[232496 rows x 8 columns]"
- ]
- },
- "execution_count": 27,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# Alternativa 3 (méně \"sémantická\")\n",
- "pd.concat([movies, ratings], axis=\"columns\", join=\"inner\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Zkusme si zreprodukovat pořadí 250 nejlepších filmů z IMDb (viz https://www.imdb.com/chart/top/?ref_=nv_mv_250):"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 28,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
\n",
- "\n",
- "
\n",
- " \n",
- "
\n",
- "
\n",
- "
title
\n",
- "
original_title
\n",
- "
is_adult
\n",
- "
year
\n",
- "
length
\n",
- "
genres
\n",
- "
imdb_rating
\n",
- "
imdb_votes
\n",
- "
\n",
- " \n",
- " \n",
- "
\n",
- "
0
\n",
- "
The Chaos Class
\n",
- "
Hababam Sinifi
\n",
- "
False
\n",
- "
1975
\n",
- "
87
\n",
- "
Comedy,Drama
\n",
- "
9.4
\n",
- "
33394
\n",
- "
\n",
- "
\n",
- "
1
\n",
- "
The Shawshank Redemption
\n",
- "
The Shawshank Redemption
\n",
- "
False
\n",
- "
1994
\n",
- "
142
\n",
- "
Drama
\n",
- "
9.3
\n",
- "
2071759
\n",
- "
\n",
- "
\n",
- "
2
\n",
- "
The Mountain II
\n",
- "
Dag II
\n",
- "
False
\n",
- "
2016
\n",
- "
135
\n",
- "
Action,Drama,War
\n",
- "
9.3
\n",
- "
100095
\n",
- "
\n",
- "
\n",
- "
3
\n",
- "
CM101MMXI Fundamentals
\n",
- "
CM101MMXI Fundamentals
\n",
- "
False
\n",
- "
2013
\n",
- "
139
\n",
- "
Comedy,Documentary
\n",
- "
9.2
\n",
- "
41327
\n",
- "
\n",
- "
\n",
- "
4
\n",
- "
The Godfather
\n",
- "
The Godfather
\n",
- "
False
\n",
- "
1972
\n",
- "
175
\n",
- "
Crime,Drama
\n",
- "
9.2
\n",
- "
1421495
\n",
- "
\n",
- "
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
\n",
- "
\n",
- "
245
\n",
- "
12 Years a Slave
\n",
- "
12 Years a Slave
\n",
- "
False
\n",
- "
2013
\n",
- "
134
\n",
- "
Biography,Drama,History
\n",
- "
8.1
\n",
- "
571204
\n",
- "
\n",
- "
\n",
- "
246
\n",
- "
The Sixth Sense
\n",
- "
The Sixth Sense
\n",
- "
False
\n",
- "
1999
\n",
- "
107
\n",
- "
Drama,Mystery,Thriller
\n",
- "
8.1
\n",
- "
836928
\n",
- "
\n",
- "
\n",
- "
247
\n",
- "
The Passion of Joan of Arc
\n",
- "
La passion de Jeanne d'Arc
\n",
- "
False
\n",
- "
1928
\n",
- "
110
\n",
- "
Biography,Drama,History
\n",
- "
8.1
\n",
- "
40107
\n",
- "
\n",
- "
\n",
- "
248
\n",
- "
Barfi!
\n",
- "
Barfi!
\n",
- "
False
\n",
- "
2012
\n",
- "
151
\n",
- "
Comedy,Drama,Romance
\n",
- "
8.1
\n",
- "
68274
\n",
- "
\n",
- "
\n",
- "
249
\n",
- "
Platoon
\n",
- "
Platoon
\n",
- "
False
\n",
- "
1986
\n",
- "
120
\n",
- "
Drama,War
\n",
- "
8.1
\n",
- "
348628
\n",
- "
\n",
- " \n",
- "
\n",
- "
250 rows × 8 columns
\n",
- "
"
- ],
- "text/plain": [
- " title original_title is_adult year \\\n",
- "0 The Chaos Class Hababam Sinifi False 1975 \n",
- "1 The Shawshank Redemption The Shawshank Redemption False 1994 \n",
- "2 The Mountain II Dag II False 2016 \n",
- "3 CM101MMXI Fundamentals CM101MMXI Fundamentals False 2013 \n",
- "4 The Godfather The Godfather False 1972 \n",
- ".. ... ... ... ... \n",
- "245 12 Years a Slave 12 Years a Slave False 2013 \n",
- "246 The Sixth Sense The Sixth Sense False 1999 \n",
- "247 The Passion of Joan of Arc La passion de Jeanne d'Arc False 1928 \n",
- "248 Barfi! Barfi! False 2012 \n",
- "249 Platoon Platoon False 1986 \n",
- "\n",
- " length genres imdb_rating imdb_votes \n",
- "0 87 Comedy,Drama 9.4 33394 \n",
- "1 142 Drama 9.3 2071759 \n",
- "2 135 Action,Drama,War 9.3 100095 \n",
- "3 139 Comedy,Documentary 9.2 41327 \n",
- "4 175 Crime,Drama 9.2 1421495 \n",
- ".. ... ... ... ... \n",
- "245 134 Biography,Drama,History 8.1 571204 \n",
- "246 107 Drama,Mystery,Thriller 8.1 836928 \n",
- "247 110 Biography,Drama,History 8.1 40107 \n",
- "248 151 Comedy,Drama,Romance 8.1 68274 \n",
- "249 120 Drama,War 8.1 348628 \n",
- "\n",
- "[250 rows x 8 columns]"
- ]
- },
- "execution_count": 28,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# Ty nejlepší (do června 2019)\n",
- "(movies_with_rating\n",
- " .query(\"imdb_votes > 25000\") # Berou se jen filmy s více než 25000 hlasy\n",
- " .sort_values(\"imdb_rating\", ascending=False) # IMDb tu použivá i váhu jednotlivých hlasů (kterou neznáme)\n",
- " .reset_index(drop=True)\n",
- ").iloc[:250]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Do výčtu se nám dostaly filmy, které hranici hlasů nepřekračují o moc. Máme důvodné podezření, že toto kritérium dávno změnili. S požadovanými 250 000 hlasy se už blížíme:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 29,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
"
- ],
- "text/plain": [
- " rank title studio lifetime_gross \\\n",
- "0 1 Star Wars: The Force Awakens BV 936662225 \n",
- "1 2 Avatar Fox 760507625 \n",
- "2 3 Black Panther BV 700059566 \n",
- "3 4 Avengers: Infinity War BV 678815482 \n",
- "4 5 Titanic Par. 659363944 \n",
- "... ... ... ... ... \n",
- "16262 16263 Dog Eat Dog IFC 80 \n",
- "16263 16264 Paranoid Girls NaN 78 \n",
- "16264 16265 Confession of a Child of the Century Cohen 74 \n",
- "16265 16266 Storage 24 Magn. 72 \n",
- "16266 16267 Zyzzyx Road Reg. 30 \n",
- "\n",
- " year \n",
- "0 2015 \n",
- "1 2009 \n",
- "2 2018 \n",
- "3 2018 \n",
- "4 1997 \n",
- "... ... \n",
- "16262 2009 \n",
- "16263 2015 \n",
- "16264 2015 \n",
- "16265 2013 \n",
- "16266 2006 \n",
- "\n",
- "[16267 rows x 5 columns]"
- ]
- },
- "execution_count": 30,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "boxoffice_raw"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 31,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "rank int64\n",
- "title object\n",
- "studio object\n",
- "lifetime_gross int64\n",
- "year int64\n",
- "dtype: object"
- ]
- },
- "execution_count": 31,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "boxoffice_raw.dtypes"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "S tím bychom v podstatně mohli být spokojení, jen přejmenujeme `rank`, abychom při joinování věděli, odkud daný sloupec pochází."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 32,
- "metadata": {},
- "outputs": [],
- "source": [
- "boxoffice = (boxoffice_raw\n",
- " .rename({\n",
- " \"rank\": \"boxoffice_rank\"\n",
- " }, axis=\"columns\")\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "A zkusíme joinovat. V tomto případě se nemůžeme opřít o index (`boxoffice` pochází z jiného zdroje a o nějakém ID filmu z IMDb nemá ani tuchy), ale explicitně specifikujeme, který sloupec (či sloupce) se musí shodovat - na to slouží argument `on`:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 33,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
\n",
- "\n",
- "
\n",
- " \n",
- "
\n",
- "
\n",
- "
title
\n",
- "
original_title
\n",
- "
is_adult
\n",
- "
year (imdb)
\n",
- "
length
\n",
- "
genres
\n",
- "
imdb_rating
\n",
- "
imdb_votes
\n",
- "
boxoffice_rank
\n",
- "
studio
\n",
- "
lifetime_gross
\n",
- "
year (boxoffice)
\n",
- "
\n",
- " \n",
- " \n",
- "
\n",
- "
1643
\n",
- "
Pinocchio
\n",
- "
Pinocchio
\n",
- "
False
\n",
- "
1940
\n",
- "
88
\n",
- "
Animation,Comedy,Family
\n",
- "
7.5
\n",
- "
114689
\n",
- "
885
\n",
- "
Dis.
\n",
- "
84254167
\n",
- "
1940
\n",
- "
\n",
- "
\n",
- "
1644
\n",
- "
Pinocchio
\n",
- "
Pinocchio
\n",
- "
False
\n",
- "
1940
\n",
- "
88
\n",
- "
Animation,Comedy,Family
\n",
- "
7.5
\n",
- "
114689
\n",
- "
6108
\n",
- "
Mira.
\n",
- "
3684305
\n",
- "
2002
\n",
- "
\n",
- "
\n",
- "
1645
\n",
- "
Pinocchio
\n",
- "
Turlis Abenteuer
\n",
- "
False
\n",
- "
1967
\n",
- "
75
\n",
- "
Adventure,Family,Fantasy
\n",
- "
7.2
\n",
- "
19
\n",
- "
885
\n",
- "
Dis.
\n",
- "
84254167
\n",
- "
1940
\n",
- "
\n",
- "
\n",
- "
1646
\n",
- "
Pinocchio
\n",
- "
Turlis Abenteuer
\n",
- "
False
\n",
- "
1967
\n",
- "
75
\n",
- "
Adventure,Family,Fantasy
\n",
- "
7.2
\n",
- "
19
\n",
- "
6108
\n",
- "
Mira.
\n",
- "
3684305
\n",
- "
2002
\n",
- "
\n",
- "
\n",
- "
1647
\n",
- "
Pinocchio
\n",
- "
Pinocchio
\n",
- "
False
\n",
- "
1971
\n",
- "
79
\n",
- "
Comedy,Fantasy
\n",
- "
3.5
\n",
- "
123
\n",
- "
885
\n",
- "
Dis.
\n",
- "
84254167
\n",
- "
1940
\n",
- "
\n",
- "
\n",
- "
1648
\n",
- "
Pinocchio
\n",
- "
Pinocchio
\n",
- "
False
\n",
- "
1971
\n",
- "
79
\n",
- "
Comedy,Fantasy
\n",
- "
3.5
\n",
- "
123
\n",
- "
6108
\n",
- "
Mira.
\n",
- "
3684305
\n",
- "
2002
\n",
- "
\n",
- "
\n",
- "
1649
\n",
- "
Pinocchio
\n",
- "
Pinocchio
\n",
- "
False
\n",
- "
1911
\n",
- "
50
\n",
- "
Fantasy
\n",
- "
5.9
\n",
- "
69
\n",
- "
885
\n",
- "
Dis.
\n",
- "
84254167
\n",
- "
1940
\n",
- "
\n",
- "
\n",
- "
1650
\n",
- "
Pinocchio
\n",
- "
Pinocchio
\n",
- "
False
\n",
- "
1911
\n",
- "
50
\n",
- "
Fantasy
\n",
- "
5.9
\n",
- "
69
\n",
- "
6108
\n",
- "
Mira.
\n",
- "
3684305
\n",
- "
2002
\n",
- "
\n",
- "
\n",
- "
1651
\n",
- "
Pinocchio
\n",
- "
Pinocchio
\n",
- "
False
\n",
- "
2002
\n",
- "
108
\n",
- "
Comedy,Family,Fantasy
\n",
- "
4.3
\n",
- "
7192
\n",
- "
885
\n",
- "
Dis.
\n",
- "
84254167
\n",
- "
1940
\n",
- "
\n",
- "
\n",
- "
1652
\n",
- "
Pinocchio
\n",
- "
Pinocchio
\n",
- "
False
\n",
- "
2002
\n",
- "
108
\n",
- "
Comedy,Family,Fantasy
\n",
- "
4.3
\n",
- "
7192
\n",
- "
6108
\n",
- "
Mira.
\n",
- "
3684305
\n",
- "
2002
\n",
- "
\n",
- "
\n",
- "
1653
\n",
- "
Pinocchio
\n",
- "
Un burattino di nome Pinocchio
\n",
- "
False
\n",
- "
1971
\n",
- "
96
\n",
- "
Animation,Family,Fantasy
\n",
- "
7.0
\n",
- "
117
\n",
- "
885
\n",
- "
Dis.
\n",
- "
84254167
\n",
- "
1940
\n",
- "
\n",
- "
\n",
- "
1654
\n",
- "
Pinocchio
\n",
- "
Un burattino di nome Pinocchio
\n",
- "
False
\n",
- "
1971
\n",
- "
96
\n",
- "
Animation,Family,Fantasy
\n",
- "
7.0
\n",
- "
117
\n",
- "
6108
\n",
- "
Mira.
\n",
- "
3684305
\n",
- "
2002
\n",
- "
\n",
- "
\n",
- "
1655
\n",
- "
Pinocchio
\n",
- "
Pinocchio
\n",
- "
False
\n",
- "
2012
\n",
- "
75
\n",
- "
Animation,Family,Fantasy
\n",
- "
6.3
\n",
- "
218
\n",
- "
885
\n",
- "
Dis.
\n",
- "
84254167
\n",
- "
1940
\n",
- "
\n",
- "
\n",
- "
1656
\n",
- "
Pinocchio
\n",
- "
Pinocchio
\n",
- "
False
\n",
- "
2012
\n",
- "
75
\n",
- "
Animation,Family,Fantasy
\n",
- "
6.3
\n",
- "
218
\n",
- "
6108
\n",
- "
Mira.
\n",
- "
3684305
\n",
- "
2002
\n",
- "
\n",
- "
\n",
- "
1657
\n",
- "
Pinocchio
\n",
- "
Pinocchio
\n",
- "
False
\n",
- "
2015
\n",
- "
<NA>
\n",
- "
Family,Fantasy
\n",
- "
4.9
\n",
- "
43
\n",
- "
885
\n",
- "
Dis.
\n",
- "
84254167
\n",
- "
1940
\n",
- "
\n",
- "
\n",
- "
1658
\n",
- "
Pinocchio
\n",
- "
Pinocchio
\n",
- "
False
\n",
- "
2015
\n",
- "
<NA>
\n",
- "
Family,Fantasy
\n",
- "
4.9
\n",
- "
43
\n",
- "
6108
\n",
- "
Mira.
\n",
- "
3684305
\n",
- "
2002
\n",
- "
\n",
- "
\n",
- "
1659
\n",
- "
Pinocchio
\n",
- "
Pinocchio
\n",
- "
False
\n",
- "
2015
\n",
- "
75
\n",
- "
Documentary
\n",
- "
6.8
\n",
- "
8
\n",
- "
885
\n",
- "
Dis.
\n",
- "
84254167
\n",
- "
1940
\n",
- "
\n",
- "
\n",
- "
1660
\n",
- "
Pinocchio
\n",
- "
Pinocchio
\n",
- "
False
\n",
- "
2015
\n",
- "
75
\n",
- "
Documentary
\n",
- "
6.8
\n",
- "
8
\n",
- "
6108
\n",
- "
Mira.
\n",
- "
3684305
\n",
- "
2002
\n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " title original_title is_adult year (imdb) \\\n",
- "1643 Pinocchio Pinocchio False 1940 \n",
- "1644 Pinocchio Pinocchio False 1940 \n",
- "1645 Pinocchio Turlis Abenteuer False 1967 \n",
- "1646 Pinocchio Turlis Abenteuer False 1967 \n",
- "1647 Pinocchio Pinocchio False 1971 \n",
- "1648 Pinocchio Pinocchio False 1971 \n",
- "1649 Pinocchio Pinocchio False 1911 \n",
- "1650 Pinocchio Pinocchio False 1911 \n",
- "1651 Pinocchio Pinocchio False 2002 \n",
- "1652 Pinocchio Pinocchio False 2002 \n",
- "1653 Pinocchio Un burattino di nome Pinocchio False 1971 \n",
- "1654 Pinocchio Un burattino di nome Pinocchio False 1971 \n",
- "1655 Pinocchio Pinocchio False 2012 \n",
- "1656 Pinocchio Pinocchio False 2012 \n",
- "1657 Pinocchio Pinocchio False 2015 \n",
- "1658 Pinocchio Pinocchio False 2015 \n",
- "1659 Pinocchio Pinocchio False 2015 \n",
- "1660 Pinocchio Pinocchio False 2015 \n",
- "\n",
- " length genres imdb_rating imdb_votes \\\n",
- "1643 88 Animation,Comedy,Family 7.5 114689 \n",
- "1644 88 Animation,Comedy,Family 7.5 114689 \n",
- "1645 75 Adventure,Family,Fantasy 7.2 19 \n",
- "1646 75 Adventure,Family,Fantasy 7.2 19 \n",
- "1647 79 Comedy,Fantasy 3.5 123 \n",
- "1648 79 Comedy,Fantasy 3.5 123 \n",
- "1649 50 Fantasy 5.9 69 \n",
- "1650 50 Fantasy 5.9 69 \n",
- "1651 108 Comedy,Family,Fantasy 4.3 7192 \n",
- "1652 108 Comedy,Family,Fantasy 4.3 7192 \n",
- "1653 96 Animation,Family,Fantasy 7.0 117 \n",
- "1654 96 Animation,Family,Fantasy 7.0 117 \n",
- "1655 75 Animation,Family,Fantasy 6.3 218 \n",
- "1656 75 Animation,Family,Fantasy 6.3 218 \n",
- "1657 Family,Fantasy 4.9 43 \n",
- "1658 Family,Fantasy 4.9 43 \n",
- "1659 75 Documentary 6.8 8 \n",
- "1660 75 Documentary 6.8 8 \n",
- "\n",
- " boxoffice_rank studio lifetime_gross year (boxoffice) \n",
- "1643 885 Dis. 84254167 1940 \n",
- "1644 6108 Mira. 3684305 2002 \n",
- "1645 885 Dis. 84254167 1940 \n",
- "1646 6108 Mira. 3684305 2002 \n",
- "1647 885 Dis. 84254167 1940 \n",
- "1648 6108 Mira. 3684305 2002 \n",
- "1649 885 Dis. 84254167 1940 \n",
- "1650 6108 Mira. 3684305 2002 \n",
- "1651 885 Dis. 84254167 1940 \n",
- "1652 6108 Mira. 3684305 2002 \n",
- "1653 885 Dis. 84254167 1940 \n",
- "1654 6108 Mira. 3684305 2002 \n",
- "1655 885 Dis. 84254167 1940 \n",
- "1656 6108 Mira. 3684305 2002 \n",
- "1657 885 Dis. 84254167 1940 \n",
- "1658 6108 Mira. 3684305 2002 \n",
- "1659 885 Dis. 84254167 1940 \n",
- "1660 6108 Mira. 3684305 2002 "
- ]
- },
- "execution_count": 33,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "pd.merge(\n",
- " movies_with_rating,\n",
- " boxoffice,\n",
- " suffixes=[\" (imdb)\", \" (boxoffice)\"],\n",
- " on=\"title\"\n",
- ").query(\"title == 'Pinocchio'\") # \"Jeden\" ukázkový film"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Jejda, to jsme asi nechtěli. Existuje spousta různých Pinocchiů a ke každému z nich se připojili vždy oba snímky tohoto jména z `boxoffice`. Z toho vyplývá poučení, že při joinování je dobré se zamyslet nad jedinečností hodnot ve sloupci, který používáme jako klíč. Jméno filmu takové očividně není.\n",
- "\n",
- "V našem konkrétním případě jsme si problému všimli sami, ale pokud bude duplikátní klíč utopen někde v milionech hodnot, rádi bychom, aby to počítač poznal za nás. K tomu slouží argument `validate` - podle toho, jaký vztah mezi tabulkami očekáš, jsou přípustné hodnoty `\"one_to_one\"`, `\"one_to_many\"`, `\"many_to_one\"` nebo `\"many_to_many\"`:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 34,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
\n",
- "\n",
- "
\n",
- " \n",
- "
\n",
- "
\n",
- "
title
\n",
- "
original_title
\n",
- "
is_adult
\n",
- "
year (imdb)
\n",
- "
length
\n",
- "
genres
\n",
- "
imdb_rating
\n",
- "
imdb_votes
\n",
- "
boxoffice_rank
\n",
- "
studio
\n",
- "
lifetime_gross
\n",
- "
year (boxoffice)
\n",
- "
\n",
- " \n",
- " \n",
- "
\n",
- "
0
\n",
- "
Oliver Twist
\n",
- "
Oliver Twist
\n",
- "
False
\n",
- "
1912
\n",
- "
<NA>
\n",
- "
Drama
\n",
- "
4.7
\n",
- "
19
\n",
- "
6826
\n",
- "
Sony
\n",
- "
2080321
\n",
- "
2005
\n",
- "
\n",
- "
\n",
- "
1
\n",
- "
Oliver Twist
\n",
- "
Oliver Twist
\n",
- "
False
\n",
- "
1912
\n",
- "
<NA>
\n",
- "
Drama
\n",
- "
4.4
\n",
- "
12
\n",
- "
6826
\n",
- "
Sony
\n",
- "
2080321
\n",
- "
2005
\n",
- "
\n",
- "
\n",
- "
2
\n",
- "
Oliver Twist
\n",
- "
Oliver Twist
\n",
- "
False
\n",
- "
1916
\n",
- "
50
\n",
- "
Drama
\n",
- "
6.6
\n",
- "
16
\n",
- "
6826
\n",
- "
Sony
\n",
- "
2080321
\n",
- "
2005
\n",
- "
\n",
- "
\n",
- "
3
\n",
- "
Oliver Twist
\n",
- "
Oliver Twist
\n",
- "
False
\n",
- "
1922
\n",
- "
98
\n",
- "
Drama
\n",
- "
6.8
\n",
- "
657
\n",
- "
6826
\n",
- "
Sony
\n",
- "
2080321
\n",
- "
2005
\n",
- "
\n",
- "
\n",
- "
4
\n",
- "
Oliver Twist
\n",
- "
Oliver Twist
\n",
- "
False
\n",
- "
1933
\n",
- "
80
\n",
- "
Drama
\n",
- "
5.0
\n",
- "
292
\n",
- "
6826
\n",
- "
Sony
\n",
- "
2080321
\n",
- "
2005
\n",
- "
\n",
- "
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
\n",
- "
\n",
- "
20562
\n",
- "
BTS World Tour: Love Yourself in Seoul
\n",
- "
BTS World Tour: Love Yourself in Seoul
\n",
- "
False
\n",
- "
2019
\n",
- "
112
\n",
- "
Documentary,Music
\n",
- "
8.5
\n",
- "
439
\n",
- "
6173
\n",
- "
Fathom
\n",
- "
3509917
\n",
- "
2019
\n",
- "
\n",
- "
\n",
- "
20563
\n",
- "
Mojin: The Worm Valley
\n",
- "
Yun nan chong gu
\n",
- "
False
\n",
- "
2018
\n",
- "
110
\n",
- "
Action,Fantasy
\n",
- "
4.7
\n",
- "
120
\n",
- "
11240
\n",
- "
WGUSA
\n",
- "
101516
\n",
- "
2019
\n",
- "
\n",
- "
\n",
- "
20564
\n",
- "
Extreme Job
\n",
- "
Geukhanjikeob
\n",
- "
False
\n",
- "
2019
\n",
- "
111
\n",
- "
Action,Comedy
\n",
- "
7.3
\n",
- "
905
\n",
- "
7212
\n",
- "
CJ
\n",
- "
1548816
\n",
- "
2019
\n",
- "
\n",
- "
\n",
- "
20565
\n",
- "
Peppa Celebrates Chinese New Year
\n",
- "
xiao zhu pei qi guo da nian
\n",
- "
False
\n",
- "
2019
\n",
- "
81
\n",
- "
Animation,Family
\n",
- "
3.4
\n",
- "
41
\n",
- "
10811
\n",
- "
STX
\n",
- "
131225
\n",
- "
2019
\n",
- "
\n",
- "
\n",
- "
20566
\n",
- "
Avant qu'on explose
\n",
- "
Avant qu'on explose
\n",
- "
False
\n",
- "
2019
\n",
- "
108
\n",
- "
Comedy
\n",
- "
6.9
\n",
- "
41
\n",
- "
10995
\n",
- "
EOne
\n",
- "
116576
\n",
- "
2019
\n",
- "
\n",
- " \n",
- "
\n",
- "
20567 rows × 12 columns
\n",
- "
"
- ],
- "text/plain": [
- " title \\\n",
- "0 Oliver Twist \n",
- "1 Oliver Twist \n",
- "2 Oliver Twist \n",
- "3 Oliver Twist \n",
- "4 Oliver Twist \n",
- "... ... \n",
- "20562 BTS World Tour: Love Yourself in Seoul \n",
- "20563 Mojin: The Worm Valley \n",
- "20564 Extreme Job \n",
- "20565 Peppa Celebrates Chinese New Year \n",
- "20566 Avant qu'on explose \n",
- "\n",
- " original_title is_adult year (imdb) length \\\n",
- "0 Oliver Twist False 1912 \n",
- "1 Oliver Twist False 1912 \n",
- "2 Oliver Twist False 1916 50 \n",
- "3 Oliver Twist False 1922 98 \n",
- "4 Oliver Twist False 1933 80 \n",
- "... ... ... ... ... \n",
- "20562 BTS World Tour: Love Yourself in Seoul False 2019 112 \n",
- "20563 Yun nan chong gu False 2018 110 \n",
- "20564 Geukhanjikeob False 2019 111 \n",
- "20565 xiao zhu pei qi guo da nian False 2019 81 \n",
- "20566 Avant qu'on explose False 2019 108 \n",
- "\n",
- " genres imdb_rating imdb_votes boxoffice_rank studio \\\n",
- "0 Drama 4.7 19 6826 Sony \n",
- "1 Drama 4.4 12 6826 Sony \n",
- "2 Drama 6.6 16 6826 Sony \n",
- "3 Drama 6.8 657 6826 Sony \n",
- "4 Drama 5.0 292 6826 Sony \n",
- "... ... ... ... ... ... \n",
- "20562 Documentary,Music 8.5 439 6173 Fathom \n",
- "20563 Action,Fantasy 4.7 120 11240 WGUSA \n",
- "20564 Action,Comedy 7.3 905 7212 CJ \n",
- "20565 Animation,Family 3.4 41 10811 STX \n",
- "20566 Comedy 6.9 41 10995 EOne \n",
- "\n",
- " lifetime_gross year (boxoffice) \n",
- "0 2080321 2005 \n",
- "1 2080321 2005 \n",
- "2 2080321 2005 \n",
- "3 2080321 2005 \n",
- "4 2080321 2005 \n",
- "... ... ... \n",
- "20562 3509917 2019 \n",
- "20563 101516 2019 \n",
- "20564 1548816 2019 \n",
- "20565 131225 2019 \n",
- "20566 116576 2019 \n",
- "\n",
- "[20567 rows x 12 columns]"
- ]
- },
- "execution_count": 34,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "pd.merge(\n",
- " movies_with_rating,\n",
- " boxoffice,\n",
- " on=\"title\",\n",
- " suffixes=[\" (imdb)\", \" (boxoffice)\"],\n",
- "# validate=\"one_to_one\" # Odkomentuj a vyskočí chyba!\n",
- ")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Řešení je jednoduché - budeme joinovat přes dva různé sloupce (argument `on` to unese ;-)). Při té příležitosti navíc zjišťujeme, že nedává smysl spojovat filmy, které rok vůbec uvedený nemají, a proto je vyhodíme:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 35,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
\n",
- "\n",
- "
\n",
- " \n",
- "
\n",
- "
\n",
- "
title
\n",
- "
original_title
\n",
- "
is_adult
\n",
- "
year
\n",
- "
length
\n",
- "
genres
\n",
- "
imdb_rating
\n",
- "
imdb_votes
\n",
- "
boxoffice_rank
\n",
- "
studio
\n",
- "
lifetime_gross
\n",
- "
\n",
- " \n",
- " \n",
- "
\n",
- "
6926
\n",
- "
Playback
\n",
- "
Playback
\n",
- "
False
\n",
- "
2012
\n",
- "
98
\n",
- "
Horror,Thriller
\n",
- "
4.3
\n",
- "
4478
\n",
- "
16256
\n",
- "
Magn.
\n",
- "
264
\n",
- "
\n",
- "
\n",
- "
6927
\n",
- "
Playback
\n",
- "
Playback
\n",
- "
False
\n",
- "
2012
\n",
- "
113
\n",
- "
Drama
\n",
- "
4.9
\n",
- "
27
\n",
- "
16256
\n",
- "
Magn.
\n",
- "
264
\n",
- "
\n",
- "
\n",
- "
6928
\n",
- "
Playback
\n",
- "
Dur d'être Dieu
\n",
- "
False
\n",
- "
2012
\n",
- "
66
\n",
- "
Documentary
\n",
- "
5.2
\n",
- "
8
\n",
- "
16256
\n",
- "
Magn.
\n",
- "
264
\n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " title original_title is_adult year length genres \\\n",
- "6926 Playback Playback False 2012 98 Horror,Thriller \n",
- "6927 Playback Playback False 2012 113 Drama \n",
- "6928 Playback Dur d'être Dieu False 2012 66 Documentary \n",
- "\n",
- " imdb_rating imdb_votes boxoffice_rank studio lifetime_gross \n",
- "6926 4.3 4478 16256 Magn. 264 \n",
- "6927 4.9 27 16256 Magn. 264 \n",
- "6928 5.2 8 16256 Magn. 264 "
- ]
- },
- "execution_count": 35,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "(\n",
- " pd.merge(\n",
- " movies_with_rating.dropna(subset=[\"year\"]), # Vyhoď všechny řádky bez roku\n",
- " boxoffice,\n",
- " on=[\"title\", \"year\"],\n",
- " validate=\"many_to_one\", # movies_with_rating pořád nejsou unikátní!\n",
- " )\n",
- ").query(\"title == 'Playback'\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Pořád nejsou unikátní! Co s tím?\n",
- "\n",
- "**Hypotéza:** Vstupujeme na nebezpečnou půdu a zkusíme spekulovat, že informace o ziscích budeme mít nejspíš jen o nejpopulárnějších filmech. Možná máme pravdu, možná ne a nejspíš nějakou drobnou nepřesnost zaneseme, ale dobrat se tady skutečné pravdy je \"drahé\" (a možná i skutečně drahé), z nabízených datových sad to věrohodně možné není.\n",
- "\n",
- "Abychom se co nejvíc přiblížili realitě, z každé opakující se dvojice (název, rok) vybereme film s nejvyšším `imdb_votes`. Nejdříve si pomocí `sort_values` srovnáme všechny filmy a pak zavoláme `drop_duplicates(..., keep=\"first\")`, což nám ponechá vždy jen jeden z řady duplikátů:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 36,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
"
- ],
- "text/plain": [
- "Empty DataFrame\n",
- "Columns: [title_type, title, original_title, is_adult, start_year, end_year, length, genres, Title, RatingTomatometer, No. of Reviews]\n",
- "Index: []"
- ]
- },
- "execution_count": 41,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# Ready to merge?\n",
- "pd.merge(imdb_titles, rotten_tomatoes_nodup, left_on=\"title\", right_on=\"Title\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "0 řádků!\n",
- "\n",
- "Dosud jsme manipulovali s řádky a sloupci jako celky, nicméně teď musíme zasahovat přímo do hodnot v buňkách. I to se při slučování dat z různých zdrojů nezřídka stává. Stojíme před úkolem převést řetězce typu \"Black Panther (2018)\" na dvě hodnoty: název \"Black Panther\" a rok 2018 (jeden sloupec na dva). \n",
- "\n",
- "Naštěstí si ty sloupce umíme jednoduše vyrobit pomocí řetězcové metody [`.str.slice`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.slice.html), která z každého řetězce vyřízne nějakou jeho část (a zase pracuje na celém sloupci - výsledkem bude nový sloupec s funkcí aplikovanou na každou z hodnot). Budeme věřit, že předposlední čtyři znaky představují rok a zbytek, až na nějaké ty závorky, tvoří skutečný název:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 42,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
\n",
- "\n",
- "
\n",
- " \n",
- "
\n",
- "
\n",
- "
tomatoes_rating
\n",
- "
tomatoes_votes
\n",
- "
title
\n",
- "
year
\n",
- "
\n",
- " \n",
- " \n",
- "
\n",
- "
0
\n",
- "
97
\n",
- "
444
\n",
- "
Black Panther
\n",
- "
2018
\n",
- "
\n",
- "
\n",
- "
1
\n",
- "
97
\n",
- "
394
\n",
- "
Mad Max: Fury Road
\n",
- "
2015
\n",
- "
\n",
- "
\n",
- "
2
\n",
- "
93
\n",
- "
410
\n",
- "
Wonder Woman
\n",
- "
2017
\n",
- "
\n",
- "
\n",
- "
3
\n",
- "
99
\n",
- "
118
\n",
- "
Metropolis
\n",
- "
1927
\n",
- "
\n",
- "
\n",
- "
4
\n",
- "
97
\n",
- "
308
\n",
- "
Coco
\n",
- "
2017
\n",
- "
\n",
- "
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
\n",
- "
\n",
- "
1585
\n",
- "
15
\n",
- "
97
\n",
- "
Priest
\n",
- "
2011
\n",
- "
\n",
- "
\n",
- "
1586
\n",
- "
14
\n",
- "
103
\n",
- "
American Outlaws
\n",
- "
2001
\n",
- "
\n",
- "
\n",
- "
1587
\n",
- "
15
\n",
- "
54
\n",
- "
September Dawn
\n",
- "
2007
\n",
- "
\n",
- "
\n",
- "
1588
\n",
- "
12
\n",
- "
147
\n",
- "
Jonah Hex
\n",
- "
2010
\n",
- "
\n",
- "
\n",
- "
1589
\n",
- "
2
\n",
- "
51
\n",
- "
Texas Rangers
\n",
- "
2001
\n",
- "
\n",
- " \n",
- "
\n",
- "
947 rows × 4 columns
\n",
- "
"
- ],
- "text/plain": [
- " tomatoes_rating tomatoes_votes title year\n",
- "0 97 444 Black Panther 2018\n",
- "1 97 394 Mad Max: Fury Road 2015\n",
- "2 93 410 Wonder Woman 2017\n",
- "3 99 118 Metropolis 1927\n",
- "4 97 308 Coco 2017\n",
- "... ... ... ... ...\n",
- "1585 15 97 Priest 2011\n",
- "1586 14 103 American Outlaws 2001\n",
- "1587 15 54 September Dawn 2007\n",
- "1588 12 147 Jonah Hex 2010\n",
- "1589 2 51 Texas Rangers 2001\n",
- "\n",
- "[947 rows x 4 columns]"
- ]
- },
- "execution_count": 42,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "rotten_tomatoes_beta = (rotten_tomatoes_nodup\n",
- " .assign(\n",
- " title=rotten_tomatoes_nodup[\"Title\"].str.slice(0, -7), \n",
- " year=rotten_tomatoes_nodup[\"Title\"].str.slice(-5, -1).astype(int)\n",
- " )\n",
- " .rename({\n",
- " \"RatingTomatometer\": \"tomatoes_rating\",\n",
- " \"No. of Reviews\": \"tomatoes_votes\",\n",
- " }, axis=\"columns\")\n",
- " .drop([\"Title\"], axis=\"columns\")\n",
- ")\n",
- "rotten_tomatoes_beta"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Závorková odysea nekončí, někdo nám proaktivně do závorek nacpal i originální název naanglickojazyčných filmů. Pojďme se o tom přesvědčit pomocí metody [`.str.contains`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.contains.html) (protože tato metoda ve výchozím stavu používá pro vyhledávání regulární výrazy, které jsme se zatím nenaučili používat, musíme jí to explicitně zakázat argumentem `regex=False`):"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 43,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
\n",
- "\n",
- "
\n",
- " \n",
- "
\n",
- "
\n",
- "
tomatoes_rating
\n",
- "
tomatoes_votes
\n",
- "
title
\n",
- "
year
\n",
- "
\n",
- " \n",
- " \n",
- "
\n",
- "
15
\n",
- "
100
\n",
- "
58
\n",
- "
Seven Samurai (Shichinin no Samurai)
\n",
- "
1956
\n",
- "
\n",
- "
\n",
- "
51
\n",
- "
98
\n",
- "
46
\n",
- "
Aguirre, the Wrath of God (Aguirre, der Zorn G...
\n",
- "
1972
\n",
- "
\n",
- "
\n",
- "
61
\n",
- "
97
\n",
- "
71
\n",
- "
Ghostbusters (1984 Original)
\n",
- "
1984
\n",
- "
\n",
- "
\n",
- "
69
\n",
- "
98
\n",
- "
47
\n",
- "
A Fistful of Dollars (Per un Pugno di Dollari)
\n",
- "
1964
\n",
- "
\n",
- "
\n",
- "
99
\n",
- "
96
\n",
- "
139
\n",
- "
Embrace Of The Serpent (El Abrazo De La Serpie...
\n",
- "
2016
\n",
- "
\n",
- "
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
...
\n",
- "
\n",
- "
\n",
- "
1368
\n",
- "
97
\n",
- "
59
\n",
- "
To Be and to Have (Etre et Avoir)
\n",
- "
2003
\n",
- "
\n",
- "
\n",
- "
1457
\n",
- "
43
\n",
- "
82
\n",
- "
Goal! The Dream Begins (Goal!: The Impossible ...
\n",
- "
2005
\n",
- "
\n",
- "
\n",
- "
1502
\n",
- "
71
\n",
- "
52
\n",
- "
Only Human (Seres queridos)
\n",
- "
2006
\n",
- "
\n",
- "
\n",
- "
1547
\n",
- "
83
\n",
- "
64
\n",
- "
The Good, the Bad, the Weird (Joheun-nom, Nabb...
\n",
- "
2010
\n",
- "
\n",
- "
\n",
- "
1559
\n",
- "
74
\n",
- "
62
\n",
- "
Fah talai jone (Tears of the Black Tiger)
\n",
- "
2007
\n",
- "
\n",
- " \n",
- "
\n",
- "
66 rows × 4 columns
\n",
- "
"
- ],
- "text/plain": [
- " tomatoes_rating tomatoes_votes \\\n",
- "15 100 58 \n",
- "51 98 46 \n",
- "61 97 71 \n",
- "69 98 47 \n",
- "99 96 139 \n",
- "... ... ... \n",
- "1368 97 59 \n",
- "1457 43 82 \n",
- "1502 71 52 \n",
- "1547 83 64 \n",
- "1559 74 62 \n",
- "\n",
- " title year \n",
- "15 Seven Samurai (Shichinin no Samurai) 1956 \n",
- "51 Aguirre, the Wrath of God (Aguirre, der Zorn G... 1972 \n",
- "61 Ghostbusters (1984 Original) 1984 \n",
- "69 A Fistful of Dollars (Per un Pugno di Dollari) 1964 \n",
- "99 Embrace Of The Serpent (El Abrazo De La Serpie... 2016 \n",
- "... ... ... \n",
- "1368 To Be and to Have (Etre et Avoir) 2003 \n",
- "1457 Goal! The Dream Begins (Goal!: The Impossible ... 2005 \n",
- "1502 Only Human (Seres queridos) 2006 \n",
- "1547 The Good, the Bad, the Weird (Joheun-nom, Nabb... 2010 \n",
- "1559 Fah talai jone (Tears of the Black Tiger) 2007 \n",
- "\n",
- "[66 rows x 4 columns]"
- ]
- },
- "execution_count": 43,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "rotten_tomatoes_beta[rotten_tomatoes_beta[\"title\"].str.contains(\")\", regex=False)]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "V rámci zjednodušení proto ještě odstraníme všechny takové závorky. K tomu pomůže funkce [`.str.rsplit`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.rsplit.html), která rozdělí zprava řetězec na několik částí podle oddělovače a vloží je do seznamu - my za ten oddělovač zvolíme levou závorku `\"(\"`, omezíme počet částí na jednu až dvě (`n=1`):"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 44,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "41 [Marvel's The Avengers]\n",
- "61 [Ghostbusters , 1984 Original)]\n",
- "81 [Mad Max 2: The Road Warrior]\n",
- "Name: title, dtype: object"
- ]
- },
- "execution_count": 44,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "split_title = (\n",
- " rotten_tomatoes_beta[\"title\"]\n",
- " .str.rsplit(\"(\", n=1)\n",
- ")\n",
- "split_title.loc[[41, 61, 81]] # Některé seznamy obsahují jeden prvek, jiné dva"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "A jak teď vybrat první prvek z každého seznamu?\n",
- "\n",
- "💡 Metoda [`apply`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.apply.html) umožňuje použít libovolnou transformaci (definovanou jako funkci) na každý řádek v tabulce či hodnotu v `Series`. Obvykle se bez ní obejdeme a měli bychom (proto se jí tolik speciálně nevěnujeme), protože není příliš výpočetně efektivní. Tady nám ale usnadní pochopení, co se vlastně dělá, t.j. vybírá první prvek nějakého seznamu:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 45,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
"
]
@@ -7936,7 +1896,7 @@
},
{
"cell_type": "code",
- "execution_count": 72,
+ "execution_count": 26,
"metadata": {},
"outputs": [
{
@@ -7955,7 +1915,7 @@
""
]
},
- "execution_count": 72,
+ "execution_count": 26,
"metadata": {},
"output_type": "execute_result"
},
@@ -8008,7 +1968,7 @@
},
{
"cell_type": "code",
- "execution_count": 73,
+ "execution_count": 27,
"metadata": {},
"outputs": [
{
@@ -8038,7 +1998,7 @@
},
{
"cell_type": "code",
- "execution_count": 74,
+ "execution_count": 28,
"metadata": {},
"outputs": [
{
@@ -8111,7 +2071,7 @@
},
{
"cell_type": "code",
- "execution_count": 76,
+ "execution_count": 30,
"metadata": {},
"outputs": [
{
diff --git a/lessons/pydata/pandas_correlations/movies_complete.csv.gz b/lessons/pydata/pandas_correlations/movies_complete.csv.gz
new file mode 100644
index 0000000..589ffc3
Binary files /dev/null and b/lessons/pydata/pandas_correlations/movies_complete.csv.gz differ
diff --git a/lessons/pydata/pandas_correlations/movies_with_rating.csv.gz b/lessons/pydata/pandas_correlations/movies_with_rating.csv.gz
new file mode 100644
index 0000000..cfdb7eb
Binary files /dev/null and b/lessons/pydata/pandas_correlations/movies_with_rating.csv.gz differ
diff --git a/lessons/pydata/pandas_correlations/boxoffice_march_2019.csv.gz b/lessons/pydata/pandas_joins/boxoffice_march_2019.csv.gz
similarity index 100%
rename from lessons/pydata/pandas_correlations/boxoffice_march_2019.csv.gz
rename to lessons/pydata/pandas_joins/boxoffice_march_2019.csv.gz
diff --git a/lessons/pydata/pandas_joins/index.ipynb b/lessons/pydata/pandas_joins/index.ipynb
new file mode 100644
index 0000000..5c3a49d
--- /dev/null
+++ b/lessons/pydata/pandas_joins/index.ipynb
@@ -0,0 +1,6118 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Pandas - spojování tabulek\n",
+ "\n",
+ "Tato lekce se nese ve znamení mnohosti a propojování - naučíš se pracovat s více tabulkami najednou. Při tom společně projdeme (ne poprvé a ne naposledy) čištění reálných datových sad."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# Importy jako obvykle\n",
+ "import pandas as pd"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "toc-hr-collapsed": false
+ },
+ "source": [
+ "## Spojování tabulek\n",
+ "\n",
+ "V lekci, kde jsme zpracovávali data o počasí, jsme ti ukázali, že je pomocí funkce `concat` možné slepit dohromady několik objektů `DataFrame` či `Series`, pokud mají \"kompatibilní\" index. Nyní se na problematiku podíváme trochu blíže a ukážeme si, jak spojovat tabulky na základě různých sloupců, a co dělat, když řádky z jedné tabulky nepasují přesně na tabulku druhou.\n",
+ "\n",
+ "Obecně pro spojování `pandas` nabízí tři funkce / metody, z nichž každá má svoje typické využití (možnostmi se ovšem překrývají):\n",
+ "\n",
+ "- [`concat`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.concat.html) je univerzální funkce pro slepování dvou či více tabulek / sloupců - pod sebe, vedle sebe, s přihlédnutím k indexům i bez něj. \n",
+ "- [`merge`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.merge.html) je univerzální funkce pro spojování tabulek na základě vazby mezi indexy nebo sloupci.\n",
+ "- [`join`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.join.html) (metoda) zjednodušuje práci, když chceš spojit dvě tabulky na základě indexu.\n",
+ "\n",
+ "Detailní rozbor toho, co která umí, najdeš v [dokumentaci](https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html). My si je také postupně ukážeme."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Jednoduché skládání"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### Pod sebou\n",
+ "\n",
+ "To je asi ten nejjednodušší případ - máme dva objekty `Series` nebo dva kusy tabulky se stejnými sloupci a chceme je spojit pod sebou. Na to se používá funkce [`concat`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.concat.html):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "a = pd.Series([\"jedna\", \"dvě\", \"tři\"])\n",
+ "b = pd.Series([\"čtyři\", \"pět\", \"šest\"])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0 jedna\n",
+ "1 dvě\n",
+ "2 tři\n",
+ "0 čtyři\n",
+ "1 pět\n",
+ "2 šest\n",
+ "dtype: object"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "pd.concat([a, b])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "💡 Vidíš, že se index opakuje? Vytvořili jsme dvě `Series`, u kterých jsme index neřešili. Jenže `pandas` na rozdíl od nás ano, a tak poslušně oba indexy spojil, i za cenu duplicitních hodnot. Za cenu použití dodatečného argumentu `ignore_index=True` se tomu lze vyhnout, což si ukážeme na příklady spojování dvou tabulek o stejných sloupcích:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0 jedna\n",
+ "1 dvě\n",
+ "2 tři\n",
+ "3 jedna\n",
+ "4 dvě\n",
+ "5 tři\n",
+ "6 jedna\n",
+ "7 dvě\n",
+ "8 tři\n",
+ "9 jedna\n",
+ "10 dvě\n",
+ "11 tři\n",
+ "12 jedna\n",
+ "13 dvě\n",
+ "14 tři\n",
+ "dtype: object"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "pd.concat([a, a, a, a, a], ignore_index=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### Vedle sebe\n",
+ "\n",
+ "Toto asi použijete zřídka, ale když chceme \"lepit\" doprava (třeba deset `Series`), stačí přidat nám dobře známý argument `axis`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
0
\n",
+ "
1
\n",
+ "
2
\n",
+ "
3
\n",
+ "
4
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
0
\n",
+ "
jedna
\n",
+ "
jedna
\n",
+ "
jedna
\n",
+ "
jedna
\n",
+ "
jedna
\n",
+ "
\n",
+ "
\n",
+ "
1
\n",
+ "
dvě
\n",
+ "
dvě
\n",
+ "
dvě
\n",
+ "
dvě
\n",
+ "
dvě
\n",
+ "
\n",
+ "
\n",
+ "
2
\n",
+ "
tři
\n",
+ "
tři
\n",
+ "
tři
\n",
+ "
tři
\n",
+ "
tři
\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " 0 1 2 3 4\n",
+ "0 jedna jedna jedna jedna jedna\n",
+ "1 dvě dvě dvě dvě dvě\n",
+ "2 tři tři tři tři tři"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "pd.concat([a, a, a, a, a], axis=\"columns\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "**Příklad:** Jak co nejrychleji \"nakreslit prázdnou šachovnici\" (obě slova jsou v uvozovkách)?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
A
\n",
+ "
B
\n",
+ "
C
\n",
+ "
D
\n",
+ "
E
\n",
+ "
F
\n",
+ "
G
\n",
+ "
H
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
8
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
\n",
+ "
\n",
+ "
7
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
\n",
+ "
\n",
+ "
6
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
\n",
+ "
\n",
+ "
5
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
\n",
+ "
\n",
+ "
4
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
\n",
+ "
\n",
+ "
3
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
\n",
+ "
\n",
+ "
2
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
\n",
+ "
\n",
+ "
1
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
⬛
\n",
+ "
⬜
\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " A B C D E F G H\n",
+ "8 ⬜ ⬛ ⬜ ⬛ ⬜ ⬛ ⬜ ⬛\n",
+ "7 ⬛ ⬜ ⬛ ⬜ ⬛ ⬜ ⬛ ⬜\n",
+ "6 ⬜ ⬛ ⬜ ⬛ ⬜ ⬛ ⬜ ⬛\n",
+ "5 ⬛ ⬜ ⬛ ⬜ ⬛ ⬜ ⬛ ⬜\n",
+ "4 ⬜ ⬛ ⬜ ⬛ ⬜ ⬛ ⬜ ⬛\n",
+ "3 ⬛ ⬜ ⬛ ⬜ ⬛ ⬜ ⬛ ⬜\n",
+ "2 ⬜ ⬛ ⬜ ⬛ ⬜ ⬛ ⬜ ⬛\n",
+ "1 ⬛ ⬜ ⬛ ⬜ ⬛ ⬜ ⬛ ⬜"
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "sachy = pd.concat(\n",
+ " [\n",
+ " pd.concat( \n",
+ " [pd.DataFrame([[\"⬜\", \"⬛\"], [\"⬛\", \"⬜\"]])] * 4,\n",
+ " axis=1)\n",
+ " ] * 4\n",
+ ")\n",
+ "sachy.index = list(range(8, 0, -1))\n",
+ "sachy.columns = list(\"ABCDEFGH\")\n",
+ "sachy"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Spojování různorodých tabulek"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "🎦 Pro spojování heterogenních dat (v datové hantýrce \"joinování\") sáhneme po trochu komplexnějších filmových datech..."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Máme staženo několik souborů, načteme si je (zatím hrubě, \"raw\") - s přihlédnutím k tomu, že první dva nejsou v pravém slova smyslu \"comma-separated\", ale používají k oddělení hodnot tabulátor (tady pomůže argument `sep`). Také zohledníme, že v nich řetězec `\"\\N\"` představuje chybějící hodnoty (pomůže argument `na_values`):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "imdb_titles_raw = pd.read_csv(\"title.basics.tsv.gz\", sep=\"\\t\", na_values=\"\\\\N\")\n",
+ "imdb_ratings_raw = pd.read_csv(\"title.ratings.tsv.gz\", sep=\"\\t\", na_values=\"\\\\N\")\n",
+ "boxoffice_raw = pd.read_csv(\"boxoffice_march_2019.csv.gz\")\n",
+ "rotten_tomatoes_raw = pd.read_csv(\"rotten_tomatoes_top_movies_2019-01-15.csv\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Co který soubor obsahuje? \n",
+ "\n",
+ "- První dva soubory obsahují volně dostupná (byť \"jen\" pro nekomerční použití) data o filmech z IMDb (Internet Movie Database). My jsme si zvolili obecné informace a uživatelská (číselná) hodnocení. Detailní popis souborů, stejně jako odkazy na další soubory, najdeš na https://www.imdb.com/interfaces/. Z důvodů paměťové náročnosti jsme datovou sadu ořezali o epizody seriálů, protože nás nebudou zajímat a s trochu štěstí přežijeme i na počítačích s menší operační pamětí.\n",
+ "\n",
+ "- Soubor `boxoffice_march_2019.csv.gz` obsahuje informace o výdělcích jednotlivých filmů. Pochází z ukázkového datasetu pro soutěž \"TMDB Box Office Prediction\" na serveru Kaggle: https://www.kaggle.com/c/tmdb-box-office-prediction/data\n",
+ "\n",
+ "- Soubor `rotten_tomatoes_top_movies_2019-01-15.csv` obsahuje procentuální hodnocení filmů ze serveru Rotten Tomatoes, které se počítá jako podíl pozitivních hodnoceních od filmových kritiku (je to tedy jiný princip než na IMDb). Staženo z: https://data.world/prasert/rotten-tomatoes-top-movies-by-genre\n",
+ "\n",
+ "Pojďme se podívat na nedostatky těchto souborů a postupně je skládat dohromady. Zajímalo by nás (a snad i tebe!), jak souvisí hodnocení s komerční úspěšností filmu, jak se liší hodnocení rotten tomatoes od těch na IMDb."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
tconst
\n",
+ "
titleType
\n",
+ "
primaryTitle
\n",
+ "
originalTitle
\n",
+ "
isAdult
\n",
+ "
startYear
\n",
+ "
endYear
\n",
+ "
runtimeMinutes
\n",
+ "
genres
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
0
\n",
+ "
tt0000001
\n",
+ "
short
\n",
+ "
Carmencita
\n",
+ "
Carmencita
\n",
+ "
0
\n",
+ "
1894.0
\n",
+ "
NaN
\n",
+ "
1.0
\n",
+ "
Documentary,Short
\n",
+ "
\n",
+ "
\n",
+ "
1
\n",
+ "
tt0000002
\n",
+ "
short
\n",
+ "
Le clown et ses chiens
\n",
+ "
Le clown et ses chiens
\n",
+ "
0
\n",
+ "
1892.0
\n",
+ "
NaN
\n",
+ "
5.0
\n",
+ "
Animation,Short
\n",
+ "
\n",
+ "
\n",
+ "
2
\n",
+ "
tt0000003
\n",
+ "
short
\n",
+ "
Pauvre Pierrot
\n",
+ "
Pauvre Pierrot
\n",
+ "
0
\n",
+ "
1892.0
\n",
+ "
NaN
\n",
+ "
4.0
\n",
+ "
Animation,Comedy,Romance
\n",
+ "
\n",
+ "
\n",
+ "
3
\n",
+ "
tt0000004
\n",
+ "
short
\n",
+ "
Un bon bock
\n",
+ "
Un bon bock
\n",
+ "
0
\n",
+ "
1892.0
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
Animation,Short
\n",
+ "
\n",
+ "
\n",
+ "
4
\n",
+ "
tt0000005
\n",
+ "
short
\n",
+ "
Blacksmith Scene
\n",
+ "
Blacksmith Scene
\n",
+ "
0
\n",
+ "
1893.0
\n",
+ "
NaN
\n",
+ "
1.0
\n",
+ "
Comedy,Short
\n",
+ "
\n",
+ "
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
\n",
+ "
\n",
+ "
1783511
\n",
+ "
tt9916734
\n",
+ "
video
\n",
+ "
Manca: Peleo
\n",
+ "
Manca: Peleo
\n",
+ "
0
\n",
+ "
2018.0
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
Music,Short
\n",
+ "
\n",
+ "
\n",
+ "
1783512
\n",
+ "
tt9916754
\n",
+ "
movie
\n",
+ "
Chico Albuquerque - Revelações
\n",
+ "
Chico Albuquerque - Revelações
\n",
+ "
0
\n",
+ "
2013.0
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
Documentary
\n",
+ "
\n",
+ "
\n",
+ "
1783513
\n",
+ "
tt9916756
\n",
+ "
short
\n",
+ "
Pretty Pretty Black Girl
\n",
+ "
Pretty Pretty Black Girl
\n",
+ "
0
\n",
+ "
2019.0
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
Short
\n",
+ "
\n",
+ "
\n",
+ "
1783514
\n",
+ "
tt9916764
\n",
+ "
short
\n",
+ "
38
\n",
+ "
38
\n",
+ "
0
\n",
+ "
2018.0
\n",
+ "
NaN
\n",
+ "
NaN
\n",
+ "
Short
\n",
+ "
\n",
+ "
\n",
+ "
1783515
\n",
+ "
tt9916856
\n",
+ "
short
\n",
+ "
The Wind
\n",
+ "
The Wind
\n",
+ "
0
\n",
+ "
2015.0
\n",
+ "
NaN
\n",
+ "
27.0
\n",
+ "
Short
\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
1783516 rows × 9 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " tconst titleType primaryTitle \\\n",
+ "0 tt0000001 short Carmencita \n",
+ "1 tt0000002 short Le clown et ses chiens \n",
+ "2 tt0000003 short Pauvre Pierrot \n",
+ "3 tt0000004 short Un bon bock \n",
+ "4 tt0000005 short Blacksmith Scene \n",
+ "... ... ... ... \n",
+ "1783511 tt9916734 video Manca: Peleo \n",
+ "1783512 tt9916754 movie Chico Albuquerque - Revelações \n",
+ "1783513 tt9916756 short Pretty Pretty Black Girl \n",
+ "1783514 tt9916764 short 38 \n",
+ "1783515 tt9916856 short The Wind \n",
+ "\n",
+ " originalTitle isAdult startYear endYear \\\n",
+ "0 Carmencita 0 1894.0 NaN \n",
+ "1 Le clown et ses chiens 0 1892.0 NaN \n",
+ "2 Pauvre Pierrot 0 1892.0 NaN \n",
+ "3 Un bon bock 0 1892.0 NaN \n",
+ "4 Blacksmith Scene 0 1893.0 NaN \n",
+ "... ... ... ... ... \n",
+ "1783511 Manca: Peleo 0 2018.0 NaN \n",
+ "1783512 Chico Albuquerque - Revelações 0 2013.0 NaN \n",
+ "1783513 Pretty Pretty Black Girl 0 2019.0 NaN \n",
+ "1783514 38 0 2018.0 NaN \n",
+ "1783515 The Wind 0 2015.0 NaN \n",
+ "\n",
+ " runtimeMinutes genres \n",
+ "0 1.0 Documentary,Short \n",
+ "1 5.0 Animation,Short \n",
+ "2 4.0 Animation,Comedy,Romance \n",
+ "3 NaN Animation,Short \n",
+ "4 1.0 Comedy,Short \n",
+ "... ... ... \n",
+ "1783511 NaN Music,Short \n",
+ "1783512 NaN Documentary \n",
+ "1783513 NaN Short \n",
+ "1783514 NaN Short \n",
+ "1783515 27.0 Short \n",
+ "\n",
+ "[1783516 rows x 9 columns]"
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "imdb_titles_raw"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "648.8971881866455"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Kolik tabulka zabírá megabajtů paměti? (1 MB = 2**20 bajtů)\n",
+ "imdb_titles_raw.memory_usage(deep=True).sum() / 2**20 "
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Jistě budeme chtít převést sloupce na správné typy. Jaké jsou v základu?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "tconst object\n",
+ "titleType object\n",
+ "primaryTitle object\n",
+ "originalTitle object\n",
+ "isAdult int64\n",
+ "startYear float64\n",
+ "endYear float64\n",
+ "runtimeMinutes float64\n",
+ "genres object\n",
+ "dtype: object"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "imdb_titles_raw.dtypes"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Na co budeme převádět?\n",
+ "\n",
+ "- `tconst` je řetězec, který posléze použijeme jako index, protože představuje unikátní identifikátor v databázi IMDb.\n",
+ "- `titleType`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "titleType\n",
+ "short 676930\n",
+ "movie 514654\n",
+ "video 227582\n",
+ "tvSeries 162781\n",
+ "tvMovie 126507\n",
+ "tvMiniSeries 25574\n",
+ "videoGame 23310\n",
+ "tvSpecial 17007\n",
+ "tvShort 9171\n",
+ "Name: count, dtype: int64"
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "imdb_titles_raw[\"titleType\"].value_counts()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Jen devět různých hodnot ve skoro 2 milionech řádků? To je ideální kandidát na převedení na typ `\"category\"`.\n",
+ "\n",
+ "- `primaryTitle` a `originalTitle` vypadají jako obyčejné řetězce (pokud možno anglický a pokud možno původní název)\n",
+ "- `isAdult` určuje, zda se jedná o dílo pro dospělé. Tento sloupec bychom nejspíše měli převést na `bool`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "isAdult\n",
+ "0 1692292\n",
+ "1 91224\n",
+ "Name: count, dtype: int64"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "imdb_titles_raw[\"isAdult\"].value_counts()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "- `startYear` a `endYear` obsahují roky, t.j. celá čísla, ovšem kvůli chybějícím hodnotám je pro ně zvolen typ `float64`. V `pandas` raději zvolíme tzv. \"nullable integer\", který se zapisuje s velkým \"I\". Když nevíš, jaký podtyp konkrétně, sáhni po `Int64`.\n",
+ "- totéž platí pro `runtimeMinutes`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "startYear 2115.0\n",
+ "endYear 2027.0\n",
+ "runtimeMinutes 125156.0\n",
+ "dtype: float64"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "imdb_titles_raw[[\"startYear\", \"endYear\", \"runtimeMinutes\"]].max()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Mimochodem všimli jste si, že máme díla z budoucnosti (rok 2115)?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "startYear\n",
+ "2020.0 340\n",
+ "2021.0 36\n",
+ "2022.0 14\n",
+ "2023.0 1\n",
+ "2024.0 2\n",
+ "2025.0 1\n",
+ "2115.0 1\n",
+ "Name: count, dtype: int64"
+ ]
+ },
+ "execution_count": 14,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAGsCAYAAAAhYYazAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAqCElEQVR4nO3de1zVdZ7H8fcB5SApqCHghcR7FxXJC8OkTU4kKg83c2bXtUxjtFnLGpKspAuMNSOaydqumpPrJXe2vOya06RihprrxOaKUNl6N8MLoKZyFAuQ89s/fHjqBCocjhz4+no+Hufx6HzP9/c7n9/3ceS8+57v7/ezWZZlCQAAwBB+vi4AAADAmwg3AADAKIQbAABgFMINAAAwCuEGAAAYhXADAACMQrgBAABGIdwAAACjEG4AAIBRCDcAAMAoN3W42bZtm0aMGKF27drJZrNp7dq1td6HZVl644031L17d9ntdrVv315//OMfvV8sAACokSa+LsCXSktLFR0drd/85jcaNWqUR/tITk7WRx99pDfeeEO9evXSmTNndObMGS9XCgAAasrGjTMvs9lsev/99zVy5EhXW1lZmV566SW99957OnfunHr27KlZs2bpvvvukyTt2bNHvXv31u7du9WjRw/fFA4AANzc1D9LXc9TTz2lnJwcrVixQl988YX+/u//XkOHDtWBAwckSX/961/VuXNnffjhh+rUqZOioqI0ceJEZm4AAPAhws1VFBQUaOnSpVq9erUGDRqkLl26aOrUqRo4cKCWLl0qSTp8+LC++eYbrV69WsuXL9eyZcuUm5urX//61z6uHgCAm9dNvebmWr788ktVVlaqe/fubu1lZWW69dZbJUlOp1NlZWVavny5q9/ixYvVt29f7du3j5+qAADwAcLNVVy4cEH+/v7Kzc2Vv7+/22vNmzeXJLVt21ZNmjRxC0B33HGHpMszP4QbAADqH+HmKmJiYlRZWamTJ09q0KBB1fa55557dOnSJR06dEhdunSRJO3fv1+S1LFjx3qrFQAA/OCmPlvqwoULOnjwoKTLYSYzM1ODBw9W69atddttt2ns2LH629/+pjlz5igmJkanTp1Sdna2evfurcTERDmdTvXv31/NmzfX3Llz5XQ6NXnyZAUHB+ujjz7y8dEBAHBzuqnDzdatWzV48OAq7ePHj9eyZctUUVGhP/zh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",
+ "text/plain": [
+ "
"
+ ],
+ "text/plain": [
+ " title \\\n",
+ "tconst \n",
+ "tt0000009 Miss Jerry \n",
+ "tt0000147 The Corbett-Fitzsimmons Fight \n",
+ "tt0000335 Soldiers of the Cross \n",
+ "tt0000502 Bohemios \n",
+ "tt0000574 The Story of the Kelly Gang \n",
+ "... ... \n",
+ "tt9916622 Rodolpho Teóphilo - O Legado de um Pioneiro \n",
+ "tt9916680 De la ilusión al desconcierto: cine colombiano... \n",
+ "tt9916706 Dankyavar Danka \n",
+ "tt9916730 6 Gunn \n",
+ "tt9916754 Chico Albuquerque - Revelações \n",
+ "\n",
+ " original_title is_adult year \\\n",
+ "tconst \n",
+ "tt0000009 Miss Jerry False 1894 \n",
+ "tt0000147 The Corbett-Fitzsimmons Fight False 1897 \n",
+ "tt0000335 Soldiers of the Cross False 1900 \n",
+ "tt0000502 Bohemios False 1905 \n",
+ "tt0000574 The Story of the Kelly Gang False 1906 \n",
+ "... ... ... ... \n",
+ "tt9916622 Rodolpho Teóphilo - O Legado de um Pioneiro False 2015 \n",
+ "tt9916680 De la ilusión al desconcierto: cine colombiano... False 2007 \n",
+ "tt9916706 Dankyavar Danka False 2013 \n",
+ "tt9916730 6 Gunn False 2017 \n",
+ "tt9916754 Chico Albuquerque - Revelações False 2013 \n",
+ "\n",
+ " length genres imdb_rating imdb_votes \n",
+ "tconst \n",
+ "tt0000009 45 Romance 5.5 77.0 \n",
+ "tt0000147 20 Documentary,News,Sport 5.2 289.0 \n",
+ "tt0000335 Biography,Drama 6.3 39.0 \n",
+ "tt0000502 100 NaN NaN NaN \n",
+ "tt0000574 70 Biography,Crime,Drama 6.2 505.0 \n",
+ "... ... ... ... ... \n",
+ "tt9916622 Documentary NaN NaN \n",
+ "tt9916680 100 Documentary NaN NaN \n",
+ "tt9916706 Comedy NaN NaN \n",
+ "tt9916730 116 NaN NaN NaN \n",
+ "tt9916754 Documentary NaN NaN \n",
+ "\n",
+ "[514654 rows x 8 columns]"
+ ]
+ },
+ "execution_count": 23,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "movies.join(ratings)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "K tabulce se nenápadně přidaly dva sloupce z tabulky `ratings`, a to takovým způsobem, že se porovnaly hodnoty indexu (tedy `tconst`) a spárovaly se ty části řádku, kde se tento index shoduje.\n",
+ "\n",
+ "💡 Uvědom si (ačkoliv z volání funkcí v `pandas` to není úplně zřejmé), že se tady děje něco fundamentálně odlišného od \"nalepení doprava\" - tabulky tu nejsou chápány jako čtverečky, které jde skládat jako lego, nýbrž jako zdroj údajů o jednotlivých objektech, které je potřeba spojit sémanticky.\n",
+ "\n",
+ "Jak ale vidíš, tabulka obsahuje spoustu řádků, kde ve sloupcích s hodnocením chybí hodnoty (respektive nachází se `NaN`). To vychází ze způsobu, jakým metoda `join` ve výchozím nastavení \"joinuje\" - použije všechny řádky z levé tabulky bez ohledu na to, jestli jim odpovídá nějaký protějšek v tabulce pravé. Naštěstí lze pomocí argumentu `how` specifikovat i jiné způsoby spojování:\n",
+ "\n",
+ "- `left` (výchozí pro metodu `join`) - vezmou se všechny prvky z levé tabulky a jim odpovídající prvky z pravé tabulky (kde nejsou, doplní se `NaN`)\n",
+ "- `right` - vezmou se všechny prvky z pravé tabulky a jim odpovídající prvky z levé tabulky (kde nejsou, doplní se `NaN`)\n",
+ "- `inner` (výchozí pro funkci `merge`) - vezmou se jen ty prvky, které jsou v levé i pravé tabulce.\n",
+ "- `outer` (výchozí pro funkci `concat`) - vezmou se všechny prvky, z levé i pravé tabulky, kde něco chybí, doplní se `NaN`.\n",
+ "\n",
+ "V podobě Vennově diagramu, kde kruhy představují množiny řádků v obou zdrojových tabulkách a modrou barvou jsou zvýrazněny řádky v tabulce cílové:\n",
+ "\n",
+ "![Typy joinů](static/joins.svg)\n",
+ "\n",
+ "*Obrázek adaptován z https://upload.wikimedia.org/wikipedia/commons/9/9d/SQL_Joins.svg (autor: Arbeck)*\n",
+ "\n",
+ "💡 Až budeme probírat databáze, tyto čtyři typu joinů se nám znovu vynoří.\n",
+ "\n",
+ "Následující výpis ukáže, kolik řádků bychom dostali při použití různých hodnot `how`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "movies.join(ratings, how=\"left\"): 514654 řádků.\n",
+ "movies.join(ratings, how=\"right\"): 923696 řádků.\n",
+ "movies.join(ratings, how=\"inner\"): 232496 řádků.\n",
+ "movies.join(ratings, how=\"outer\"): 1205854 řádků.\n"
+ ]
+ }
+ ],
+ "source": [
+ "for how in [\"left\", \"right\", \"inner\", \"outer\"]:\n",
+ " print(f\"movies.join(ratings, how=\\\"{how}\\\"):\", movies.join(ratings, how=how).shape[0], \"řádků.\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "A teď tedy ty tři alternativy:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
title
\n",
+ "
original_title
\n",
+ "
is_adult
\n",
+ "
year
\n",
+ "
length
\n",
+ "
genres
\n",
+ "
imdb_rating
\n",
+ "
imdb_votes
\n",
+ "
\n",
+ "
\n",
+ "
tconst
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
tt0000009
\n",
+ "
Miss Jerry
\n",
+ "
Miss Jerry
\n",
+ "
False
\n",
+ "
1894
\n",
+ "
45
\n",
+ "
Romance
\n",
+ "
5.5
\n",
+ "
77
\n",
+ "
\n",
+ "
\n",
+ "
tt0000147
\n",
+ "
The Corbett-Fitzsimmons Fight
\n",
+ "
The Corbett-Fitzsimmons Fight
\n",
+ "
False
\n",
+ "
1897
\n",
+ "
20
\n",
+ "
Documentary,News,Sport
\n",
+ "
5.2
\n",
+ "
289
\n",
+ "
\n",
+ "
\n",
+ "
tt0000335
\n",
+ "
Soldiers of the Cross
\n",
+ "
Soldiers of the Cross
\n",
+ "
False
\n",
+ "
1900
\n",
+ "
<NA>
\n",
+ "
Biography,Drama
\n",
+ "
6.3
\n",
+ "
39
\n",
+ "
\n",
+ "
\n",
+ "
tt0000574
\n",
+ "
The Story of the Kelly Gang
\n",
+ "
The Story of the Kelly Gang
\n",
+ "
False
\n",
+ "
1906
\n",
+ "
70
\n",
+ "
Biography,Crime,Drama
\n",
+ "
6.2
\n",
+ "
505
\n",
+ "
\n",
+ "
\n",
+ "
tt0000615
\n",
+ "
Robbery Under Arms
\n",
+ "
Robbery Under Arms
\n",
+ "
False
\n",
+ "
1907
\n",
+ "
<NA>
\n",
+ "
Drama
\n",
+ "
4.8
\n",
+ "
14
\n",
+ "
\n",
+ "
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
\n",
+ "
\n",
+ "
tt9910930
\n",
+ "
Jeg ser deg
\n",
+ "
Jeg ser deg
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
75
\n",
+ "
Crime,Documentary
\n",
+ "
4.6
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
tt9911774
\n",
+ "
Padmavyuhathile Abhimanyu
\n",
+ "
Padmavyuhathile Abhimanyu
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
130
\n",
+ "
Drama
\n",
+ "
8.5
\n",
+ "
363
\n",
+ "
\n",
+ "
\n",
+ "
tt9913056
\n",
+ "
Swarm Season
\n",
+ "
Swarm Season
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
86
\n",
+ "
Documentary
\n",
+ "
6.2
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
tt9913084
\n",
+ "
Diabolik sono io
\n",
+ "
Diabolik sono io
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
75
\n",
+ "
Documentary
\n",
+ "
6.2
\n",
+ "
6
\n",
+ "
\n",
+ "
\n",
+ "
tt9914286
\n",
+ "
Sokagin Çocuklari
\n",
+ "
Sokagin Çocuklari
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
98
\n",
+ "
Drama,Family
\n",
+ "
9.8
\n",
+ "
72
\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
232496 rows × 8 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " title original_title \\\n",
+ "tconst \n",
+ "tt0000009 Miss Jerry Miss Jerry \n",
+ "tt0000147 The Corbett-Fitzsimmons Fight The Corbett-Fitzsimmons Fight \n",
+ "tt0000335 Soldiers of the Cross Soldiers of the Cross \n",
+ "tt0000574 The Story of the Kelly Gang The Story of the Kelly Gang \n",
+ "tt0000615 Robbery Under Arms Robbery Under Arms \n",
+ "... ... ... \n",
+ "tt9910930 Jeg ser deg Jeg ser deg \n",
+ "tt9911774 Padmavyuhathile Abhimanyu Padmavyuhathile Abhimanyu \n",
+ "tt9913056 Swarm Season Swarm Season \n",
+ "tt9913084 Diabolik sono io Diabolik sono io \n",
+ "tt9914286 Sokagin Çocuklari Sokagin Çocuklari \n",
+ "\n",
+ " is_adult year length genres imdb_rating \\\n",
+ "tconst \n",
+ "tt0000009 False 1894 45 Romance 5.5 \n",
+ "tt0000147 False 1897 20 Documentary,News,Sport 5.2 \n",
+ "tt0000335 False 1900 Biography,Drama 6.3 \n",
+ "tt0000574 False 1906 70 Biography,Crime,Drama 6.2 \n",
+ "tt0000615 False 1907 Drama 4.8 \n",
+ "... ... ... ... ... ... \n",
+ "tt9910930 False 2019 75 Crime,Documentary 4.6 \n",
+ "tt9911774 False 2019 130 Drama 8.5 \n",
+ "tt9913056 False 2019 86 Documentary 6.2 \n",
+ "tt9913084 False 2019 75 Documentary 6.2 \n",
+ "tt9914286 False 2019 98 Drama,Family 9.8 \n",
+ "\n",
+ " imdb_votes \n",
+ "tconst \n",
+ "tt0000009 77 \n",
+ "tt0000147 289 \n",
+ "tt0000335 39 \n",
+ "tt0000574 505 \n",
+ "tt0000615 14 \n",
+ "... ... \n",
+ "tt9910930 5 \n",
+ "tt9911774 363 \n",
+ "tt9913056 5 \n",
+ "tt9913084 6 \n",
+ "tt9914286 72 \n",
+ "\n",
+ "[232496 rows x 8 columns]"
+ ]
+ },
+ "execution_count": 25,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Alternativa 1 (preferovaná)\n",
+ "movies_with_rating = movies.join(ratings, how=\"inner\")\n",
+ "movies_with_rating"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
title
\n",
+ "
original_title
\n",
+ "
is_adult
\n",
+ "
year
\n",
+ "
length
\n",
+ "
genres
\n",
+ "
imdb_rating
\n",
+ "
imdb_votes
\n",
+ "
\n",
+ "
\n",
+ "
tconst
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
tt0000009
\n",
+ "
Miss Jerry
\n",
+ "
Miss Jerry
\n",
+ "
False
\n",
+ "
1894
\n",
+ "
45
\n",
+ "
Romance
\n",
+ "
5.5
\n",
+ "
77
\n",
+ "
\n",
+ "
\n",
+ "
tt0000147
\n",
+ "
The Corbett-Fitzsimmons Fight
\n",
+ "
The Corbett-Fitzsimmons Fight
\n",
+ "
False
\n",
+ "
1897
\n",
+ "
20
\n",
+ "
Documentary,News,Sport
\n",
+ "
5.2
\n",
+ "
289
\n",
+ "
\n",
+ "
\n",
+ "
tt0000335
\n",
+ "
Soldiers of the Cross
\n",
+ "
Soldiers of the Cross
\n",
+ "
False
\n",
+ "
1900
\n",
+ "
<NA>
\n",
+ "
Biography,Drama
\n",
+ "
6.3
\n",
+ "
39
\n",
+ "
\n",
+ "
\n",
+ "
tt0000574
\n",
+ "
The Story of the Kelly Gang
\n",
+ "
The Story of the Kelly Gang
\n",
+ "
False
\n",
+ "
1906
\n",
+ "
70
\n",
+ "
Biography,Crime,Drama
\n",
+ "
6.2
\n",
+ "
505
\n",
+ "
\n",
+ "
\n",
+ "
tt0000615
\n",
+ "
Robbery Under Arms
\n",
+ "
Robbery Under Arms
\n",
+ "
False
\n",
+ "
1907
\n",
+ "
<NA>
\n",
+ "
Drama
\n",
+ "
4.8
\n",
+ "
14
\n",
+ "
\n",
+ "
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
\n",
+ "
\n",
+ "
tt9910930
\n",
+ "
Jeg ser deg
\n",
+ "
Jeg ser deg
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
75
\n",
+ "
Crime,Documentary
\n",
+ "
4.6
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
tt9911774
\n",
+ "
Padmavyuhathile Abhimanyu
\n",
+ "
Padmavyuhathile Abhimanyu
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
130
\n",
+ "
Drama
\n",
+ "
8.5
\n",
+ "
363
\n",
+ "
\n",
+ "
\n",
+ "
tt9913056
\n",
+ "
Swarm Season
\n",
+ "
Swarm Season
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
86
\n",
+ "
Documentary
\n",
+ "
6.2
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
tt9913084
\n",
+ "
Diabolik sono io
\n",
+ "
Diabolik sono io
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
75
\n",
+ "
Documentary
\n",
+ "
6.2
\n",
+ "
6
\n",
+ "
\n",
+ "
\n",
+ "
tt9914286
\n",
+ "
Sokagin Çocuklari
\n",
+ "
Sokagin Çocuklari
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
98
\n",
+ "
Drama,Family
\n",
+ "
9.8
\n",
+ "
72
\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
232496 rows × 8 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " title original_title \\\n",
+ "tconst \n",
+ "tt0000009 Miss Jerry Miss Jerry \n",
+ "tt0000147 The Corbett-Fitzsimmons Fight The Corbett-Fitzsimmons Fight \n",
+ "tt0000335 Soldiers of the Cross Soldiers of the Cross \n",
+ "tt0000574 The Story of the Kelly Gang The Story of the Kelly Gang \n",
+ "tt0000615 Robbery Under Arms Robbery Under Arms \n",
+ "... ... ... \n",
+ "tt9910930 Jeg ser deg Jeg ser deg \n",
+ "tt9911774 Padmavyuhathile Abhimanyu Padmavyuhathile Abhimanyu \n",
+ "tt9913056 Swarm Season Swarm Season \n",
+ "tt9913084 Diabolik sono io Diabolik sono io \n",
+ "tt9914286 Sokagin Çocuklari Sokagin Çocuklari \n",
+ "\n",
+ " is_adult year length genres imdb_rating \\\n",
+ "tconst \n",
+ "tt0000009 False 1894 45 Romance 5.5 \n",
+ "tt0000147 False 1897 20 Documentary,News,Sport 5.2 \n",
+ "tt0000335 False 1900 Biography,Drama 6.3 \n",
+ "tt0000574 False 1906 70 Biography,Crime,Drama 6.2 \n",
+ "tt0000615 False 1907 Drama 4.8 \n",
+ "... ... ... ... ... ... \n",
+ "tt9910930 False 2019 75 Crime,Documentary 4.6 \n",
+ "tt9911774 False 2019 130 Drama 8.5 \n",
+ "tt9913056 False 2019 86 Documentary 6.2 \n",
+ "tt9913084 False 2019 75 Documentary 6.2 \n",
+ "tt9914286 False 2019 98 Drama,Family 9.8 \n",
+ "\n",
+ " imdb_votes \n",
+ "tconst \n",
+ "tt0000009 77 \n",
+ "tt0000147 289 \n",
+ "tt0000335 39 \n",
+ "tt0000574 505 \n",
+ "tt0000615 14 \n",
+ "... ... \n",
+ "tt9910930 5 \n",
+ "tt9911774 363 \n",
+ "tt9913056 5 \n",
+ "tt9913084 6 \n",
+ "tt9914286 72 \n",
+ "\n",
+ "[232496 rows x 8 columns]"
+ ]
+ },
+ "execution_count": 26,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Alternativa 2 (taky dobrá)\n",
+ "pd.merge(movies, ratings, left_index=True, right_index=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
title
\n",
+ "
original_title
\n",
+ "
is_adult
\n",
+ "
year
\n",
+ "
length
\n",
+ "
genres
\n",
+ "
imdb_rating
\n",
+ "
imdb_votes
\n",
+ "
\n",
+ "
\n",
+ "
tconst
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
tt0000009
\n",
+ "
Miss Jerry
\n",
+ "
Miss Jerry
\n",
+ "
False
\n",
+ "
1894
\n",
+ "
45
\n",
+ "
Romance
\n",
+ "
5.5
\n",
+ "
77
\n",
+ "
\n",
+ "
\n",
+ "
tt0000147
\n",
+ "
The Corbett-Fitzsimmons Fight
\n",
+ "
The Corbett-Fitzsimmons Fight
\n",
+ "
False
\n",
+ "
1897
\n",
+ "
20
\n",
+ "
Documentary,News,Sport
\n",
+ "
5.2
\n",
+ "
289
\n",
+ "
\n",
+ "
\n",
+ "
tt0000335
\n",
+ "
Soldiers of the Cross
\n",
+ "
Soldiers of the Cross
\n",
+ "
False
\n",
+ "
1900
\n",
+ "
<NA>
\n",
+ "
Biography,Drama
\n",
+ "
6.3
\n",
+ "
39
\n",
+ "
\n",
+ "
\n",
+ "
tt0000574
\n",
+ "
The Story of the Kelly Gang
\n",
+ "
The Story of the Kelly Gang
\n",
+ "
False
\n",
+ "
1906
\n",
+ "
70
\n",
+ "
Biography,Crime,Drama
\n",
+ "
6.2
\n",
+ "
505
\n",
+ "
\n",
+ "
\n",
+ "
tt0000615
\n",
+ "
Robbery Under Arms
\n",
+ "
Robbery Under Arms
\n",
+ "
False
\n",
+ "
1907
\n",
+ "
<NA>
\n",
+ "
Drama
\n",
+ "
4.8
\n",
+ "
14
\n",
+ "
\n",
+ "
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
\n",
+ "
\n",
+ "
tt9910930
\n",
+ "
Jeg ser deg
\n",
+ "
Jeg ser deg
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
75
\n",
+ "
Crime,Documentary
\n",
+ "
4.6
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
tt9911774
\n",
+ "
Padmavyuhathile Abhimanyu
\n",
+ "
Padmavyuhathile Abhimanyu
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
130
\n",
+ "
Drama
\n",
+ "
8.5
\n",
+ "
363
\n",
+ "
\n",
+ "
\n",
+ "
tt9913056
\n",
+ "
Swarm Season
\n",
+ "
Swarm Season
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
86
\n",
+ "
Documentary
\n",
+ "
6.2
\n",
+ "
5
\n",
+ "
\n",
+ "
\n",
+ "
tt9913084
\n",
+ "
Diabolik sono io
\n",
+ "
Diabolik sono io
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
75
\n",
+ "
Documentary
\n",
+ "
6.2
\n",
+ "
6
\n",
+ "
\n",
+ "
\n",
+ "
tt9914286
\n",
+ "
Sokagin Çocuklari
\n",
+ "
Sokagin Çocuklari
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
98
\n",
+ "
Drama,Family
\n",
+ "
9.8
\n",
+ "
72
\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
232496 rows × 8 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " title original_title \\\n",
+ "tconst \n",
+ "tt0000009 Miss Jerry Miss Jerry \n",
+ "tt0000147 The Corbett-Fitzsimmons Fight The Corbett-Fitzsimmons Fight \n",
+ "tt0000335 Soldiers of the Cross Soldiers of the Cross \n",
+ "tt0000574 The Story of the Kelly Gang The Story of the Kelly Gang \n",
+ "tt0000615 Robbery Under Arms Robbery Under Arms \n",
+ "... ... ... \n",
+ "tt9910930 Jeg ser deg Jeg ser deg \n",
+ "tt9911774 Padmavyuhathile Abhimanyu Padmavyuhathile Abhimanyu \n",
+ "tt9913056 Swarm Season Swarm Season \n",
+ "tt9913084 Diabolik sono io Diabolik sono io \n",
+ "tt9914286 Sokagin Çocuklari Sokagin Çocuklari \n",
+ "\n",
+ " is_adult year length genres imdb_rating \\\n",
+ "tconst \n",
+ "tt0000009 False 1894 45 Romance 5.5 \n",
+ "tt0000147 False 1897 20 Documentary,News,Sport 5.2 \n",
+ "tt0000335 False 1900 Biography,Drama 6.3 \n",
+ "tt0000574 False 1906 70 Biography,Crime,Drama 6.2 \n",
+ "tt0000615 False 1907 Drama 4.8 \n",
+ "... ... ... ... ... ... \n",
+ "tt9910930 False 2019 75 Crime,Documentary 4.6 \n",
+ "tt9911774 False 2019 130 Drama 8.5 \n",
+ "tt9913056 False 2019 86 Documentary 6.2 \n",
+ "tt9913084 False 2019 75 Documentary 6.2 \n",
+ "tt9914286 False 2019 98 Drama,Family 9.8 \n",
+ "\n",
+ " imdb_votes \n",
+ "tconst \n",
+ "tt0000009 77 \n",
+ "tt0000147 289 \n",
+ "tt0000335 39 \n",
+ "tt0000574 505 \n",
+ "tt0000615 14 \n",
+ "... ... \n",
+ "tt9910930 5 \n",
+ "tt9911774 363 \n",
+ "tt9913056 5 \n",
+ "tt9913084 6 \n",
+ "tt9914286 72 \n",
+ "\n",
+ "[232496 rows x 8 columns]"
+ ]
+ },
+ "execution_count": 27,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Alternativa 3 (méně \"sémantická\")\n",
+ "pd.concat([movies, ratings], axis=\"columns\", join=\"inner\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Zkusme si zreprodukovat pořadí 250 nejlepších filmů z IMDb (viz https://www.imdb.com/chart/top/?ref_=nv_mv_250):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
title
\n",
+ "
original_title
\n",
+ "
is_adult
\n",
+ "
year
\n",
+ "
length
\n",
+ "
genres
\n",
+ "
imdb_rating
\n",
+ "
imdb_votes
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
0
\n",
+ "
The Chaos Class
\n",
+ "
Hababam Sinifi
\n",
+ "
False
\n",
+ "
1975
\n",
+ "
87
\n",
+ "
Comedy,Drama
\n",
+ "
9.4
\n",
+ "
33394
\n",
+ "
\n",
+ "
\n",
+ "
1
\n",
+ "
The Shawshank Redemption
\n",
+ "
The Shawshank Redemption
\n",
+ "
False
\n",
+ "
1994
\n",
+ "
142
\n",
+ "
Drama
\n",
+ "
9.3
\n",
+ "
2071759
\n",
+ "
\n",
+ "
\n",
+ "
2
\n",
+ "
The Mountain II
\n",
+ "
Dag II
\n",
+ "
False
\n",
+ "
2016
\n",
+ "
135
\n",
+ "
Action,Drama,War
\n",
+ "
9.3
\n",
+ "
100095
\n",
+ "
\n",
+ "
\n",
+ "
3
\n",
+ "
CM101MMXI Fundamentals
\n",
+ "
CM101MMXI Fundamentals
\n",
+ "
False
\n",
+ "
2013
\n",
+ "
139
\n",
+ "
Comedy,Documentary
\n",
+ "
9.2
\n",
+ "
41327
\n",
+ "
\n",
+ "
\n",
+ "
4
\n",
+ "
The Godfather
\n",
+ "
The Godfather
\n",
+ "
False
\n",
+ "
1972
\n",
+ "
175
\n",
+ "
Crime,Drama
\n",
+ "
9.2
\n",
+ "
1421495
\n",
+ "
\n",
+ "
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
\n",
+ "
\n",
+ "
245
\n",
+ "
12 Years a Slave
\n",
+ "
12 Years a Slave
\n",
+ "
False
\n",
+ "
2013
\n",
+ "
134
\n",
+ "
Biography,Drama,History
\n",
+ "
8.1
\n",
+ "
571204
\n",
+ "
\n",
+ "
\n",
+ "
246
\n",
+ "
The Sixth Sense
\n",
+ "
The Sixth Sense
\n",
+ "
False
\n",
+ "
1999
\n",
+ "
107
\n",
+ "
Drama,Mystery,Thriller
\n",
+ "
8.1
\n",
+ "
836928
\n",
+ "
\n",
+ "
\n",
+ "
247
\n",
+ "
The Passion of Joan of Arc
\n",
+ "
La passion de Jeanne d'Arc
\n",
+ "
False
\n",
+ "
1928
\n",
+ "
110
\n",
+ "
Biography,Drama,History
\n",
+ "
8.1
\n",
+ "
40107
\n",
+ "
\n",
+ "
\n",
+ "
248
\n",
+ "
Barfi!
\n",
+ "
Barfi!
\n",
+ "
False
\n",
+ "
2012
\n",
+ "
151
\n",
+ "
Comedy,Drama,Romance
\n",
+ "
8.1
\n",
+ "
68274
\n",
+ "
\n",
+ "
\n",
+ "
249
\n",
+ "
Platoon
\n",
+ "
Platoon
\n",
+ "
False
\n",
+ "
1986
\n",
+ "
120
\n",
+ "
Drama,War
\n",
+ "
8.1
\n",
+ "
348628
\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
250 rows × 8 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " title original_title is_adult year \\\n",
+ "0 The Chaos Class Hababam Sinifi False 1975 \n",
+ "1 The Shawshank Redemption The Shawshank Redemption False 1994 \n",
+ "2 The Mountain II Dag II False 2016 \n",
+ "3 CM101MMXI Fundamentals CM101MMXI Fundamentals False 2013 \n",
+ "4 The Godfather The Godfather False 1972 \n",
+ ".. ... ... ... ... \n",
+ "245 12 Years a Slave 12 Years a Slave False 2013 \n",
+ "246 The Sixth Sense The Sixth Sense False 1999 \n",
+ "247 The Passion of Joan of Arc La passion de Jeanne d'Arc False 1928 \n",
+ "248 Barfi! Barfi! False 2012 \n",
+ "249 Platoon Platoon False 1986 \n",
+ "\n",
+ " length genres imdb_rating imdb_votes \n",
+ "0 87 Comedy,Drama 9.4 33394 \n",
+ "1 142 Drama 9.3 2071759 \n",
+ "2 135 Action,Drama,War 9.3 100095 \n",
+ "3 139 Comedy,Documentary 9.2 41327 \n",
+ "4 175 Crime,Drama 9.2 1421495 \n",
+ ".. ... ... ... ... \n",
+ "245 134 Biography,Drama,History 8.1 571204 \n",
+ "246 107 Drama,Mystery,Thriller 8.1 836928 \n",
+ "247 110 Biography,Drama,History 8.1 40107 \n",
+ "248 151 Comedy,Drama,Romance 8.1 68274 \n",
+ "249 120 Drama,War 8.1 348628 \n",
+ "\n",
+ "[250 rows x 8 columns]"
+ ]
+ },
+ "execution_count": 28,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Ty nejlepší (do června 2019)\n",
+ "(movies_with_rating\n",
+ " .query(\"imdb_votes > 25000\") # Berou se jen filmy s více než 25000 hlasy\n",
+ " .sort_values(\"imdb_rating\", ascending=False) # IMDb tu použivá i váhu jednotlivých hlasů (kterou neznáme)\n",
+ " .reset_index(drop=True)\n",
+ ").iloc[:250]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Do výčtu se nám dostaly filmy, které hranici hlasů nepřekračují o moc. Máme důvodné podezření, že toto kritérium dávno změnili. S požadovanými 250 000 hlasy se už blížíme:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 29,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
"
+ ],
+ "text/plain": [
+ " rank title studio lifetime_gross \\\n",
+ "0 1 Star Wars: The Force Awakens BV 936662225 \n",
+ "1 2 Avatar Fox 760507625 \n",
+ "2 3 Black Panther BV 700059566 \n",
+ "3 4 Avengers: Infinity War BV 678815482 \n",
+ "4 5 Titanic Par. 659363944 \n",
+ "... ... ... ... ... \n",
+ "16262 16263 Dog Eat Dog IFC 80 \n",
+ "16263 16264 Paranoid Girls NaN 78 \n",
+ "16264 16265 Confession of a Child of the Century Cohen 74 \n",
+ "16265 16266 Storage 24 Magn. 72 \n",
+ "16266 16267 Zyzzyx Road Reg. 30 \n",
+ "\n",
+ " year \n",
+ "0 2015 \n",
+ "1 2009 \n",
+ "2 2018 \n",
+ "3 2018 \n",
+ "4 1997 \n",
+ "... ... \n",
+ "16262 2009 \n",
+ "16263 2015 \n",
+ "16264 2015 \n",
+ "16265 2013 \n",
+ "16266 2006 \n",
+ "\n",
+ "[16267 rows x 5 columns]"
+ ]
+ },
+ "execution_count": 30,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "boxoffice_raw"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 31,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "rank int64\n",
+ "title object\n",
+ "studio object\n",
+ "lifetime_gross int64\n",
+ "year int64\n",
+ "dtype: object"
+ ]
+ },
+ "execution_count": 31,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "boxoffice_raw.dtypes"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "S tím bychom v podstatně mohli být spokojení, jen přejmenujeme `rank`, abychom při joinování věděli, odkud daný sloupec pochází."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 32,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "boxoffice = (boxoffice_raw\n",
+ " .rename({\n",
+ " \"rank\": \"boxoffice_rank\"\n",
+ " }, axis=\"columns\")\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "A zkusíme joinovat. V tomto případě se nemůžeme opřít o index (`boxoffice` pochází z jiného zdroje a o nějakém ID filmu z IMDb nemá ani tuchy), ale explicitně specifikujeme, který sloupec (či sloupce) se musí shodovat - na to slouží argument `on`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 33,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
title
\n",
+ "
original_title
\n",
+ "
is_adult
\n",
+ "
year (imdb)
\n",
+ "
length
\n",
+ "
genres
\n",
+ "
imdb_rating
\n",
+ "
imdb_votes
\n",
+ "
boxoffice_rank
\n",
+ "
studio
\n",
+ "
lifetime_gross
\n",
+ "
year (boxoffice)
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
1643
\n",
+ "
Pinocchio
\n",
+ "
Pinocchio
\n",
+ "
False
\n",
+ "
1940
\n",
+ "
88
\n",
+ "
Animation,Comedy,Family
\n",
+ "
7.5
\n",
+ "
114689
\n",
+ "
885
\n",
+ "
Dis.
\n",
+ "
84254167
\n",
+ "
1940
\n",
+ "
\n",
+ "
\n",
+ "
1644
\n",
+ "
Pinocchio
\n",
+ "
Pinocchio
\n",
+ "
False
\n",
+ "
1940
\n",
+ "
88
\n",
+ "
Animation,Comedy,Family
\n",
+ "
7.5
\n",
+ "
114689
\n",
+ "
6108
\n",
+ "
Mira.
\n",
+ "
3684305
\n",
+ "
2002
\n",
+ "
\n",
+ "
\n",
+ "
1645
\n",
+ "
Pinocchio
\n",
+ "
Turlis Abenteuer
\n",
+ "
False
\n",
+ "
1967
\n",
+ "
75
\n",
+ "
Adventure,Family,Fantasy
\n",
+ "
7.2
\n",
+ "
19
\n",
+ "
885
\n",
+ "
Dis.
\n",
+ "
84254167
\n",
+ "
1940
\n",
+ "
\n",
+ "
\n",
+ "
1646
\n",
+ "
Pinocchio
\n",
+ "
Turlis Abenteuer
\n",
+ "
False
\n",
+ "
1967
\n",
+ "
75
\n",
+ "
Adventure,Family,Fantasy
\n",
+ "
7.2
\n",
+ "
19
\n",
+ "
6108
\n",
+ "
Mira.
\n",
+ "
3684305
\n",
+ "
2002
\n",
+ "
\n",
+ "
\n",
+ "
1647
\n",
+ "
Pinocchio
\n",
+ "
Pinocchio
\n",
+ "
False
\n",
+ "
1971
\n",
+ "
79
\n",
+ "
Comedy,Fantasy
\n",
+ "
3.5
\n",
+ "
123
\n",
+ "
885
\n",
+ "
Dis.
\n",
+ "
84254167
\n",
+ "
1940
\n",
+ "
\n",
+ "
\n",
+ "
1648
\n",
+ "
Pinocchio
\n",
+ "
Pinocchio
\n",
+ "
False
\n",
+ "
1971
\n",
+ "
79
\n",
+ "
Comedy,Fantasy
\n",
+ "
3.5
\n",
+ "
123
\n",
+ "
6108
\n",
+ "
Mira.
\n",
+ "
3684305
\n",
+ "
2002
\n",
+ "
\n",
+ "
\n",
+ "
1649
\n",
+ "
Pinocchio
\n",
+ "
Pinocchio
\n",
+ "
False
\n",
+ "
1911
\n",
+ "
50
\n",
+ "
Fantasy
\n",
+ "
5.9
\n",
+ "
69
\n",
+ "
885
\n",
+ "
Dis.
\n",
+ "
84254167
\n",
+ "
1940
\n",
+ "
\n",
+ "
\n",
+ "
1650
\n",
+ "
Pinocchio
\n",
+ "
Pinocchio
\n",
+ "
False
\n",
+ "
1911
\n",
+ "
50
\n",
+ "
Fantasy
\n",
+ "
5.9
\n",
+ "
69
\n",
+ "
6108
\n",
+ "
Mira.
\n",
+ "
3684305
\n",
+ "
2002
\n",
+ "
\n",
+ "
\n",
+ "
1651
\n",
+ "
Pinocchio
\n",
+ "
Pinocchio
\n",
+ "
False
\n",
+ "
2002
\n",
+ "
108
\n",
+ "
Comedy,Family,Fantasy
\n",
+ "
4.3
\n",
+ "
7192
\n",
+ "
885
\n",
+ "
Dis.
\n",
+ "
84254167
\n",
+ "
1940
\n",
+ "
\n",
+ "
\n",
+ "
1652
\n",
+ "
Pinocchio
\n",
+ "
Pinocchio
\n",
+ "
False
\n",
+ "
2002
\n",
+ "
108
\n",
+ "
Comedy,Family,Fantasy
\n",
+ "
4.3
\n",
+ "
7192
\n",
+ "
6108
\n",
+ "
Mira.
\n",
+ "
3684305
\n",
+ "
2002
\n",
+ "
\n",
+ "
\n",
+ "
1653
\n",
+ "
Pinocchio
\n",
+ "
Un burattino di nome Pinocchio
\n",
+ "
False
\n",
+ "
1971
\n",
+ "
96
\n",
+ "
Animation,Family,Fantasy
\n",
+ "
7.0
\n",
+ "
117
\n",
+ "
885
\n",
+ "
Dis.
\n",
+ "
84254167
\n",
+ "
1940
\n",
+ "
\n",
+ "
\n",
+ "
1654
\n",
+ "
Pinocchio
\n",
+ "
Un burattino di nome Pinocchio
\n",
+ "
False
\n",
+ "
1971
\n",
+ "
96
\n",
+ "
Animation,Family,Fantasy
\n",
+ "
7.0
\n",
+ "
117
\n",
+ "
6108
\n",
+ "
Mira.
\n",
+ "
3684305
\n",
+ "
2002
\n",
+ "
\n",
+ "
\n",
+ "
1655
\n",
+ "
Pinocchio
\n",
+ "
Pinocchio
\n",
+ "
False
\n",
+ "
2012
\n",
+ "
75
\n",
+ "
Animation,Family,Fantasy
\n",
+ "
6.3
\n",
+ "
218
\n",
+ "
885
\n",
+ "
Dis.
\n",
+ "
84254167
\n",
+ "
1940
\n",
+ "
\n",
+ "
\n",
+ "
1656
\n",
+ "
Pinocchio
\n",
+ "
Pinocchio
\n",
+ "
False
\n",
+ "
2012
\n",
+ "
75
\n",
+ "
Animation,Family,Fantasy
\n",
+ "
6.3
\n",
+ "
218
\n",
+ "
6108
\n",
+ "
Mira.
\n",
+ "
3684305
\n",
+ "
2002
\n",
+ "
\n",
+ "
\n",
+ "
1657
\n",
+ "
Pinocchio
\n",
+ "
Pinocchio
\n",
+ "
False
\n",
+ "
2015
\n",
+ "
<NA>
\n",
+ "
Family,Fantasy
\n",
+ "
4.9
\n",
+ "
43
\n",
+ "
885
\n",
+ "
Dis.
\n",
+ "
84254167
\n",
+ "
1940
\n",
+ "
\n",
+ "
\n",
+ "
1658
\n",
+ "
Pinocchio
\n",
+ "
Pinocchio
\n",
+ "
False
\n",
+ "
2015
\n",
+ "
<NA>
\n",
+ "
Family,Fantasy
\n",
+ "
4.9
\n",
+ "
43
\n",
+ "
6108
\n",
+ "
Mira.
\n",
+ "
3684305
\n",
+ "
2002
\n",
+ "
\n",
+ "
\n",
+ "
1659
\n",
+ "
Pinocchio
\n",
+ "
Pinocchio
\n",
+ "
False
\n",
+ "
2015
\n",
+ "
75
\n",
+ "
Documentary
\n",
+ "
6.8
\n",
+ "
8
\n",
+ "
885
\n",
+ "
Dis.
\n",
+ "
84254167
\n",
+ "
1940
\n",
+ "
\n",
+ "
\n",
+ "
1660
\n",
+ "
Pinocchio
\n",
+ "
Pinocchio
\n",
+ "
False
\n",
+ "
2015
\n",
+ "
75
\n",
+ "
Documentary
\n",
+ "
6.8
\n",
+ "
8
\n",
+ "
6108
\n",
+ "
Mira.
\n",
+ "
3684305
\n",
+ "
2002
\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " title original_title is_adult year (imdb) \\\n",
+ "1643 Pinocchio Pinocchio False 1940 \n",
+ "1644 Pinocchio Pinocchio False 1940 \n",
+ "1645 Pinocchio Turlis Abenteuer False 1967 \n",
+ "1646 Pinocchio Turlis Abenteuer False 1967 \n",
+ "1647 Pinocchio Pinocchio False 1971 \n",
+ "1648 Pinocchio Pinocchio False 1971 \n",
+ "1649 Pinocchio Pinocchio False 1911 \n",
+ "1650 Pinocchio Pinocchio False 1911 \n",
+ "1651 Pinocchio Pinocchio False 2002 \n",
+ "1652 Pinocchio Pinocchio False 2002 \n",
+ "1653 Pinocchio Un burattino di nome Pinocchio False 1971 \n",
+ "1654 Pinocchio Un burattino di nome Pinocchio False 1971 \n",
+ "1655 Pinocchio Pinocchio False 2012 \n",
+ "1656 Pinocchio Pinocchio False 2012 \n",
+ "1657 Pinocchio Pinocchio False 2015 \n",
+ "1658 Pinocchio Pinocchio False 2015 \n",
+ "1659 Pinocchio Pinocchio False 2015 \n",
+ "1660 Pinocchio Pinocchio False 2015 \n",
+ "\n",
+ " length genres imdb_rating imdb_votes \\\n",
+ "1643 88 Animation,Comedy,Family 7.5 114689 \n",
+ "1644 88 Animation,Comedy,Family 7.5 114689 \n",
+ "1645 75 Adventure,Family,Fantasy 7.2 19 \n",
+ "1646 75 Adventure,Family,Fantasy 7.2 19 \n",
+ "1647 79 Comedy,Fantasy 3.5 123 \n",
+ "1648 79 Comedy,Fantasy 3.5 123 \n",
+ "1649 50 Fantasy 5.9 69 \n",
+ "1650 50 Fantasy 5.9 69 \n",
+ "1651 108 Comedy,Family,Fantasy 4.3 7192 \n",
+ "1652 108 Comedy,Family,Fantasy 4.3 7192 \n",
+ "1653 96 Animation,Family,Fantasy 7.0 117 \n",
+ "1654 96 Animation,Family,Fantasy 7.0 117 \n",
+ "1655 75 Animation,Family,Fantasy 6.3 218 \n",
+ "1656 75 Animation,Family,Fantasy 6.3 218 \n",
+ "1657 Family,Fantasy 4.9 43 \n",
+ "1658 Family,Fantasy 4.9 43 \n",
+ "1659 75 Documentary 6.8 8 \n",
+ "1660 75 Documentary 6.8 8 \n",
+ "\n",
+ " boxoffice_rank studio lifetime_gross year (boxoffice) \n",
+ "1643 885 Dis. 84254167 1940 \n",
+ "1644 6108 Mira. 3684305 2002 \n",
+ "1645 885 Dis. 84254167 1940 \n",
+ "1646 6108 Mira. 3684305 2002 \n",
+ "1647 885 Dis. 84254167 1940 \n",
+ "1648 6108 Mira. 3684305 2002 \n",
+ "1649 885 Dis. 84254167 1940 \n",
+ "1650 6108 Mira. 3684305 2002 \n",
+ "1651 885 Dis. 84254167 1940 \n",
+ "1652 6108 Mira. 3684305 2002 \n",
+ "1653 885 Dis. 84254167 1940 \n",
+ "1654 6108 Mira. 3684305 2002 \n",
+ "1655 885 Dis. 84254167 1940 \n",
+ "1656 6108 Mira. 3684305 2002 \n",
+ "1657 885 Dis. 84254167 1940 \n",
+ "1658 6108 Mira. 3684305 2002 \n",
+ "1659 885 Dis. 84254167 1940 \n",
+ "1660 6108 Mira. 3684305 2002 "
+ ]
+ },
+ "execution_count": 33,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "pd.merge(\n",
+ " movies_with_rating,\n",
+ " boxoffice,\n",
+ " suffixes=[\" (imdb)\", \" (boxoffice)\"],\n",
+ " on=\"title\"\n",
+ ").query(\"title == 'Pinocchio'\") # \"Jeden\" ukázkový film"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Jejda, to jsme asi nechtěli. Existuje spousta různých Pinocchiů a ke každému z nich se připojili vždy oba snímky tohoto jména z `boxoffice`. Z toho vyplývá poučení, že při joinování je dobré se zamyslet nad jedinečností hodnot ve sloupci, který používáme jako klíč. Jméno filmu takové očividně není.\n",
+ "\n",
+ "V našem konkrétním případě jsme si problému všimli sami, ale pokud bude duplikátní klíč utopen někde v milionech hodnot, rádi bychom, aby to počítač poznal za nás. K tomu slouží argument `validate` - podle toho, jaký vztah mezi tabulkami očekáš, jsou přípustné hodnoty `\"one_to_one\"`, `\"one_to_many\"`, `\"many_to_one\"` nebo `\"many_to_many\"`:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 34,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
title
\n",
+ "
original_title
\n",
+ "
is_adult
\n",
+ "
year (imdb)
\n",
+ "
length
\n",
+ "
genres
\n",
+ "
imdb_rating
\n",
+ "
imdb_votes
\n",
+ "
boxoffice_rank
\n",
+ "
studio
\n",
+ "
lifetime_gross
\n",
+ "
year (boxoffice)
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
0
\n",
+ "
Oliver Twist
\n",
+ "
Oliver Twist
\n",
+ "
False
\n",
+ "
1912
\n",
+ "
<NA>
\n",
+ "
Drama
\n",
+ "
4.7
\n",
+ "
19
\n",
+ "
6826
\n",
+ "
Sony
\n",
+ "
2080321
\n",
+ "
2005
\n",
+ "
\n",
+ "
\n",
+ "
1
\n",
+ "
Oliver Twist
\n",
+ "
Oliver Twist
\n",
+ "
False
\n",
+ "
1912
\n",
+ "
<NA>
\n",
+ "
Drama
\n",
+ "
4.4
\n",
+ "
12
\n",
+ "
6826
\n",
+ "
Sony
\n",
+ "
2080321
\n",
+ "
2005
\n",
+ "
\n",
+ "
\n",
+ "
2
\n",
+ "
Oliver Twist
\n",
+ "
Oliver Twist
\n",
+ "
False
\n",
+ "
1916
\n",
+ "
50
\n",
+ "
Drama
\n",
+ "
6.6
\n",
+ "
16
\n",
+ "
6826
\n",
+ "
Sony
\n",
+ "
2080321
\n",
+ "
2005
\n",
+ "
\n",
+ "
\n",
+ "
3
\n",
+ "
Oliver Twist
\n",
+ "
Oliver Twist
\n",
+ "
False
\n",
+ "
1922
\n",
+ "
98
\n",
+ "
Drama
\n",
+ "
6.8
\n",
+ "
657
\n",
+ "
6826
\n",
+ "
Sony
\n",
+ "
2080321
\n",
+ "
2005
\n",
+ "
\n",
+ "
\n",
+ "
4
\n",
+ "
Oliver Twist
\n",
+ "
Oliver Twist
\n",
+ "
False
\n",
+ "
1933
\n",
+ "
80
\n",
+ "
Drama
\n",
+ "
5.0
\n",
+ "
292
\n",
+ "
6826
\n",
+ "
Sony
\n",
+ "
2080321
\n",
+ "
2005
\n",
+ "
\n",
+ "
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
\n",
+ "
\n",
+ "
20562
\n",
+ "
BTS World Tour: Love Yourself in Seoul
\n",
+ "
BTS World Tour: Love Yourself in Seoul
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
112
\n",
+ "
Documentary,Music
\n",
+ "
8.5
\n",
+ "
439
\n",
+ "
6173
\n",
+ "
Fathom
\n",
+ "
3509917
\n",
+ "
2019
\n",
+ "
\n",
+ "
\n",
+ "
20563
\n",
+ "
Mojin: The Worm Valley
\n",
+ "
Yun nan chong gu
\n",
+ "
False
\n",
+ "
2018
\n",
+ "
110
\n",
+ "
Action,Fantasy
\n",
+ "
4.7
\n",
+ "
120
\n",
+ "
11240
\n",
+ "
WGUSA
\n",
+ "
101516
\n",
+ "
2019
\n",
+ "
\n",
+ "
\n",
+ "
20564
\n",
+ "
Extreme Job
\n",
+ "
Geukhanjikeob
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
111
\n",
+ "
Action,Comedy
\n",
+ "
7.3
\n",
+ "
905
\n",
+ "
7212
\n",
+ "
CJ
\n",
+ "
1548816
\n",
+ "
2019
\n",
+ "
\n",
+ "
\n",
+ "
20565
\n",
+ "
Peppa Celebrates Chinese New Year
\n",
+ "
xiao zhu pei qi guo da nian
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
81
\n",
+ "
Animation,Family
\n",
+ "
3.4
\n",
+ "
41
\n",
+ "
10811
\n",
+ "
STX
\n",
+ "
131225
\n",
+ "
2019
\n",
+ "
\n",
+ "
\n",
+ "
20566
\n",
+ "
Avant qu'on explose
\n",
+ "
Avant qu'on explose
\n",
+ "
False
\n",
+ "
2019
\n",
+ "
108
\n",
+ "
Comedy
\n",
+ "
6.9
\n",
+ "
41
\n",
+ "
10995
\n",
+ "
EOne
\n",
+ "
116576
\n",
+ "
2019
\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
20567 rows × 12 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " title \\\n",
+ "0 Oliver Twist \n",
+ "1 Oliver Twist \n",
+ "2 Oliver Twist \n",
+ "3 Oliver Twist \n",
+ "4 Oliver Twist \n",
+ "... ... \n",
+ "20562 BTS World Tour: Love Yourself in Seoul \n",
+ "20563 Mojin: The Worm Valley \n",
+ "20564 Extreme Job \n",
+ "20565 Peppa Celebrates Chinese New Year \n",
+ "20566 Avant qu'on explose \n",
+ "\n",
+ " original_title is_adult year (imdb) length \\\n",
+ "0 Oliver Twist False 1912 \n",
+ "1 Oliver Twist False 1912 \n",
+ "2 Oliver Twist False 1916 50 \n",
+ "3 Oliver Twist False 1922 98 \n",
+ "4 Oliver Twist False 1933 80 \n",
+ "... ... ... ... ... \n",
+ "20562 BTS World Tour: Love Yourself in Seoul False 2019 112 \n",
+ "20563 Yun nan chong gu False 2018 110 \n",
+ "20564 Geukhanjikeob False 2019 111 \n",
+ "20565 xiao zhu pei qi guo da nian False 2019 81 \n",
+ "20566 Avant qu'on explose False 2019 108 \n",
+ "\n",
+ " genres imdb_rating imdb_votes boxoffice_rank studio \\\n",
+ "0 Drama 4.7 19 6826 Sony \n",
+ "1 Drama 4.4 12 6826 Sony \n",
+ "2 Drama 6.6 16 6826 Sony \n",
+ "3 Drama 6.8 657 6826 Sony \n",
+ "4 Drama 5.0 292 6826 Sony \n",
+ "... ... ... ... ... ... \n",
+ "20562 Documentary,Music 8.5 439 6173 Fathom \n",
+ "20563 Action,Fantasy 4.7 120 11240 WGUSA \n",
+ "20564 Action,Comedy 7.3 905 7212 CJ \n",
+ "20565 Animation,Family 3.4 41 10811 STX \n",
+ "20566 Comedy 6.9 41 10995 EOne \n",
+ "\n",
+ " lifetime_gross year (boxoffice) \n",
+ "0 2080321 2005 \n",
+ "1 2080321 2005 \n",
+ "2 2080321 2005 \n",
+ "3 2080321 2005 \n",
+ "4 2080321 2005 \n",
+ "... ... ... \n",
+ "20562 3509917 2019 \n",
+ "20563 101516 2019 \n",
+ "20564 1548816 2019 \n",
+ "20565 131225 2019 \n",
+ "20566 116576 2019 \n",
+ "\n",
+ "[20567 rows x 12 columns]"
+ ]
+ },
+ "execution_count": 34,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "pd.merge(\n",
+ " movies_with_rating,\n",
+ " boxoffice,\n",
+ " on=\"title\",\n",
+ " suffixes=[\" (imdb)\", \" (boxoffice)\"],\n",
+ "# validate=\"one_to_one\" # Odkomentuj a vyskočí chyba!\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Řešení je jednoduché - budeme joinovat přes dva různé sloupce (argument `on` to unese ;-)). Při té příležitosti navíc zjišťujeme, že nedává smysl spojovat filmy, které rok vůbec uvedený nemají, a proto je vyhodíme:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 35,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
title
\n",
+ "
original_title
\n",
+ "
is_adult
\n",
+ "
year
\n",
+ "
length
\n",
+ "
genres
\n",
+ "
imdb_rating
\n",
+ "
imdb_votes
\n",
+ "
boxoffice_rank
\n",
+ "
studio
\n",
+ "
lifetime_gross
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
6926
\n",
+ "
Playback
\n",
+ "
Playback
\n",
+ "
False
\n",
+ "
2012
\n",
+ "
98
\n",
+ "
Horror,Thriller
\n",
+ "
4.3
\n",
+ "
4478
\n",
+ "
16256
\n",
+ "
Magn.
\n",
+ "
264
\n",
+ "
\n",
+ "
\n",
+ "
6927
\n",
+ "
Playback
\n",
+ "
Playback
\n",
+ "
False
\n",
+ "
2012
\n",
+ "
113
\n",
+ "
Drama
\n",
+ "
4.9
\n",
+ "
27
\n",
+ "
16256
\n",
+ "
Magn.
\n",
+ "
264
\n",
+ "
\n",
+ "
\n",
+ "
6928
\n",
+ "
Playback
\n",
+ "
Dur d'être Dieu
\n",
+ "
False
\n",
+ "
2012
\n",
+ "
66
\n",
+ "
Documentary
\n",
+ "
5.2
\n",
+ "
8
\n",
+ "
16256
\n",
+ "
Magn.
\n",
+ "
264
\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " title original_title is_adult year length genres \\\n",
+ "6926 Playback Playback False 2012 98 Horror,Thriller \n",
+ "6927 Playback Playback False 2012 113 Drama \n",
+ "6928 Playback Dur d'être Dieu False 2012 66 Documentary \n",
+ "\n",
+ " imdb_rating imdb_votes boxoffice_rank studio lifetime_gross \n",
+ "6926 4.3 4478 16256 Magn. 264 \n",
+ "6927 4.9 27 16256 Magn. 264 \n",
+ "6928 5.2 8 16256 Magn. 264 "
+ ]
+ },
+ "execution_count": 35,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "(\n",
+ " pd.merge(\n",
+ " movies_with_rating.dropna(subset=[\"year\"]), # Vyhoď všechny řádky bez roku\n",
+ " boxoffice,\n",
+ " on=[\"title\", \"year\"],\n",
+ " validate=\"many_to_one\", # movies_with_rating pořád nejsou unikátní!\n",
+ " )\n",
+ ").query(\"title == 'Playback'\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Pořád nejsou unikátní! Co s tím?\n",
+ "\n",
+ "**Hypotéza:** Vstupujeme na nebezpečnou půdu a zkusíme spekulovat, že informace o ziscích budeme mít nejspíš jen o nejpopulárnějších filmech. Možná máme pravdu, možná ne a nejspíš nějakou drobnou nepřesnost zaneseme, ale dobrat se tady skutečné pravdy je \"drahé\" (a možná i skutečně drahé), z nabízených datových sad to věrohodně možné není.\n",
+ "\n",
+ "Abychom se co nejvíc přiblížili realitě, z každé opakující se dvojice (název, rok) vybereme film s nejvyšším `imdb_votes`. Nejdříve si pomocí `sort_values` srovnáme všechny filmy a pak zavoláme `drop_duplicates(..., keep=\"first\")`, což nám ponechá vždy jen jeden z řady duplikátů:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 36,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
"
+ ],
+ "text/plain": [
+ "Empty DataFrame\n",
+ "Columns: [title_type, title, original_title, is_adult, start_year, end_year, length, genres, Title, RatingTomatometer, No. of Reviews]\n",
+ "Index: []"
+ ]
+ },
+ "execution_count": 41,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# Ready to merge?\n",
+ "pd.merge(imdb_titles, rotten_tomatoes_nodup, left_on=\"title\", right_on=\"Title\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "0 řádků!\n",
+ "\n",
+ "Dosud jsme manipulovali s řádky a sloupci jako celky, nicméně teď musíme zasahovat přímo do hodnot v buňkách. I to se při slučování dat z různých zdrojů nezřídka stává. Stojíme před úkolem převést řetězce typu \"Black Panther (2018)\" na dvě hodnoty: název \"Black Panther\" a rok 2018 (jeden sloupec na dva). \n",
+ "\n",
+ "Naštěstí si ty sloupce umíme jednoduše vyrobit pomocí řetězcové metody [`.str.slice`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.slice.html), která z každého řetězce vyřízne nějakou jeho část (a zase pracuje na celém sloupci - výsledkem bude nový sloupec s funkcí aplikovanou na každou z hodnot). Budeme věřit, že předposlední čtyři znaky představují rok a zbytek, až na nějaké ty závorky, tvoří skutečný název:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 42,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
tomatoes_rating
\n",
+ "
tomatoes_votes
\n",
+ "
title
\n",
+ "
year
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
0
\n",
+ "
97
\n",
+ "
444
\n",
+ "
Black Panther
\n",
+ "
2018
\n",
+ "
\n",
+ "
\n",
+ "
1
\n",
+ "
97
\n",
+ "
394
\n",
+ "
Mad Max: Fury Road
\n",
+ "
2015
\n",
+ "
\n",
+ "
\n",
+ "
2
\n",
+ "
93
\n",
+ "
410
\n",
+ "
Wonder Woman
\n",
+ "
2017
\n",
+ "
\n",
+ "
\n",
+ "
3
\n",
+ "
99
\n",
+ "
118
\n",
+ "
Metropolis
\n",
+ "
1927
\n",
+ "
\n",
+ "
\n",
+ "
4
\n",
+ "
97
\n",
+ "
308
\n",
+ "
Coco
\n",
+ "
2017
\n",
+ "
\n",
+ "
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
\n",
+ "
\n",
+ "
1585
\n",
+ "
15
\n",
+ "
97
\n",
+ "
Priest
\n",
+ "
2011
\n",
+ "
\n",
+ "
\n",
+ "
1586
\n",
+ "
14
\n",
+ "
103
\n",
+ "
American Outlaws
\n",
+ "
2001
\n",
+ "
\n",
+ "
\n",
+ "
1587
\n",
+ "
15
\n",
+ "
54
\n",
+ "
September Dawn
\n",
+ "
2007
\n",
+ "
\n",
+ "
\n",
+ "
1588
\n",
+ "
12
\n",
+ "
147
\n",
+ "
Jonah Hex
\n",
+ "
2010
\n",
+ "
\n",
+ "
\n",
+ "
1589
\n",
+ "
2
\n",
+ "
51
\n",
+ "
Texas Rangers
\n",
+ "
2001
\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
947 rows × 4 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " tomatoes_rating tomatoes_votes title year\n",
+ "0 97 444 Black Panther 2018\n",
+ "1 97 394 Mad Max: Fury Road 2015\n",
+ "2 93 410 Wonder Woman 2017\n",
+ "3 99 118 Metropolis 1927\n",
+ "4 97 308 Coco 2017\n",
+ "... ... ... ... ...\n",
+ "1585 15 97 Priest 2011\n",
+ "1586 14 103 American Outlaws 2001\n",
+ "1587 15 54 September Dawn 2007\n",
+ "1588 12 147 Jonah Hex 2010\n",
+ "1589 2 51 Texas Rangers 2001\n",
+ "\n",
+ "[947 rows x 4 columns]"
+ ]
+ },
+ "execution_count": 42,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "rotten_tomatoes_beta = (rotten_tomatoes_nodup\n",
+ " .assign(\n",
+ " title=rotten_tomatoes_nodup[\"Title\"].str.slice(0, -7), \n",
+ " year=rotten_tomatoes_nodup[\"Title\"].str.slice(-5, -1).astype(int)\n",
+ " )\n",
+ " .rename({\n",
+ " \"RatingTomatometer\": \"tomatoes_rating\",\n",
+ " \"No. of Reviews\": \"tomatoes_votes\",\n",
+ " }, axis=\"columns\")\n",
+ " .drop([\"Title\"], axis=\"columns\")\n",
+ ")\n",
+ "rotten_tomatoes_beta"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Závorková odysea nekončí, někdo nám proaktivně do závorek nacpal i originální název naanglickojazyčných filmů. Pojďme se o tom přesvědčit pomocí metody [`.str.contains`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.contains.html) (protože tato metoda ve výchozím stavu používá pro vyhledávání regulární výrazy, které jsme se zatím nenaučili používat, musíme jí to explicitně zakázat argumentem `regex=False`):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 43,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
\n",
+ "
tomatoes_rating
\n",
+ "
tomatoes_votes
\n",
+ "
title
\n",
+ "
year
\n",
+ "
\n",
+ " \n",
+ " \n",
+ "
\n",
+ "
15
\n",
+ "
100
\n",
+ "
58
\n",
+ "
Seven Samurai (Shichinin no Samurai)
\n",
+ "
1956
\n",
+ "
\n",
+ "
\n",
+ "
51
\n",
+ "
98
\n",
+ "
46
\n",
+ "
Aguirre, the Wrath of God (Aguirre, der Zorn G...
\n",
+ "
1972
\n",
+ "
\n",
+ "
\n",
+ "
61
\n",
+ "
97
\n",
+ "
71
\n",
+ "
Ghostbusters (1984 Original)
\n",
+ "
1984
\n",
+ "
\n",
+ "
\n",
+ "
69
\n",
+ "
98
\n",
+ "
47
\n",
+ "
A Fistful of Dollars (Per un Pugno di Dollari)
\n",
+ "
1964
\n",
+ "
\n",
+ "
\n",
+ "
99
\n",
+ "
96
\n",
+ "
139
\n",
+ "
Embrace Of The Serpent (El Abrazo De La Serpie...
\n",
+ "
2016
\n",
+ "
\n",
+ "
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
...
\n",
+ "
\n",
+ "
\n",
+ "
1368
\n",
+ "
97
\n",
+ "
59
\n",
+ "
To Be and to Have (Etre et Avoir)
\n",
+ "
2003
\n",
+ "
\n",
+ "
\n",
+ "
1457
\n",
+ "
43
\n",
+ "
82
\n",
+ "
Goal! The Dream Begins (Goal!: The Impossible ...
\n",
+ "
2005
\n",
+ "
\n",
+ "
\n",
+ "
1502
\n",
+ "
71
\n",
+ "
52
\n",
+ "
Only Human (Seres queridos)
\n",
+ "
2006
\n",
+ "
\n",
+ "
\n",
+ "
1547
\n",
+ "
83
\n",
+ "
64
\n",
+ "
The Good, the Bad, the Weird (Joheun-nom, Nabb...
\n",
+ "
2010
\n",
+ "
\n",
+ "
\n",
+ "
1559
\n",
+ "
74
\n",
+ "
62
\n",
+ "
Fah talai jone (Tears of the Black Tiger)
\n",
+ "
2007
\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
66 rows × 4 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " tomatoes_rating tomatoes_votes \\\n",
+ "15 100 58 \n",
+ "51 98 46 \n",
+ "61 97 71 \n",
+ "69 98 47 \n",
+ "99 96 139 \n",
+ "... ... ... \n",
+ "1368 97 59 \n",
+ "1457 43 82 \n",
+ "1502 71 52 \n",
+ "1547 83 64 \n",
+ "1559 74 62 \n",
+ "\n",
+ " title year \n",
+ "15 Seven Samurai (Shichinin no Samurai) 1956 \n",
+ "51 Aguirre, the Wrath of God (Aguirre, der Zorn G... 1972 \n",
+ "61 Ghostbusters (1984 Original) 1984 \n",
+ "69 A Fistful of Dollars (Per un Pugno di Dollari) 1964 \n",
+ "99 Embrace Of The Serpent (El Abrazo De La Serpie... 2016 \n",
+ "... ... ... \n",
+ "1368 To Be and to Have (Etre et Avoir) 2003 \n",
+ "1457 Goal! The Dream Begins (Goal!: The Impossible ... 2005 \n",
+ "1502 Only Human (Seres queridos) 2006 \n",
+ "1547 The Good, the Bad, the Weird (Joheun-nom, Nabb... 2010 \n",
+ "1559 Fah talai jone (Tears of the Black Tiger) 2007 \n",
+ "\n",
+ "[66 rows x 4 columns]"
+ ]
+ },
+ "execution_count": 43,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "rotten_tomatoes_beta[rotten_tomatoes_beta[\"title\"].str.contains(\")\", regex=False)]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "V rámci zjednodušení proto ještě odstraníme všechny takové závorky. K tomu pomůže funkce [`.str.rsplit`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.rsplit.html), která rozdělí zprava řetězec na několik částí podle oddělovače a vloží je do seznamu - my za ten oddělovač zvolíme levou závorku `\"(\"`, omezíme počet částí na jednu až dvě (`n=1`):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 44,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "41 [Marvel's The Avengers]\n",
+ "61 [Ghostbusters , 1984 Original)]\n",
+ "81 [Mad Max 2: The Road Warrior]\n",
+ "Name: title, dtype: object"
+ ]
+ },
+ "execution_count": 44,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "split_title = (\n",
+ " rotten_tomatoes_beta[\"title\"]\n",
+ " .str.rsplit(\"(\", n=1)\n",
+ ")\n",
+ "split_title.loc[[41, 61, 81]] # Některé seznamy obsahují jeden prvek, jiné dva"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "A jak teď vybrat první prvek z každého seznamu?\n",
+ "\n",
+ "💡 Metoda [`apply`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.apply.html) umožňuje použít libovolnou transformaci (definovanou jako funkci) na každý řádek v tabulce či hodnotu v `Series`. Obvykle se bez ní obejdeme a měli bychom (proto se jí tolik speciálně nevěnujeme), protože není příliš výpočetně efektivní. Tady nám ale usnadní pochopení, co se vlastně dělá, t.j. vybírá první prvek nějakého seznamu:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 45,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "