A Pandas könyvtár

Mérési vagy szimulációs adatainkat gyakran célszerűbb a puszta számokat tartalmazó list vagy numpy.array adatszerkezet helyett a pandas könyvtár DataFrame osztályában tárolunk, ahol a számok mellett feliratozni is tudjuk a sorokat, illetve oszlopokat, illetve a különböző oszlopokban különböző adattípusok lehetnek.

A DataFrame-re gondolhatunk úgy, mint egy szokásos Excel-táblázatra, az osztályhoz tartozó függvények egy része ugyanis nagyon hasonlít a táblázatkezelőkből ismertekére. Használata első ránézésre talán bonyolultnak tűnhet, de mindenképpen megéri a befektetett energiát.

A szokásos import:


In [1]:
import pandas as pd

Beolvasás fájlból

Legtöbbször vesszővel vagy tabulátorral elválasztott értékeket (amit a sep kulcsszóval állíthatunk be, ha szükséges) olvasunk be egyszerű szövegfájlokból. Itt be kell állítanunk, hogy a táblázatunk tartalmaz-e fejlécet (header), illetve hogy a soroknak van-e nevük (index).

Az alapértelmezett beállítás megpróbálja kitalálni, hogy van-e fejléc, és a sorokat magától megszámozza.


In [2]:
pd.read_csv("data/kisnevsor.csv")


Out[2]:
Unnamed: 0 Eszter Orsi Nem Kor
0 Bálint 2 3 fiú 20
1 Csenge 4 4 lány 22
2 István 5 4 fiú 19
3 Zita 3 5 lány 20

Mi viszont azt szeretnénk, ha a legelső oszlopot a sorok neveiként olvasnánk be, mint az exceles esetben.


In [3]:
pd.read_csv("data/kisnevsor.csv",index_col=0)


Out[3]:
Eszter Orsi Nem Kor
Bálint 2 3 fiú 20
Csenge 4 4 lány 22
István 5 4 fiú 19
Zita 3 5 lány 20

Most a fejlécbeolvasót kikapcsoljuk. Így az első sor ismeretlen (NaN) sorfelirattal bekerül az értékek elé, az oszlopok pedig 0-tól számozódnak.


In [4]:
pd.read_csv("data/kisnevsor.csv",header=None,index_col=0)


Out[4]:
1 2 3 4
0
NaN Eszter Orsi Nem Kor
Bálint 2 3 fiú 20
Csenge 4 4 lány 22
István 5 4 fiú 19
Zita 3 5 lány 20

Ha elfelejtettük beállítani az oszlopok neveit eredetileg, utólag is megtehetjük azt a .set_index(oszlopnev) függvény segítségével. A set_index() függvény visszatérési értéke alapesetben az új oszloppal indexelt DataFrame.


In [ ]:
nevsor=pd.read_csv("data/kisnevsor.csv")
ujnevsor=nevsor.set_index("Unnamed: 0")

Ezt megtehettük volna úgy is, hogy a nevsor nevű DataFrame-et rögtön felülírjuk helyben (inplace):


In [ ]:
nevsor.set_index("Unnamed: 0",inplace=True)

Adatok elérése

A pandas a DataFrame-ben tárolt értékeket elsősorban a fejléccel és a sorok neveivel teszi elérhetővé.

Ha egy oszlop nevét stringként szögletes zárójelekben írjuk a DataFrame neve mögé, visszakapjuk az oszlopot.


In [5]:
df=pd.read_csv("data/kisnevsor.csv",index_col=0)
print(df["Eszter"])


Bálint    2
Csenge    4
István    5
Zita      3
Name: Eszter, dtype: int64

Ha több oszlopot is vissza szeretnénk kapni, akkor azokat egy stringeket tartalmazó listában írjuk a DataFrame mögötti szögletes zárójelbe.


In [6]:
df[["Eszter","Nem","Kor"]]


Out[6]:
Eszter Nem Kor
Bálint 2 fiú 20
Csenge 4 lány 22
István 5 fiú 19
Zita 3 lány 20

Ha egy oszlopnak szeretnénk elérni az egyik elemét:


In [7]:
print(df["Eszter"]["Zita"])


3

Vigyázat, mindig először az oszlop nevét írtuk! Ha egy sort szeretnénk visszakapni, az ix objektumot kell használunk.


In [8]:
df.ix["Zita"]


Out[8]:
Eszter       3
Orsi         5
Nem       lány
Kor         20
Name: Zita, dtype: object

Aki szeretné ugyanúgy számokkal indexelni a DataFrame-et, mint egy array-t, annak erre az iloc biztosít lehetőséget. Nézzük meg az előző eléréseket iloc-kal!


In [9]:
df.iloc[:,0] # az első (0.) oszlop


Out[9]:
Bálint    2
Csenge    4
István    5
Zita      3
Name: Eszter, dtype: int64

In [10]:
df.iloc[0,0]  # az első sor első eleme


Out[10]:
2

Sőt, a DataFrame belsejét átalakíthatjuk numpy array-jé, és alkalmazhatjuk rá a korábban tanult módszereket :-)


In [11]:
df.as_matrix()


Out[11]:
array([[2, 3, 'fiú', 20],
       [4, 4, 'lány', 22],
       [5, 4, 'fiú', 19],
       [3, 5, 'lány', 20]], dtype=object)

Az oszlopnevek és a sornevek elérése

Írassuk ki a táblázatunk oszlopainak a nevét!


In [12]:
df.columns


Out[12]:
Index(['Eszter', 'Orsi', 'Nem', 'Kor'], dtype='object')

Írassuk ki a táblázatunk sorainak a nevét!


In [13]:
df.index


Out[13]:
Index(['Bálint', 'Csenge', 'István', 'Zita'], dtype='object')

Szükség lehet rá, hogy a fenti listákat tényleg Python-féle list-ként kapjuk vissza.


In [14]:
df.columns.tolist()


Out[14]:
['Eszter', 'Orsi', 'Nem', 'Kor']

In [15]:
list(df.columns)


Out[15]:
['Eszter', 'Orsi', 'Nem', 'Kor']

Egyszerű sor- és oszlopműveletek

A DataFrame-re is könnyű néhány beépített függvény segítségével különböző aggregált értékeket számolni.

Például álljon itt oszloponként a számok összege:


In [16]:
df.sum()


Out[16]:
Eszter                14
Orsi                  16
Nem       fiúlányfiúlány
Kor                   81
dtype: object

Mit tegyünk, ha ezt soronként szeretnénk visszakapni? Változtassuk meg az összegzés "tengelyét" (axis)! Az előző eset ugyanis az alapértelmezett axis=0 volt, ami oszloponként végzi a műveletet. Csak a jegyeket tartalmazó oszlopokat összegezzük.


In [17]:
df[["Eszter","Orsi"]].sum(axis=1)


Out[17]:
Bálint    5
Csenge    8
István    9
Zita      8
dtype: int64

Számoltassuk meg, hány elem van az oszlopokban, illetve a sorokban!


In [18]:
df.count()


Out[18]:
Eszter    4
Orsi      4
Nem       4
Kor       4
dtype: int64

In [19]:
df.count(axis=1)


Out[19]:
Bálint    4
Csenge    4
István    4
Zita      4
dtype: int64

Ezt persze az array-hez hasonlóan is megtehettük volna:


In [20]:
df.shape


Out[20]:
(4, 4)

További ötletek beépített függvényekre: mean, median, min, max, std.

Boolean indexing

Nagyon gyakran előfordul, hogy a táblázatunkból csak bizonyos feltételeknek megfelelő sorokat szeretnénk látni. Ha a táblázat sorainak számával megegyező hosszú igaz/hamis sorozatot adunk meg a DataFrame mögötti szögletes zárójelben, akkor csak az igaz elemeket fogjuk visszakapni visszatérési értékként.

Először nézzük meg, mi történik, ha megkérdezzük, hogy egy oszlop egyenlő-e egy értékkel:


In [21]:
df["Nem"]=="lány"


Out[21]:
Bálint    False
Csenge     True
István    False
Zita       True
Name: Nem, dtype: bool

Láttuk, hogy minden sorhoz kaptunk egy igaz/hamis értéket. Most a fenti kifejezést beírjuk a []-be:


In [22]:
df[df["Nem"]=="lány"]


Out[22]:
Eszter Orsi Nem Kor
Csenge 4 4 lány 22
Zita 3 5 lány 20

De más feltételt is megadhatunk, például hogy kinek adott Eszter 3-asnál jobb jegyet.


In [23]:
df[df["Eszter"]>3]


Out[23]:
Eszter Orsi Nem Kor
Csenge 4 4 lány 22
István 5 4 fiú 19

Két feltételt összefűzhetünk egymáshoz, ilyenkor a & és a | operátorokat használjuk and és or helyett, mert azok nem tudnak két sorozatot elemenként összehasonlítani. A feltételeket zárójelbe kell tenni, különben hibát kapunk.

Ezek alapján az, akinek Eszter hármasnál jobbat adott, és idősebb 20 évesnél:


In [24]:
df[(df["Eszter"]>3) & (df["Kor"]>20)]


Out[24]:
Eszter Orsi Nem Kor
Csenge 4 4 lány 22

Sorba rendezés

Szükségünk lehet arra, hogy a táblázatunkat sorba rendezzük valamelyik oszlop szerint. Ilyenkor a sort_values(by="oszlop_neve") függvényt használjuk, melynek megadhatjuk, hogy növekvő (ascending=True), vagy csökkenő (ascending=False) sorrendben szeretnénk-e a rendezést.

A függvény visszatérési értéke a rendezett táblázat.


In [25]:
df.sort_values(by="Kor",ascending=False)


Out[25]:
Eszter Orsi Nem Kor
Csenge 4 4 lány 22
Bálint 2 3 fiú 20
Zita 3 5 lány 20
István 5 4 fiú 19

Ha azt szeretnénk, hogy az eredeti DataFrame-ben rendezve tárolódjanak el a sorok, be kell kapcsolnunk az inplace=True paramétert, ami felülírja a DataFrame-et a rendezés után.


In [26]:
df.sort_values(by="Kor",ascending=False,inplace=True)

Persze, ezt elérhettük volna szokásos értékadással is.


In [27]:
df=df.sort_values(by="Kor",ascending=False)

Ha a DataFrame indexe szerint szeretnénk sorba rendezni, akkor a sort_index() függvény segít (itt is választhatjuk, hogy helyben szeretnénk-e a rendezést az inplace=True segítségével):


In [28]:
df.sort_index(inplace=True)

Új sor/oszlop hozzáadása, törlés

Ha új sort szeretnénk hozzáadni a táblázathoz, akkor a .loc["Új_sor_indexe"] változónak egy, az oszlopok számával megegyező hosszúságú listát kell odaadnunk.


In [29]:
df.loc["Dávid"]=[5,5,"fiú",20]
df


Out[29]:
Eszter Orsi Nem Kor
Bálint 2 3 fiú 20
Csenge 4 4 lány 22
István 5 4 fiú 19
Zita 3 5 lány 20
Dávid 5 5 fiú 20

Ha új oszlopot, akkor hasonlóan járunk el, de nem szükséges a loc, mert az a sorokat indexeli.


In [30]:
df["Emelt"]=[0,0,1,1,0]
df


Out[30]:
Eszter Orsi Nem Kor Emelt
Bálint 2 3 fiú 20 0
Csenge 4 4 lány 22 0
István 5 4 fiú 19 1
Zita 3 5 lány 20 1
Dávid 5 5 fiú 20 0

Ha sort szeretnénk törölni, a drop függvénnyel tehetjük meg.


In [31]:
df.drop("Bálint",inplace=True)
df


Out[31]:
Eszter Orsi Nem Kor Emelt
Csenge 4 4 lány 22 0
István 5 4 fiú 19 1
Zita 3 5 lány 20 1
Dávid 5 5 fiú 20 0

Elég ritkán, de szeretnénk a táblázatunkból oszlopokat törölni:


In [32]:
del df["Kor"] #ritkán

In [33]:
df["Kor"]=[22,19,20,20]

Csoportosítás

Egy oszlop értékei szerint csoportosíthatjuk a DataFrame-et, és utána a csoportokon végezhetünk műveleteket.

Például az emelt szintű érettségit tevők (1), illtve nem tevők (0) maximum jegyeit láthatjuk a következő sorban.

Figyeljük meg, hogy a Nem oszlop maximális értéke mindkét csoportban a "lány", hiszen az hátrébb áll az abc-ben, mint a fiú.


In [34]:
df.groupby("Emelt").max()


Out[34]:
Eszter Orsi Nem Kor
Emelt
0 5 5 lány 22
1 5 5 lány 20

Egyszerre két oszlop szerint is csoportosíthatunk, ilyenkor listát kell a groupby-nak átadnunk. Itt már nem csak az Emelt oszlop, hanem a Nem oszlop is a táblázat indexének a része, ezt hívjuk többszintű indexelésnek. A továbbiakban az órán erre nem lesz szükség, csak a példa kedvéért áll itt.


In [35]:
df.groupby(["Emelt","Nem"]).max()


Out[35]:
Eszter Orsi Kor
Emelt Nem
0 fiú 5 5 20
lány 4 4 22
1 fiú 5 4 19
lány 3 5 20

Érettségi adatok feldolgozása

Az alábbiakban az elmúlt pár év érettségi statisztikai adatait fogjuk megvizsgálni. Ez a példa sok szempontból jól illusztrál olyan problémákat, amelyek valós adatbázis-elemzések kapcsán felmerülhetnek. Ilyen például a hiányzó adatok kezelése, vagy a nem egészen kompatibilis adatbázisok egységes kezelése. Az érettségi adatokat a fenti honlap az előzőekben megismert elválasztóval tagolt tagolt (comma separated value, röviden csv) formátumban teszi elérhetővé, itt az elválasztójel a pontosvessző.

Mivel ékezetes karakterek is vannak a fájlban, át kell állítanunk a karakterkódolást is a beolvasásnál. Az értékeket a sorokban a ";" karakter választja el, a sorok nevei a 0. oszlopban vannak.


In [36]:
erettsegi_adat=pd.read_csv("data/erettsegi.csv.gz",encoding="utf8",sep=";",index_col=0)

Listáztassuk ki, milyen oszlopnevek vannak a fájlban!


In [37]:
print("\n".join(erettsegi_adat.columns.tolist()))


intézmény megyéje
intézmény városa
vizsgázó évfolyama
vizsgázó képzési típusa
vizsgázó neme
vizsgázó képzési munkarendje
vizsgatárgy neve
vizsga szintje
vizsga fajtája
vizsgamentesség
vizsga nyelve
érdemjegy
össz százalék
össz pontszám
vizsgázó részvétele
I. feleletválasztós kérdéssor
II. esszé: tartalom
II. esszé:  kifejtés módja
III. összetett feladatok
írásbeli pontszám
mérés és tételkifejtés: tartalmi helyesség
mérés és tételkifejtés: felépítés, kifejtés
szóbeli pontszám
év
szint
időszak
egy téma kifejtése kísérlettel vagy méréssel: tartalom
egy téma kifejtése kísérlettel vagy méréssel: felépítés, kifejtés
II. összetett feladatok

Látható, hogy az év, szint megadják, hogy melyik évben, melyik szintű érettségiről van szó. Azt is megállapíthatjuk, hogy ősszel vagy tavasszal (időszak) írta-e a diák az érettségit, az iskolájáról és a képzési típusról is rögzítve van a statisztika. Emellett részletes írásbeli és szóbeli, illetve összpontszám, összesített százalék is szerepel az adatok között.

Érdemes az első néhány sort kiíratni példaként, hogy lássuk, mivel is van dolgunk. Most transzponálva írjuk ki, hogy elférjen a képernyőre.


In [38]:
erettsegi_adat.head().transpose()


Out[38]:
0 1 2 3 4
intézmény megyéje Budapest Budapest Budapest Budapest Budapest
intézmény városa Budapest Budapest Budapest Budapest Budapest
vizsgázó évfolyama 12 12 12 13 12
vizsgázó képzési típusa gimnázium gimnázium gimnázium gimnázium gimnázium
vizsgázó neme férfi férfi férfi
vizsgázó képzési munkarendje nappali nappali nappali nappali nappali
vizsgatárgy neve fizika fizika fizika fizika fizika
vizsga szintje közép közép közép közép közép
vizsga fajtája elõrehozott elõrehozott elõrehozott elõrehozott elõrehozott
vizsgamentesség - - - - -
vizsga nyelve magyar magyar magyar magyar magyar
érdemjegy 1 1 5 3 5
össz százalék 26 19 97 40 84
össz pontszám 40 29 146 61 126
vizsgázó részvétele nem jelent meg nem jelent meg megjelent megjelent megjelent
I. feleletválasztós kérdéssor NaN NaN 38 14 24
II. esszé: tartalom NaN NaN NaN NaN NaN
II. esszé: kifejtés módja NaN NaN NaN NaN NaN
III. összetett feladatok NaN NaN NaN NaN NaN
írásbeli pontszám NaN NaN 86 23 66
mérés és tételkifejtés: tartalmi helyesség NaN NaN NaN NaN NaN
mérés és tételkifejtés: felépítés, kifejtés NaN NaN NaN NaN NaN
szóbeli pontszám NaN NaN 60 38 60
év 2013 2013 2013 2013 2013
szint K K K K K
időszak tavasz tavasz tavasz tavasz tavasz
egy téma kifejtése kísérlettel vagy méréssel: tartalom NaN NaN 55 36 55
egy téma kifejtése kísérlettel vagy méréssel: felépítés, kifejtés NaN NaN 5 2 5
II. összetett feladatok NaN NaN 48 9 42

Itt aztán már tényleg nagy hasznát vesszük a fentebb tanult csoportosítási, aggregálási műveleteknek, a következőkben felteszünk néhány példakérdést, és megválaszoljuk azt.

  • Melyik évben mennyi volt az emelt szintű érettségik jegyeinek átlaga?

Ehhez először kiválasztjuk az emelt szintű érettségit tartalmazó sorokat, majd azokat év szerint csoportosítjuk. Kiválasztjuk az "érdemjegy" oszlopot, amit a végén átlagolunk. A csoportosítás miatt az átlag évenként kerül kiszámítása.


In [39]:
erettsegi_adat[erettsegi_adat["szint"]=="E"].groupby("év")["érdemjegy"].mean()


Out[39]:
év
2011    4.125000
2012    4.429338
2013    4.232607
2014    4.404090
2015    4.432165
Name: érdemjegy, dtype: float64
  • Vajon a fiúk vagy a lányok írtak jobb pontszámú középszintű érettségit 2015-ben?

A "\" jel csak azért kell, hogy ne írjunk túl hosszú sorokat a Pythonnak, mert az nehéz lenne elolvasni. Ha ilyen jelet teszel a sor végére, akkor az értelmező úgy olvassa, mintha a következő sor a "\" jel helyére lenne fűzve.

Először logikai indexeléssel kiválasztjuk a 2015-ös középszintű érettségiket tartalmazó sorokat. Több feltételt a sorokra egyszerre az and operátor helyett az & operátorral adhatunk meg, és a feltételeket zárójeleznünk kell, hogy jól olvassa az értelmező.

Ezek után csoportosítunk a vizsgázó neme szerint, majd vesszük az összpontszámok átlagát.


In [40]:
erettsegi_adat[
    (erettsegi_adat["szint"]=="K") &\
    (erettsegi_adat["év"]==2015)].\
groupby("vizsgázó neme")["össz pontszám"].mean()


Out[40]:
vizsgázó neme
férfi    100.270135
nõ        97.180775
Name: össz pontszám, dtype: float64
  • Számoljuk le, melyik iskolatípusban hány érettségiző jelent meg, illetve nem jelent meg!

Most egyszerre két oszlop szerint is csoportosítottunk, a csoportosítás alapját képező oszlopok nevét listaként kell megadni a groupby-nak. Utána egy tetszőleges oszlopot (pl. év) kiválasztva megszámláltathatjuk csoportonként a sorokat a count-tal.


In [41]:
erettsegi_adat.groupby(["vizsgázó képzési típusa", "vizsgázó részvétele"])["év"].count()


Out[41]:
vizsgázó képzési típusa  vizsgázó részvétele
-                        megjelent               1260
                         nem jelent meg           490
gimnázium                megjelent              14448
                         nem jelent meg           551
szakközép                megjelent               5007
                         nem jelent meg           134
Name: év, dtype: int64

Ábrázolás

A pandas nagy erőssége, hogy a DataFrame-ekből nagyon rövid szintaxissal lehet egészen elfogadható ábrákat készíteni. Ehhez a pandas a matplotlib könyvtárat használja, melyet emiatt be is kell importálnunk.


In [42]:
%pylab inline


Populating the interactive namespace from numpy and matplotlib

Az ábra paramétereit (title, ylabel stb.) a matplotlibben megszokott módon állíthatjuk be.

Elsőként növeljük meg alapértelmezetten a tengelyfeliratokat:


In [43]:
rcParams["font.size"]=15

Nézzük meg ábrán is az emelt szintű érettségik évenkénti átlagát! Ehhez csak a fenti parancs végére hozzá kell fűznünk a "plot" szócskát. Az oszlopdiagram rajzolásához megadhatjuk a plot függvénynek a kind kulcsszóval, hogy kind="bar". Az x tengely feliratai a DataFrame indexei lesznek, de az y tengelynek már mi kell, hogy nevet adjunk.


In [44]:
erettsegi_adat[erettsegi_adat["szint"]=="E"].groupby("év")["érdemjegy"].mean().plot(kind="bar", figsize=(12, 9))
ylabel("Emelt szint átlag")
ylim(0,5)


Out[44]:
(0, 5)

Megnézhetjük kördiagramon, hogy melyik iskolatípusból hányan érettségiztek közép- és emelt szinten 2011 és 2015 között. Ehhez két alábrát készítünk a múltkor tanultakhoz hasonlóan.

Vajon mit csinált az autopct kulcsszó?


In [45]:
subplot(1,2,1)
erettsegi_adat[
    (erettsegi_adat["vizsgázó részvétele"]=="megjelent") &\
    (erettsegi_adat["szint"]=="K")]\
    .groupby(["vizsgázó képzési típusa"])\
    .size()\
    .plot(kind="pie",autopct='%.1f',figsize=(20,10))
title("Középszint")

subplot(1,2,2)
erettsegi_adat[
    (erettsegi_adat["vizsgázó részvétele"]=="megjelent") &\
    (erettsegi_adat["szint"]=="E")]\
    .groupby(["vizsgázó képzési típusa"])\
    .size()\
    .plot(kind="pie",autopct='%.1f',figsize=(20,10))
title("Emelt szint")


Out[45]:
<matplotlib.text.Text at 0x7f2fc4c2a198>

☠ Haladóknak

Összefűzés, join

Két DataFrame-et összefűzhetünk egymás alá, ha a pd.concat() függvénynek egy ugyanannyi oszlopból álló DataFrame-eket tartalmazó listát adunk oda.

Példánkban kétszer egymás alá írjuk ugyanazt a DataFrame-et.


In [46]:
pd.concat([df,df])


Out[46]:
Eszter Orsi Nem Emelt Kor
Csenge 4 4 lány 0 22
István 5 4 fiú 1 19
Zita 3 5 lány 1 20
Dávid 5 5 fiú 0 20
Csenge 4 4 lány 0 22
István 5 4 fiú 1 19
Zita 3 5 lány 1 20
Dávid 5 5 fiú 0 20

Létrehozunk egy másik DataFrame-et, és egy Énekkar nevű oszlopot teszünk bele az előző DataFrame indexeivel.


In [47]:
import numpy as np
df2=pd.DataFrame(np.array([[0,1,1,1]]).transpose(),columns=["Énekkar"],index=df.index)
df2


Out[47]:
Énekkar
Csenge 0
István 1
Zita 1
Dávid 1

Hogyan tudnánk ezt az oszlopot hozzáilleszteni az előző táblázathoz? Megtehetjük concat segítségével, de át kell állítanunk, hogy melyik irányban fűzzük össze a két táblázatot (axis=1 jelenti, hogy az oszlopok mellé szeretnénk írni).


In [48]:
pd.concat([df,df2],axis=1)


Out[48]:
Eszter Orsi Nem Emelt Kor Énekkar
Csenge 4 4 lány 0 22 0
István 5 4 fiú 1 19 1
Zita 3 5 lány 1 20 1
Dávid 5 5 fiú 0 20 1

Megtehetnénk azt is, hogy elkészítjük a két táblázat Descartes-szorzatát, azaz az egyikből minden sort összepárosítunk a másik minden sorával, majd kiválogatjuk ebből a sorhalmazból csak azokat a sorokat, amelyekben az indexek megegyeznek.

(Aki ismeri az SQL-nyelv join parancsát, ez az ún. inner join.)


In [49]:
pd.merge(df,df2,left_index=True,right_index=True)


Out[49]:
Eszter Orsi Nem Emelt Kor Énekkar
Csenge 4 4 lány 0 22 0
István 5 4 fiú 1 19 1
Zita 3 5 lány 1 20 1
Dávid 5 5 fiú 0 20 1

Contains

Ha egy stringeket tartalmazó oszlopban végig kell néznünk, hogy megvan-e valamilyen karaktersorozat:


In [50]:
df["Nem"].str.contains("án")


Out[50]:
Csenge     True
István    False
Zita       True
Dávid     False
Name: Nem, dtype: bool

Apply

Ha egy tetszőleges függvényt szeretnénk egy oszlop minden egyes elemére alkalmazni, megtehetjük az apply segítségével. Az apply belsejébe írjuk a függvényt, amit alkalmazni szeretnénk.

Elsőként például készítünk egy függvényt, ami egy számhoz hozzáad egyet:


In [51]:
def hozzaad(x):
    return x+1

Ezek után mindenkit öregítünk egy évvel.


In [52]:
df["Kor"].apply(hozzaad)


Out[52]:
Csenge    23
István    20
Zita      21
Dávid     21
Name: Kor, dtype: int64

Az apply-t is lehet soronként is végeztetni az axis=1 kulcsszó segítségével. Például írjuk meg kézzel azt a függvényt, ami a két kapott jegy átlagát kiszámolja.


In [53]:
def atlag(sor):
    return (sor["Eszter"]+sor["Orsi"])/2

In [54]:
df.apply(atlag,axis=1)


Out[54]:
Csenge    4.0
István    4.5
Zita      4.0
Dávid     5.0
dtype: float64

Pivot

Új táblázatot is készíthetünk összesített eredmények alapján az eredetiből. Hogy legyen valami látható eredményünk, adjuk még hozzá Károlyt a táblázatunkhoz.


In [55]:
df.loc["Károly"]=[4,5,"fiú",1,20]

Most megnézzünk nemenként és emelt szintű érettségi szerint, hogy melyik kategóriában hány ember van. Mivel a csoportosítás készít nekünk egy többszintű indexet, ezt kiiktatjuk a reset_index(inplace=True) parancs segítségével.


In [56]:
p=df.groupby(["Nem","Emelt"]).count()
p.reset_index(inplace=True)
p


Out[56]:
Nem Emelt Eszter Orsi Kor
0 fiú 0 1 1 1
1 fiú 1 2 2 2
2 lány 0 1 1 1
3 lány 1 1 1 1

Készítsünk egy táblázatot, melyben a sorok a nemek, az oszlopok, hogy tett-e valaki emelt szintű érettségit, és az értékek a kategóriák leszámlálásai:


In [57]:
p.pivot_table(values="Eszter",columns="Emelt",index="Nem")


Out[57]:
Emelt 0 1
Nem
fiú 1 2
lány 1 1