Arvutiteaduse instituut
  1. Kursused
  2. 2017/18 kevad
  3. Programmeerimise alused II (LTAT.TK.001)
EN
Logi sisse

Programmeerimise alused II 2017/18 kevad

  • Kursuse info
  • 1. Kahemõõtmeline järjend
  • 2. Kahekordne tsükkel
  • 3. Andmestruktuurid
  • 4. Viitamine ja muteerimine
  • 5. Testimine ja silumine. Rekursioon
  • 6. Rekursioon II
  • Korraldajad
V OSA sisukord

5.4 ANDMETÖÖTLUS MOODULIGA PANDAS

Sissejuhatus

Elame ajastul, kus kogutakse hulgaliselt erinevaid andmeid. Ühelt poolt sisaldab see näiteks ohte privaatsusele, teiselt poolt aga annab võimalusi õigemaid otsuseid teha. Otsustamiseks või ka lihtsalt millestki parema ülevaate saamiseks tuleb andmeid mõistlikult töödelda. Andmetöötluseks on väga erinevaid vahendeid, millest käesoleval kursusel kasutame Pythoni moodulit pandas. Selle nädala materjalides tutvustatakse pandast ja vaadeldakse andmeid teatrikülastuste kohta. Ülesanne on aga raamatukogude kohta. Andmed on saadud statistikaameti veebilehelt, kus on tohutult palju erinevaid andmeid. Valmis andmeid on võimalik saada ka mitmetest muudest kohtadest. Samuti on võimalik ise andmeid koguda, näiteks pulsikella abil. Natuke etteruttavalt võib öelda, et 7. ja 8. nädalal tehtav projekt võib põhineda andmetöötlusel. Seega on need materjalid ka projekti ettevalmistuseks.

Kuna pandase kasutamise kohta eriti palju eestikeelseid materjale pole ja pole ka väljakujunenud eestikeelset terminoloogiat, on materjalides kasutatud mõningaid otsemugandusi, nt seeria (Series), andmefreim (DataFrame). Andmetöötluse materjalid on seotud Inga Konovalova bakalaureusetööga. Tema hoiab silma peal ka vastaval foorumil ning kohendab soovituste põhjal materjale.

Installeerimine

Kursusel Programmeerimise alused II kasutavad paljud osalejad Pythonis programmide kirjutamiseks keskkonda Thonny. Vaatamegi, kuidas Thonnys installeerida Pythoni andmetöötluseks mõeldud moodul pandas.

Pandase paigaldamiseks tuleb Thonny ülamenüüst valida Tools --> Manage packages ja otsingusse kirjutada pandas ning vajutada nuppu Install.

Kui te ei kasuta Thonnyt, siis võib pandase installeerimine olla mõnevõrra keerulisem. Windowsi käsurealt saab pandase installeerida käsuga py -m pip install pandas

Jupyter notebookis saab pandase installeerida reaga: !pip install pandas. Lisainfot installeerimise kohta saab pandase veebilehelt.

Koos pandasega installitakse ka moodul NumPy. Tegelikult saaks pelgalt NumPy abiga andmeid töödelda, kuid pandases on rohkem funktsioone ning andmete töötlemine on mugavam. Mooduliga NumPy saab soovi korral tutvuda siin.

Graafikute tegemiseks läheb vaja moodulit Matplotlib, mille installeerimine on sama nagu pandase oma:

Thonnys paigaldamiseks tuleb ülamenüüst valida Tools --> Manage packages ja otsingusse kirjutada matplotlib ning vajutada nuppu Install.

Windowsi käsurealt saab Matplotlib installeerida käsuga py -m pip install matplotlib.

Jupyter notebookis tuleks kasutada koodirida: !pip install matplotlib.

Andmestruktuurid

Pandase kohta leidub väga vähe eestikeelseid materjale ja terminoloogia on lünklik. Kasutame siin materjalides ingliskeelseid termineid ja nende toortõlkeid: seeria, andmefreim ja paneel.

Pandases on andmete hoidmiseks 3 põhilist andmestruktuuri:

  • Series - seeria
  • DataFrame - andmefreim
  • Panel - paneel

Enimkasutatav andmestruktuur on andmefreim ning ka nendes materjalides keskendutakse sellele. Esmalt aga tutvustatakse seeriaga.

Seeria (Series)

Seeria (Series) on ühemõõtmeline, sarnastest andmetest koosnev, muutumatu suurusega andmestruktuur. Sellest võib mõelda ka kui kindla suurusega sõnastikust, milles igale võtmele vastab kindel väärtus.

Erinevus sõnastiku ja seeria vahel

Struktuuri poolest meenutab seeria kõige rohkem sõnastikku. Andmeid hoitakse siltidega seostatuna ja vajadusel võib kindla elemendi sildi järgi kätte saada. See meenutab sõnastiku võtme ja väärtuse süsteemi.

Sõnastiku puhul

isikud_sonastik = {'Võistleja nr 1': 'Mari', 'Võistleja nr 2': 'Joonas', 'Võistleja nr 3': 'Kati'} 
print(isikud_sonastik)

saame

{'Võistleja nr 1': 'Mari', 'Võistleja nr 2': 'Joonas', 'Võistleja nr 3': 'Kati'}

Seeria puhul

import pandas as pd
isikud_seeria = pd.Series({'Võistleja nr 1': 'Mari', 'Võistleja nr 2': 'Joonas', 'Võistleja nr 3': 'Kati'}) 
print(isikud_seeria)

aga

Võistleja nr 1    Mari
Võistleja nr 2    Joonas
Võistleja nr 3    Kati
dtype: object

Sõnastikku tasub kasutada juhul, kui on soov andmeid võtmete ja väärtuste paaridena hoida ning pole vajadust edaspidise põhjalikuma andmete töötluse järele. Andmetöötluse jaoks sobib paremini seeria, sest sellel on rohkem funktsioone (aritmeetilised tehted, sorteerimine, filtreerimine jne). Tegevused toimuvad ka efektiivsemalt ning kood on lihtsam.

Näitena vaadeldakse seeriat, milles hoitakse õpilaste arvusid klasside kaupa.

import pandas as pd
import matplotlib.pyplot as plot

klassid = pd.Series([24, 23, 21, 22, 28, 26, 30, 28, 31, 35, 33, 32, 29, 27, 25, 30, 26, 31, 22], 
index = ['1a', '1b', '2', '3a', '3b', '4a', '4b', '5', '6a', '6b', '7', '8', '9', '10 reaal', '10 sotsiaal', '11 reaal', '11 sotsiaal', '12 reaal', '12 sotsiaal'], name = 'Õpilaste arv klassis')
print(klassid)

Seeria puhul loetakse veeruks vaid andmete veergu ja seal asuvaid andmeid töödeldakse. Siltide veerg on vajalik konkreetsetele andmetele viitamiseks.

Illustreerime ülaltoodud andmeid graafikul.

klassid.plot.bar(title = 'Õpilaste arvud klasside kaupa')
plot.show()

Täpsemalt saab graafikute loomise ja kujundamise kohta infot materjalide lõpuosas esitatud näitest ja näiteks ingliskeelsest materjalist.

Sarnasus järjendi ja seeria vahel

Seeria on teatud mõttes sarnane tavalise järjendiga. Järgmises näites on püütud järjendile eriti sarnane seeria tekitada.

import pandas as pd 
järjend = ['a', 'b', 'c', 'd'] 
print(järjend) 
print('Element indeksiga 0 järjendis on:', järjend[0])

Ekraanile ilmub siis

['a', 'b', 'c', 'd'] 
Element indeksiga 0 järjendis on: a

Anname ka seerias samad indeksid

seeria = pd.Series(['a', 'b', 'c', 'd'], index = [0, 1, 2, 3]) 
print(seeria) 
print('Element sildiga 0 seerias on:', seeria[0])

Nüüd saame ekraanile

0   a 
1   b 
2   c 
3   d 
dtype: object
Element sildiga 0 seerias on: a


Nii seeria kui järjendi puhul on konkreetsele elemendile lisatud viide, mille järgi saab vajadusel elemendi kätte. Järjendis on elementidel järjekorranumbrid ehk indeksid 0, 1, 2, ..., n. Seeria puhul on lisaks indeksitele tegemist siltidega (ingl label), mille kasutaja saab ise määrata. Sildid ei pruugi olla alati järjestikused ja isegi mitte arvud. Klasside õpilaste arvu näites polnud näiteks arvud.

Uue seeria loomine

Uue Series-tüüpi andmestruktuuri saab luua järgmiselt.

pandas.Series(data, index, dtype, copy)

Kõiki parameetreid ei pea defineerimisel kasutama, mingi parameetri ärajätmisel kasutatakse selle vaikimisi määratud väärtust. Kui näiteks ära jätta data, kuid lisada siltide järjend, siis genereeritakse seeria, mille igale sildile vastab spetsiaalne väärtus NaN (Not a Number).

Järgmine tabel kirjeldab, mis tüüpi väärtused igale parameetrile saab anda ja mida need tähendavad.

ParameeterSelgitus
dataAndmed võivad olla järjendi, sõnastiku või konstandi (üks element) kujul. Näiteks pandas.Series({'Mari': '12', 'Karmo': '15', 'Malle': '20'}, …) või pandas.Series(['punane', 'kollane', 'sinine'], …) või pandas.Series('a', ...)
indexSiltide järjend. Vaikimisi määratakse siltideks arvud 0, 1, 2,..., n-1, kus n on elementide arv parameetriga data lisatud andmestruktuuris.
dtypeAndmete tüüp, mida seerias hoitakse. Vaikimisi tuvastatakse tüüp antud andmetest. Näiteks kui hoitakse seerias ujukomaarve, siis vaikimisi määratakse tüübiks float.
copyMäärab, kas andmetest, mida kasutatakse, tehakse koopia. Vaikimisi väärtus false.

Lisaks tabelis olevatele parameetritele, võib kasulikuks osutuda ka name, mille lisamisel saab seeriale määrata nime.

Vaatame ülaltoodud klasside ja õpilaste näidet uuesti ning analüüsime selle seeria loomist:

klassid = pd.Series([24, 23, 21, 22, 28, 26, 30, 28, 31, 35, 33, 32, 29, 27, 25, 30, 26, 31, 22], #andmed ehk data
index = ['1a', '1b', '2', '3a', '3b', '4a', '4b', '5', '6a', '6b', '7', '8', '9', '10 reaal', '10 sotsiaal', '11 reaal', '11 sotsiaal', '12 reaal', '12 sotsiaal'], #sildid
name = 'Õpilaste arv klassis') #seeriale antud nimi

Siltide arv (antud juhul klasside arv) peab olema võrdne parameetriga data antud andmestruktuuri elementide arvuga ehk õpilaste arvude arvuga. Antud juhul on meil tegemist 19 erineva klassiga ning järelikult ka õpilaste arvusid peab olema andmete järjendis 19. Parameetri name abil on seeriale lisatud nimeks “Õpilaste arv klassis”. Muudele parameetritele määrati väärtused vaikimisi.

Loodud seeria näeb ekraanile väljastatuna välja niisugune.

1a             24
1b             23
2              21
3a             22
3b             28
4a             26
4b             30
5              28
6a             31
6b             35
7              33
8              32
9              29
10 reaal       27
10 sotsiaal    25
11 reaal       30
11 sotsiaal    26
12 reaal       31
12 sotsiaal    22
Name: Õpilaste arv klassis, dtype: int64

Andmete tüübiks on vaikimisi määratud int64, sest õpilaste arvude näol on tegemist täisarvudega.


Erandjuhuna saab seeria luua nii, et loomisel on lisatud vaid üks väärtus ja näiteks 4 silti. Sel juhul korratakse seda ühte väärtust 4 korda ning luuakse 4 sama väärtusega elementi.

import pandas as pd 
seeria = pd.Series(7, index = [0, 2, 4, 6]) 
print(seeria)

Ekraanile saame

0   7 
2   7 
4   7 
6   7 
dtype: int64

Sildid võivad olla arvud, sõned või mingit muud mittemuteeritavat tüüpi.

seeria = pd.Series([7, 'Tartu Ülikool', 3.14, -1789710578, 'Informaatika!'], index = ['A', '2', 'C', '4', 'E'])
print(seeria)

Väljund

A    7 
2    Tartu Ülikool 
C    3.14 
4    -1789710578 
E    Informaatika! 
dtype: object

Ülaltoodud näidetes loodi seeriad kasutades järjendit või konstanti (ühte elementi). Lisatavad andmed võivad olla ka sõnastikus.

import pandas as pd
dict_isikud = {'Võistleja nr 1' : 'Mari','Võistleja nr 2': 'Joonas','Võistleja nr 3': 'Kati'} 
seeria = pd.Series(dict_isikud)
print(seeria)

Väljund

Võistleja nr 1    Mari 
Võistleja nr 2    Joonas 
Võistleja nr 3    Kati 
dtype: object

Selleks, et tutvuda osaga võimalustest, mida seeria kasutamine andmete töötlemiseks annab, võtame ette juba tuttava klasside õpilaste arvude näite.

import pandas as pd

klassid = pd.Series([24, 23, 21, 22, 28, 26, 30, 28, 31, 35, 33, 32, 29, 27, 25, 30, 26, 31, 22], 
index = ['1a', '1b', '2', '3a', '3b', '4a', '4b', '5', '6a', '6b', '7', '8', '9', '10 reaal', '10 sotsiaal', '11 reaal', '11 sotsiaal', '12 reaal', '12 sotsiaal'], name = 'Õpilaste arv klassis') 
print(klassid)
1a             24
1b             23
2              21
3a             22
3b             28
4a             26
4b             30
5              28
6a             31
6b             35
7              33
8              32
9              29
10 reaal       27
10 sotsiaal    25
11 reaal       30
11 sotsiaal    26
12 reaal       31
12 sotsiaal    22
Name: Õpilaste arv klassis, dtype: int64

Oletame, et meil on vaja eraldada ainult algklasside õpilaste arvud. Seda saab teha kahel moel, kasutades andmete asukohta seerias või silte. Asukoha järgi saab andmeid eraldada seetõttu, et lisaks siltidele, on igal elemendil olemas ka indeks, mis tähistab numbriliselt elemendi asukohta seerias. Nagu ka järjendis, on indeksiteks arvud 0, 1, 2, ..., n-1, kus n tähistab elementide arvu seerias.

import pandas as pd

klassid = pd.Series([24, 23, 21, 22, 28, 26, 30, 28, 31, 35, 33, 32, 29, 27, 25, 30, 26, 31, 22], 
index = ['1a', '1b', '2', '3a', '3b', '4a', '4b', '5', '6a', '6b', '7', '8', '9', '10 reaal', '10 sotsiaal', '11 reaal', '11 sotsiaal', '12 reaal', '12 sotsiaal'], name = 'Õpilaste arv klassis') 
algklassid = klassid[['1a', '1b', '2', '3a', '3b', '4a', '4b', '5', '6a', '6b']]
print(algklassid)

Ja teistmoodi

import pandas as pd

klassid = pd.Series([24, 23, 21, 22, 28, 26, 30, 28, 31, 35, 33, 32, 29, 27, 25, 30, 26, 31, 22], 
index = ['1a', '1b', '2', '3a', '3b', '4a', '4b', '5', '6a', '6b', '7', '8', '9', '10 reaal', '10 sotsiaal', '11 reaal', '11 sotsiaal', '12 reaal', '12 sotsiaal'], name = 'Õpilaste arv klassis') 
algklassid = klassid[0:10]
print(algklassid)

Tulemus tuleb mõlemal juhul täpselt sama.

1a    24
1b    23
2     21
3a    22
3b    28
4a    26
4b    30
5     28
6a    31
6b    35
Name: Õpilaste arv klassis, dtype: int64

Järgmisena vaatame, mitu klassi kokku on meil seerias, selleks kasutame .size tunnust.

import pandas as pd

klassid = pd.Series([24, 23, 21, 22, 28, 26, 30, 28, 31, 35, 33, 32, 29, 27, 25, 30, 26, 31, 22], 
index = ['1a', '1b', '2', '3a', '3b', '4a', '4b', '5', '6a', '6b', '7', '8', '9', '10 reaal', '10 sotsiaal', '11 reaal', '11 sotsiaal', '12 reaal', '12 sotsiaal'], name = 'Õpilaste arv klassis') 
print(klassid.size)

Väljastatakse 19.

Tihti on vaja andmeid mingis kindlas järjekorras sorteerida, sorteerime klassid õpilaste arvude järgi kahanevas järjekorras funktsiooni .sort_values() abil. Samuti saab sorteerida ka siltide järgi funktsiooni .sort_index() abil.

import pandas as pd

klassid = pd.Series([24, 23, 21, 22, 28, 26, 30, 28, 31, 35, 33, 32, 29, 27, 25, 30, 26, 31, 22], 
index = ['1a', '1b', '2', '3a', '3b', '4a', '4b', '5', '6a', '6b', '7', '8', '9', '10 reaal', '10 sotsiaal', '11 reaal', '11 sotsiaal', '12 reaal', '12 sotsiaal'], name = 'Õpilaste arv klassis')
klassid_kahanevalt = klassid.sort_values(ascending=False)
print(klassid_kahanevalt)
6b             35
7              33
8              32
12 reaal       31
6a             31
11 reaal       30
4b             30
9              29
3b             28
5              28
10 reaal       27
11 sotsiaal    26
4a             26
10 sotsiaal    25
1a             24
1b             23
3a             22
12 sotsiaal    22
2              21
Name: Õpilaste arv klassis, dtype: int64

Mõnikord on vaja lisada seeriasse andmeid juurde. Vaatame, kuidas saab kahe seeria andmed ühendada. Lisame juurde õpetajate arvu, õpilaste arvu kokku ja klasside arvu kokku. Selleks loome uue Series-tüüpi andmestruktuuri, mille andmeteks on järjend õpetajate arvuga, õpilaste arvuga kokku ja klasside arvuga kokku ning mille siltideks on ‘Õpetajate arv’, ‘Õpilaste arv kokku’ ja ‘Klasside arv kokku’. Õpilaste arvu kokku saame kasutades .sum() funktsiooni klasside seeria peal ning klasside arvu kokku leiame atribuudiga .size, mida kasutasime ka varem.

import pandas as pd

klassid = pd.Series([24, 23, 21, 22, 28, 26, 30, 28, 31, 35, 33, 32, 29, 27, 25, 30, 26, 31, 22], 
index=['1a', '1b', '2', '3a', '3b', '4a', '4b', '5', '6a', '6b', '7', '8', '9', '10 reaal', '10 sotsiaal', '11 reaal', '11 sotsiaal', '12 reaal', '12 sotsiaal'], name='Õpilaste arv klassis')
uus_seeria = pd.Series([25, klassid.sum(), klassid.size], index=['Õpetajate arv', 'Õpilaste arv kokku','Klasside arv kokku'])
klassid = klassid.append(uus_seeria)
print(klassid)

Tulemuseks on uuendatud klasside seeria. Oluline on meelde jätta, et funktsioonide rakendamisel seeria peal, tuleb uus ja modifitseeritud muutuja alati uuesti omistada, kas siis uuele muutujale või kirjutada vana seeria üle.

1a                     24
1b                     23
2                      21
3a                     22
3b                     28
4a                     26
4b                     30
5                      28
6a                     31
6b                     35
7                      33
8                      32
9                      29
10 reaal               27
10 sotsiaal            25
11 reaal               30
11 sotsiaal            26
12 reaal               31
12 sotsiaal            22
Õpetajate arv          25
Õpilaste arv kokku    523
Klasside arv kokku     19
dtype: int64

Andmefreim (DataFrame)

Juba seeria abil saab andmeid teatud määral töödelda ja illustreerida. Veelgi põnevamaid võimalusi pakub andmefreim (DataFrame), mis kujutab endast põhimõtteliselt tabelit. Seeria tähistab andmefreimis (DataFrame) ühte veergu. Andmefreimis võivad olla erinevat tüüpi andmed ja selle suurust saab muuta. Ridadele ja veergudele saab rakendada aritmeetilisi funktsioone - näiteks saab veergusid liita, lahutada, korrutada ja jagada ning arvutada rea või veeru kaupa selle maksimumi, keskmist jpm.

Esimese näitena vaatame andmefreimi, milles on õpilaste nimed ning eesti keele ja matemaatika hinded.

import pandas as pd
import matplotlib.pyplot as plot
opilased = { 'matemaatika': pd.Series([5, 4, 5], index = ['Mirjam', 'Sirje', 'Vaido']), 
'eesti keel': pd.Series([5, 5, 5, 4], index = ['Mirjam', 'Sirje', 'Vaido', 'Kunnar'])}
opilased_tabel = pd.DataFrame(opilased)
print(opilased_tabel)

Andmefreimis ei loeta siltide veergu ja veergude pealkirjasid ridade ja veergude hulka. Erinevalt seeriast, vastab siin igale sildile üks rida. See koosneb põhimõtteliselt pealkirjaga seeriatest (veergudest), millel on ühised sildid.

Illustreerime ülaltoodud andmeid graafikul:

opilased_tabel.plot.bar()
plot.show()

Andmefreimi saab luua järgmiselt:

pandas.DataFrame(data, index, columns, dtype, copy)

Ka andmefreimi puhul ei pea kõiki parameetreid defineerimisel kasutama, parameetri ärajätmisel kasutatakse selle vaikimisi määratud väärtust.

ParameeterSelgitus
dataAndmed võivad olla n-dimensioonilise andmemassiivi, sõnastiku, konstandi, järjendi või teise andmefreimi kujul. Näiteks: pandas.DataFrame([['Ruudi', 12], ['Malle', 10]], ...)
indexRidade siltide järjend, pikkus peab olema võrdne ridade arvuga. Vaikimisi määratakse arvud 0, 1, 2, ..., n-1, kus n on ridade arv.
columnsVeergude siltide järjend, pikkus peab olema võrdne veergude arvuga. Vaikimisi määratakse arvud 0, 1, 2, ..., m-1, kus m on veergude arv.
dtypeAndmetüüp, mida DataFrames olevatele andmetele määratakse. Vaikimisi järeldatakse andmetest.
copyMäärab, kas andmetest, mida kasutatakse, tehakse koopia. Vaikimisi väärtus False.

Vaatame ülaltoodud klasside ja õpilaste näidet uuesti ning analüüsime selle seeria loomist:

import pandas as pd
opilased = { 'matemaatika': pd.Series([5, 4, 5], index = ['Mirjam', 'Sirje', 'Vaido']), 
'eesti keel': pd.Series([5, 5, 5, 4], index = ['Mirjam', 'Sirje', 'Vaido', 'Kunnar'])}
opilased_tabel = pd.DataFrame(opilased)
print(opilased_tabel)

Sisendiks antakse sõnastik, mille võtmed on veeru pealkirjad ja vastavateks väärtusteks kaks seeriat (kaks veergu). Seeriate siltideks on õpilaste nimed ning andmeteks õpilaste poolt saadud hinded. Pange tähele, et mõlemas seerias on õpilaste arv võrdne hinnete arvuga, kuid lisatavad seeriad pole sama pikad. Muudele parameetritele määrati väärtused vaikimisi.

Rohkem näiteid andmefreimide loomisest:

Tühja andmefreimi loomine:

import pandas as pd
tühi = pd.DataFrame()
print(tühi)

Väljund:

Empty DataFrame
Columns: []
Index: []

Andmefreimi loomine järjendi põhjal:

Tegemist on järjendite järjendiga, mis antakse ette andmefreimi andmetena. Columns parameetriks antud järjend määrab ära veergude pealkirjad. Andmed jaotatakse veergudesse vastavalt nende paigutusele järjendites, iga järjend on eraldi rida ja sisemiste järjendite elemendid asuvad erinevates veergudes. Määratud on ka andmefreimis arvuna antud vanuste andmetüüp, selleks on float.

import pandas as pd
isikud = [['Juss',10],['Illar',12],['Mari-Liis',13]] 
andmestruktuur = pd.DataFrame(isikud, columns = ['Nimi','Vanus'], dtype=float) 
print(andmestruktuur)
     Nimi        Vanus	 
0    Juss        10.0 
1    Illar       12.0	
2    Mari-Liis   13.0
dype: object

Andmefreimi loomine sõnastiku põhjal:

Sarnaselt ülaltoodud näitele on siingi sõnastiku võtmed veergude pealkirjadeks. Konkreetsetele võtmetele vastavad järjendid on aga veergudes väärtusteks. Andmefreimi loomisel on etteantud ka siltide järjend.

import pandas as pd
voistlejad = {'Nimi' : ['Malle', 'Kalle', 'Jaanus', 'Pille'], 'Vanus' : [24, 34, 51, 47]}
voistlejad_tabel = pd.DataFrame(voistlejad, index = ['Nr. 1', 'Nr. 2', 'Nr. 3', 'Nr. 4'])
print(voistlejad_tabel)

Väljund:

         Nimi    Vanus
Nr. 1	 Malle	   24
Nr. 2	 Kalle	   34
Nr. 3	 Jaanus	   51
Nr. 4	 Pille	   47

Andmefreimi (DataFrame) loomine sõnastikust, milles on seeriad:

Ülaltoodud näide õpilastest ja hinnetest sobib hästi näiteks, kus andmefreim luuakse sõnastikust, milles on seeriad.

import pandas as pd
opilased = { 'matemaatika' : pd.Series([5, 4, 5], index=['Mirjam', 'Sirje', 'Vaido']), 
'eesti keel' : pd.Series([5, 5, 5, 4], index = ['Mirjam', 'Sirje', 'Vaido', 'Kunnar'])}
opilased_tabel = pd.DataFrame(opilased)
print(opilased_tabel)

Väljund:

		eesti keel	   matemaatika
Kunnar		     4			NaN
Mirjam		     5			5.0				
Sirje		     5			4.0
Vaido		     5			5.0

Matemaatika veerus oli andmeid vaid 3 inimese kohta, seega lisati Kunnari matemaatika hindeks NaN ehk siis “pole arv” väärtus (ingl not a number). Sellest tulenevalt muudeti selle veeru väärtused ujukomaarvudeks (ingl float), sest NaN väärtust loetakse ujukomaarvuks.

Edasi tutvume mõnede andmefreimi võimalustega ja selleks on jällegi hea kasutada õpilaste ja hinnete näidet. Oletame, et pandi välja veel mitme aine hinded ning vaja oleks lisada ka need tabelisse.

Selleks loome sama põhimõtte järgi uue andmefreimi ning ühendame .join() funktsiooni abil kaks andmefreimi omavahel.

import pandas as pd
lisa = { 'inglise keel' : pd.Series([5, 4, 5, 5, 3], index = ['Mirjam', 'Sirje', 'Vaido','Karmen','Kunnar']),
             'kehaline kasvatus' : pd.Series([5, 5, 5, 4, 5], index = ['Mirjam', 'Sirje', 'Vaido', 'Karmen', 'Kunnar'])}

lisa_tabel = pd.DataFrame(lisa)

Uute andmetega tabeli kuju:

             inglise keel  kehaline kasvatus
Mirjam             5                  5
Sirje              4                  5
Vaido              5                  5
Karmen             5                  4
Kunnar             3                  5

Algse tabeli kuju:


            eesti keel  matemaatika
Kunnar           4          NaN
Mirjam           5          5.0
Sirje            5          4.0
Vaido            5          5.0

Näeme, et lisatavas tabelis on rohkem õpilasi, seega peame ühendama algse õpilaste tabeli uue tabeliga, et kõik nimed oleksid olemas ka uues tabelis.

import pandas as pd
opilased = { 'matemaatika': pd.Series([5, 4, 5], index = ['Mirjam', 'Sirje', 'Vaido']), 
'eesti keel': pd.Series([5, 5, 5, 4], index = ['Mirjam', 'Sirje', 'Vaido', 'Kunnar'])}
opilased_tabel = pd.DataFrame(opilased)

lisa = { 'inglise keel' : pd.Series([5, 4, 5, 5, 3], index = ['Mirjam', 'Sirje', 'Vaido','Karmen','Kunnar']),
             'kehaline kasvatus' : pd.Series([5, 5, 5, 4, 5], index = ['Mirjam', 'Sirje', 'Vaido', 'Karmen', 'Kunnar'])}
lisa_tabel = pd.DataFrame(lisa)

uus_tabel = lisa_tabel.join(opilased_tabel)
print(uus_tabel)

Uue tabeli kuju:

             inglise keel  kehaline kasvatus  eesti keel  matemaatika
Mirjam             5               5             5.0          5.0
Sirje              4               5             5.0          4.0
Vaido              5               5             5.0          5.0
Karmen             5               4             NaN          NaN
Kunnar             3               5             4.0          NaN

Lähenemas on õppeaasta lõpp ja lisanduvad ka viimased üksikud hinded, mis tuleb tabelisse lisada. Lisame hinded ühekaupa õigele kohale. Esimese parameetriga määrame õpilase nime (sildi), kelle hinnet soovime muuta ning teise parameetriga aine (veeru):

uus_tabel.loc['Karmen','matemaatika'] = 3
uus_tabel.loc['Karmen', 'eesti keel'] = 5
uus_tabel.loc['Kunnar', 'matemaatika'] = 3

Kuna keskmisest hindest oleneb ekskursioonile minek, soovime välja arvutada keskmised hinded ja lisada need uude veergu “Keskmine hinne”. Lisame uue veeru ja arvutame õpilaste keskmised hinded. Õige rea valimiseks kasutame tunnust .loc ning keskmise arvutamiseks reas funktsiooni .mean():

uus_tabel['Keskmine hinne'] = pd.Series([uus_tabel.loc['Sirje'].mean(), uus_tabel.loc['Mirjam'].mean(),
                                        uus_tabel.loc['Vaido'].mean(), uus_tabel.loc['Karmen'].mean(), uus_tabel.loc['Kunnar'].mean()], index = ['Sirje', 'Mirjam', 'Vaido', 'Karmen', 'Kunnar'])

Pane tähele, et uude veergu lisatavad keskmised peavad olema siltide järjendis olevate siltidega samas järjekorras, siis saab õige hinne lisatud õige õpilase juurde.

Tabel, milles on puuduvad hinded ja keskmised:

        inglise keel  kehaline kasvatus  eesti keel  matemaatika  \
Mirjam             5                  5         5.0          5.0   
Sirje              4                  5         5.0          4.0   
Vaido              5                  5         5.0          5.0   
Karmen             5                  4         5.0          3.0   
Kunnar             3                  5         4.0          3.0   

        Keskmine hinne  
Mirjam            5.00  
Sirje             4.50  
Vaido             5.00  
Karmen            4.25  
Kunnar            3.75

Järgmises peatükis leiate veelgi näiteid andmetöötluse jaoks kasutatavatest andmefreimi funktsioonidest.


V OSA sisukord
  • Arvutiteaduse instituut
  • Loodus- ja täppisteaduste valdkond
  • Tartu Ülikool
Tehniliste probleemide või küsimuste korral kirjuta:

Kursuse sisu ja korralduslike küsimustega pöörduge kursuse korraldajate poole.
Õppematerjalide varalised autoriõigused kuuluvad Tartu Ülikoolile. Õppematerjalide kasutamine on lubatud autoriõiguse seaduses ettenähtud teose vaba kasutamise eesmärkidel ja tingimustel. Õppematerjalide kasutamisel on kasutaja kohustatud viitama õppematerjalide autorile.
Õppematerjalide kasutamine muudel eesmärkidel on lubatud ainult Tartu Ülikooli eelneval kirjalikul nõusolekul.
Tartu Ülikooli arvutiteaduse instituudi kursuste läbiviimist toetavad järgmised programmid:
euroopa sotsiaalfondi logo