Pivot tabulky
Pivot tabulka (často se též používá termín kontingenční tabulka) je nástroj, který vám umožní rychle a efektivně shrnovat, analyzovat, prozkoumávat a prezentovat souhrnná data.
Jak bychom pivot tabulky mohli využít pro naše data? Pivot tabulky dokážou zobrazit vztah mezi dvěma sloupci tabulky (dvěma proměnnými), v našem případě můžeme například sledovat vztah mezi dvěma výživnými látkami. Mohli bychom tedy zkoumat, jestli při růstu množství jedné výživné látky roste (nebo naopak klesá) množství jiné výživné látky. Dále nám tabulka může usnadnit hledání vhodných potravin na základě více než jednoho kritéria. Pokud bychom například hledali potravinu, která má hodně vlákniny a současně málo nasycených tuků, museli bychom napsat poměrně složitou podmínku. Pivot tabulka nám situaci zjednoduší. Poslední příklad je zkoumání průměrného množství výživných látek v jednotlivých kategoriích potravin, kontingenční tabulky tedy mohou být alternativou k vizualizacím, které jsme si ukázali v minulé lekci.
Začneme tím, že si načteme data ze souboru food_nutrient.csv
do tabulky food_nutrient
.
import pandas as pd
food_nutrient = pd.read_csv("food_nutrient.csv")
V pandas
existuje několik funkcí. My začneme s funkcí pivot()
. Tato funkce slouží k "přeskládání" tabulky. Výsledná tabulka nebude mít samostatný řádek pro každou kombinaci potraviny a výživné látky. Tabulku přeskládáme tak, aby každá potravina měla pouze jeden řádek a jednotlivé výživné látky budou uloženy ve sloupcích. Namísto sloupce name
s názvem výživné látky budeme mít názvy výživných látek přímo ve sloupcích.
Funkci pivot
určíme čtyři parametry, kromě prvního parametru data
musíme všechny psát jako pojmenované:
- Prvním parametrem (
data
) určujeme tabulku, se kterou bude funkce pracovat. - Parametr
index
slouží jako popisek řádků. V našem případě zvolíme sloupečekfdc_id
, tj. unikátní číslo potraviny. - Parametr
columns
bude použit k vytvoření nových sloupečků. Každá unikátní hodnota v tomto sloupci bude znamenat nový sloupeček ve výsledné tabulce. Sem doplníme sloupecname
. - Parametr
value
označuje sloupec, ze kterého budou čteny hodnoty. V našem případě půjde o sloupecamount
. Funkcepivot
se pro každý řádek původní tabulky "podívá" na sloupcefdc_id
aname
, tj. na číslo potraviny a název výživné látky. Hodnotu, která je ve sloupciamount
, pak doplní do nové tabulky na řádek se stejnýmfdc_id
a do sloupce pro příslušnou výživnou látku.
Pozor na to, že kombinace každé dvojice sloupců index
a columns
může být v původní tabulce pouze jednou, jinak by totiž nebylo možné data "přeskládat" - do jednoho políčka tabulky bychom museli nacpat více než jednu hodnotu. Funkce na takovou situaci reaguje chybou. Pokud máme v tabulce malé množství duplicitních hodnot, můžeme je odstranit s využitím metody drop_duplicates()
. Použijeme metodu pro naše data. Využijeme parametr subset
a do něj vložíme názvy sloupců, podle kterých má být duplicita rozpoznána.
food_nutrient = food_nutrient.drop_duplicates(subset=["fdc_id", "name"])
U funkce pivot()
je důležité, abychom pro každou kombinaci fdc_id
a name
měli pouze jeden řádek. Funkce totiž neprovádí žádnou agregaci. Pokud bychom agregaci potřebovali provést, musíme použít některou z funkcí, které si ukážeme dále.
Níže je použití funkce pivot
.
food_nutrient_pivot = pd.pivot(food_nutrient, index="fdc_id", columns="name", values="amount")
K tabulce food_nutrient_pivot
můžeme připojit další informace o potravinách, se kterými jsme pracovali v předchozích lekcích. Budeme tedy vědět, kterých potravin se každý řádek týká.
branded_food = pd.read_csv("branded_food.csv")
food = pd.concat([pd.read_csv("food_sample_100.csv"), pd.read_csv("food_other.csv")], ignore_index=True)
food_brands = pd.merge(food, branded_food, on="fdc_id")
food_nutrient_pivot = pd.merge(food_nutrient_pivot, food_brands, on="fdc_id")
Po úpravě dat s využitím funkce pivot()
můžeme snadno vytvořit další typ grafu, a to je scatter plotbodový graf. Bodový graf bude mít na svislé i vodorovné ose množství některé z výživných látek. Pomocí bodového grafu uvidíme, jestli může být mezi množstvím výživných látek nějaká souvislost. Vraťme se opět k výzkumu o kardiovaskulárním systému. Pro něj mohou být škodlivé nasycené kyseliny a cholesterol. Pomocí bodového grafu se můžeme podívat, jestli mají sýry s větším množstvím nasycených kyselin i větší množství cholesterolu. Graf doplníme popiskem, musíme pro něj využít mírně odlišnou syntaxi.
import seaborn as sns
cheese = food_nutrient_pivot[food_nutrient_pivot["branded_food_category"] == "Cheese"]
g = sns.JointGrid(cheese, x="Fatty acids, total saturated", y="Cholesterol")
g.plot_joint(sns.scatterplot)
g.fig.suptitle("Porovnání množství výživných látek v sýrech")
g.ax_joint.set_xlabel("Nasycené kyseliny")
g.ax_joint.set_ylabel("Cholesterol")
Výsledný graf je na obrázku níže.
Skupiny
Na zakládě nějaké číselné hodnoty můžeme data rozdělit i do skupin. Každá skupina potřebuje dvě věci:
- číselný interval, který udává rozsah pro zařazení do skupiny,
- označení skupiny.
Uvažujme následující skupiny.
Obsah cholesterolu | Kategorie |
---|---|
0-20 | Low Cholesterol |
20-100 | Moderate Cholesterol |
100-inf | High Cholesterol |
Každé potravině můžeme přiřadit popisek, která nám usnadní psaní dotazů.
bins = [0, 20, 100, float('inf')]
labels = ['Low Cholesterol', 'Moderate Cholesterol', 'High Cholesterol']
food_nutrient_pivot['Cholesterol Category'] = pd.cut(food_nutrient_pivot['Cholesterol'], bins=bins, labels=labels)
food_nutrient_pivot
Pokud bychom chtěli zkoumat množství cholesterolu v různých typech potravin, můžeme použít vizualizaci countplot
, kterou už jsme si ukazovali v minulé lekci. V grafu pak uvidíme, kolik je v každé skupině potravin s nízkým obsahem cholesterolu, se středním a vysokým.
top_cat_list = ['Candy', 'Popcorn, Peanuts, Seeds & Related Snacks', 'Cheese', 'Ice Cream & Frozen Yogurt', 'Chips, Pretzels & Snacks', 'Cookies & Biscuits', 'Pickles, Olives, Peppers & Relishes', 'Breads & Buns', 'Fruit & Vegetable Juice, Nectars & Fruit Drinks', 'Snack, Energy & Granola Bars', 'Chocolate', 'Other Snacks']
food_nutrient_pivot = food_nutrient_pivot[food_nutrient_pivot["branded_food_category"].isin(top_cat_list)]
sns.countplot(food_nutrient_pivot, y="branded_food_category", hue="Cholesterol Category")