ANDMETÖÖTLUS MOODULIGA NUMPY
Sissejuhatus
NumPy (ingl Numerical Python) on mitmemõõtmeliste järjendite töötlemiseks mõeldud Pythoni moodul. See loodi 1995. aastal ja kandis nime Numeric. Alates aastast 2006 kannab moodul nime NumPy. Mooduli loojaks on ameeriklane Travis Oliphant, kes on andmeteadlane ja ärimees ning on õppinud näiteks matemaatikat ja elektrotehnikat. Peamiselt kasutatakse NumPy moodulit andmetöötluses ja teaduslikes arvutustes. Näiteks on Numpyt kasutatud heliprogrammis Pitch Perfect ning multimeediast tuntud vektorgraafika programmi Inkspace’i viimases versioonis kujutise moonutamisel. Andmetöötluses eelistatakse kasutada NumPyt, sest lisaks Pythonile on selle kirjutamiseks kasutatud C keelt ning moodul on seetõttu palju kiirem kui tavaline Python. Ka lihtsate järjendi operatsioonide jaoks on NumPy mugavam tänu sisseehitatud funktsioonidele. Käesolev peatükk tutvustab, kuidas NumPyt kasutada ja mida sellega teha saab.
Installeerimine
Thonny on üks populaarsemaid ja lihtsamaid programme Pythonis programmeerimiseks. Seetõttu on installeerimise sammud kirjeldatud just selle programmi põhjal.
Video NumPy installeerimisest Thonnys:
Installeerimise sammud:
- Ava Thonny programm
- Vali ülevalt menüüribalt
Tools
- Sealt vali
Manage packages…
- Avaneb uus aken
- Sisesta otsinguribale
numpy
- Kliki nupul
Find package from PyPI
- Kui avaneb
numpy
informatsioon, kliki nupulInstall
- Pärast installeerimist ongi Thonny programmil moodul NumPy
- Kasutamiseks kirjuta
import numpy as np
programmi algusesse. Et kiiremini proovida NumPy funktsioone ja järjendi loomist, võib selle kirjutada ka otse käsureale
np on levinud lühend NumPy kasutamiseks.
NumPy
NumPy järjendite loomine
NumPy järjendid jagatakse mõõtmete järgi erinevatesse kategooriatesse. Selles materjalis pöörame peamist tähelepanu ühe-ja kahemõõtmelistele järjenditele. On võimalik töödelda ka kolmemõõtmelistest kuni N-mõõtmeliste järjenditeni, kuid nende kasutamist selles materjalis ei tutvustata. Alustuseks vaatame, kuidas luua NumPy abil järjendeid.
NumPy ühemõõtmelised järjendid
Kõigepealt proovime NumPy abil luua ühemõõtmelisi järjendeid. NumPy kasutamiseks, peab selle Pythonis sisse importima käsuga import numpy as np
, kus np on levinud lühend selle mooduli kasutamiseks. Programmis ei pea pikalt kirjutama välja numpy, vaid saab kasutada lühedit np. Järjendi saab NumPy abil luua array
funktsiooni kasutades. Võrreldes tavalise Pythoniga, kus järjendi elemendid lisatakse nurksulgude vahele, siis NumPy puhul kasutatakse järjendit array
funktsiooni argumendina ehk np.array(järjend)
NumPy programmis puuduvad järjendi väljastamisel elementide vahel komad, näiteks [1 2 3]
.
#NumPy järjendi loomine ja väljastamine import numpy as np b = np.array([1,2,3]) print(b) ⇒ Väljund: [1 2 3]
Väga lihtsalt saab Numpy järjendi dtype parameetrit kasutades muuta järjendi tüüpi.
- Int → Float:
a = np.array([1,2,3], dtype=float) ⇒ Väljund: [1. 2. 3.]
(NumPys ei ole ujukomaarvudel 0 punkti järel)
- Float → Bool:
a = np.array([1.,0.,6.], dtype=bool) ⇒ Väljund: [True False True]
(Arv 0 on False, ülejäänud arvud on True)
Samanimelise funktsiooni abil saab ka järjendi tüübi teada. Näiteks järjendi a = np.array([1,2,3,4])
tüüp a.dtype
on int
(tähistatakse int32
).
NumPy kahemõõtmelised järjendid
Peamiselt kasutatakse andmetöötluses kahemõõtmelisi järjendeid, kus andmetabeleid saab kirjutada kahemõõtmelise järjendi kujul. Nende loomine käib sarnaselt Pythoni käsule, kuid taas peab juurde lisama np.array()
.
#NumPy järjendi loomine ja väljastamine import numpy as np b = np.array([[1,2,3],[4,5,6]]) print(b) ⇒ Väljund: [[1 2 3] [4 5 6]]
Sisseehitatud funktsioonid
Nagu ka Pythonil, on NumPyl endal sisseehitatud funktsioonid, mille abil saab järjendite kohta andmeid või vastavalt soovile neid töödelda. Järgnevalt vaatame lähemalt peamisi Numpy funktsioone ja mille jaoks neid kasutatakse.
Järjendi suurus
Järjendi suuruse leidmine on sarnane Pythonile. Kui Pythonis on käsk len(järjend)
, siis NumPys näeb see välja nii (olgu järjendi nimi a):
- Ühemõõtmeline järjend
#NumPy järjendi elementide arvu leidmine ja väljastamine import numpy as np a = np.array([1,2,3]) print("Järjendi suurus: ", a.size) ⇒ Väljund: 3
- Kahemõõtmeline järjend
#NumPy järjendi elementide arvu leidmine ja väljastamine import numpy as np b = np.array([[1,2,3],[4,5,6]]) print("Järjendi suurus: ", b.size) ⇒ Väljund: 6
Järjendist elemendi võtmine
Üks lihtsamaid järjendi operatsioone on järjendist elemendi võtmine. Ühemõõtmelise järjendi puhul käib see samamoodi nagu Pythonis. Järjendi nime taha tuleb lisada nurksulgude vahele soovitud elemendi indeks. Kahemõõtmeliste järjendite puhul on Pythonil ja NumPyl väike erinevus. NumPy abil saab indeksid kirjutada mugavalt ühe paari nurksulgude vahele.
Meeldetuletuseks: indeksid algavad nullist.
#NumPy järjendist elemendi võtmine import numpy as np a = np.array([[1,2,3],[4,5,6]]) #Võtame järjendi esimese osa teise elemendi ja tagastame selle print("Järjendi esimene osa teine element: ", a[0,1]) ⇒ Väljund: Järjendi esimene osa teine element: 2
Nüüd aga vaatame natuke keerulisemat olukorda. Oletame, et meil on antud järjend, mis koosneb nii positiivsetest kui ka negatiivsetest täisarvudest. Me soovime teha programmi, mis väljastab kõik negatiivsed täisarvud järjendina. Pythonis peab selleks looma tulemuslisti. Sinna hakatakse lisama elemente algsest järjendist, mis vastavad meie avaldisele. Avaldis on element < 0
.
#Pythoni järjendist negatiivsete täisarvude võtmine b = [3,-1,-2,4,-6,8] #tulemuslist tulemus = [] #Võtame järjendist b järjest elemente for element in b: #Kui element on väiksem nullist... if element < 0: #...siis lisame selle elemendi tulemuslisti tulemus.append(element) #Väljastame tulemuslisti print("Tulemuslist: ", tulemus) ⇒ Väljund: Tulemuslist: [-1, -2, -6]
NumPy puhul on see palju lihtsam. Me saame suvalisele muutujale anda argumendiks avaldise ning seda kasutada esialgse järjendi peal. Siin on aga oluline, et avaldises esineks järjendi nimi. Ehk kui me tahame saada järjendist b negatiivseid täisarve, peab meie kontrollavaldis välja nägema b < 0
. Samuti ei pea me looma tulemuslisti, kuna NumPy tagastab elemendid automaatselt järjendina.
#NumPy järjendist negatiivsete täisarvude võtmine import numpy as np b = np.array([3,-1,-2,4,-6,8]) #Avaldis, mille põhjal hakkame järjendist elemente võtma negatiivsed = b < 0 print("Järjendi negatiivsed täisarvud: ", b[negatiivsed]) ⇒ Väljund: Järjendi negatiivsed täisarvud: [-1 -2 -6]
Järjendisse elemendi/elementide lisamine
Eelnevalt vaatasime järjendist elemendi võtmist. Nüüd vaatame, kuidas järjendisse elementi/elemente lisada. Nii Pythoni kui NumPy puhul on käib elemendi lisamine append
käsuga. Vaatame näidet:
#NumPy järjendisse elementide lisamine import numpy as np a = np.array([1,2,3]) #Lisame järjendisse a ühe elemendi a = np.append(a, 4) print("Uue elemendiga järjend: ", a) ⇒ Väljund: Uue elemendiga järjend: [1 2 3 4] #Lisame järjendisse a kaks elementi a = np.append(a, [4,5]) print("Uute elementidega järjend: ", a) ⇒ Väljund: Uute elementidega järjend: [1 2 3 4 4 5]
Pythonis ei saa kahte elementi korraga ühemõõtmelisse järjendisse lisada, vaid seda peab tegema ühekaupa. NumPyga saab lisada mitu elementi korraga: np.append([4,5])
. Kui Pythoniga lisada samamoodi b.append([4,5])
, oleks väljund: [1, 2, 3, 4, [4, 5]]
.
NumPy append funktsioonil on võimalus lisada ka juurde täpsustav parameeter axis, mis näitab, kas uued elemendid lisatakse mitmemõõtmelisse järjendisse rea järgi või veeru järgi. Rida tähistab arv 0 ja veergu arv 1. Lisamisel peab aga teadma järjendi mõõtmeid, muidu pole võimalik elemente juurde lisada. Kui täpsustavat parameetrit (axis) append funktsiooni ei kirjutata, lisab NumPy uue elemendi või elemendid järjendi lõppu ning väljund näitab kahemõõtmelist järjendit ühemõõtmelise järjendina. Vaatame kõigepealt, milline näeb välja ilma rida/veergu tähistava parameetrita append funktsioon.
#NumPy järjendisse elementide lisamine import numpy as np a = np.array([[8,9,7],[10,11,12]]) #Lisame järjendisse a ühe elemendi a = np.append(a, 4) print("Uue elemendiga järjend: ", a) ⇒ Väljund: Uue elemendiga järjend: [8 9 7 10 11 12 4] #Lisame järjendisse a kaks elementi a = np.append(a, [4,5]) print("Uute elementidega järjend: ", a) ⇒ Väljund: Uute elementidega järjend: [8 9 7 10 11 12 4 4 5]
Nüüd vaatame, kuidas rea või veeru järgi elemente lisada.
#NumPy järjendisse elementide lisamine import numpy as np a = np.array([[2,4],[6,7]]) #Lisame järjendisse a samamõõtmelise järjendi rea järgi #Järjendisse a tekivad uued read, väljastame järjendi uue järjendina b b = np.append(a, [[3,4],[5,6]], axis = 0) print("Uute ridadega järjend: ", b) ⇒ Väljund: Uute ridadega järjend: [[2 4] [6 7] [3 4] [5 6]] #Lisame järjendisse a samamõõtmelise järjendi veeru järgi #Järjendisse a tekivad uued veerud, väljastame järjendi uue järjendina c c = np.append(a, [[3,4],[5,6]], axis = 1) print("Uute veergudega järjend: ", c) ⇒ Väljund: Uute veergudega järjend: [[2 4 3 4] [6 7 5 6]]
Järjendi suurima/vähima väärtuse leidmine
Järjendist saab väga lihtsalt leida suurimat ja vähimat väärtust. Pythonis oleme kasutanud selleks funktsioone max(järjend)
ja min(järjend)
. NumPys on need aga vastavalt: np.amax(järjend)
ja np.amin(järjend)
.
#NumPy min ja max import numpy as np a = np.array([1,2,3]) #Järjendi suurim element print("Järjendi suurim element: ", np.amax(a)) ⇒ Väljund: Järjendi suurim element: 3 #Järjendi vähim element print("Järjendi vähim element: ", np.amin(a)) ⇒ Väljund: Järjendi vähim element: 1
Järjendi aritmeetilise keskmise leidmine
Üks levinumaid matemaatilisi funktsioone on arvude aritmeetilise keskmise leidmine. Seda saab väga lihtsalt ka teha NumPy järjendiga, kasutades mean
funktsiooni. Mean funktsioon liidab automaatselt järjendi elemendid kokku ja jagab järjendi pikkuse ehk elementide arvuga. Vaatame näidet:
#NumPy järjendi keskmine väärtus import numpy as np a = np.array([2,8,10,6,12]) #Leiame arvude keskmise väärtuse print("Järjendi keskmine väärtus: ", np.mean(a)) ⇒ Väljund: Järjendi keskmine väärtus: 7.6
Pythonis sisseehitatud funktsiooni ei leidu.
Tükeldamine
Tükeldamine (ingl slicing) on järjendist vajamineva osa võtmine. Ühemõõtmeliste järjendite puhul ei erine NumPy siin Pythonist. Vaatame aga, kuidas tükeldada NumPy kahemõõtmelist järjendit. Kõigepealt loome järjendi b.
#NumPy järjendi tükeldamine import numpy as np b = np.array([[10,34,21,65],[51,77,23,16]]) print("Järjend b: ", b) ⇒ Väljund: Järjend b: [[10 34 21 65] [51 77 23 16]]
Tabeli kujul näeks see välja selline (Tumedaga on märgitud tabeli indeksid).
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | 10 | 34 | 21 | 65 |
1 | 51 | 77 | 23 | 16 |
Tükeldamise juures tähendab nurksulgude vahel esimene arv ridu ja teine arv veerge. Meeldetuletuseks: Kõikide elementide saamiseks reas/veerus piisab, kui kirjutada :
, näiteks a[:]
. Mingis vahemikus elementide saamiseks peab kirjutama: algus::lõpp
, näiteks a[1::2]
. Vaatame näiteid:
- Esimene ja kolmas veerg:
print("Järjendi esimene ja kolmas veerg: ", b[:, 0::2]) ⇒ Väljund: Järjendi esimene ja kolmas veerg: [[10 21] [51 23]]
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | 10 | 34 | 21 | 65 |
1 | 51 | 77 | 23 | 16 |
- Teine rida:
print("Järjendi teine rida: ", b[1, :]) ⇒ Väljund: Järjendi teine rida: [51 77 23 16]
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | 10 | 34 | 21 | 65 |
1 | 51 | 77 | 23 | 16 |
- Esimese rea teine ja neljas element:
print("Järjendi esimese rea teine ja neljas element: ", b[0, 1::2]) ⇒ Väljund: Järjendi esimese rea teine ja neljas element: [34 65]
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | 10 | 34 | 21 | 65 |
1 | 51 | 77 | 23 | 16 |
Järjendist elemendi/elementide otsimine
NumPyl on järjendist elemendi otsimise jaoks olemas funktsioon where
, mis tagastab otsitava elemendi indeksi ja tüübi. Vaatame näidet. Olgu meil järjend a, mille elemendid on [1 2 3 4]
. Leiame arvu 3 indeksi:
# Where funktsiooni kasutamine import numpy as np a = np.array([1,2,3,4]) # Where võtab argumendiks järjendi nime ja tingimuse, mida tahetakse leida el = np.where(a == 3) # Kogu informatsioon print(el) ⇒ Väljund: (array([2], dtype=int32),) # Indeksi saamiseks peame võtma esimese elemendi # Ning tegema selle täisarvuks print(int(el[0])) ⇒ Väljund: 2
Kahemõõtmelise järjendi puhul leiame tulemuse, kui teame, millisest veerust/reast me elementi otsime. Näiteks leiame järjendist kõikide nende ridade indeksid, mille esimene element on 1.
Olgu järjend b = [[1 2 3 4] [5 6 7 8] [1 6 3 7] [1 6 7 2] [5 7 3 2]]
# Võtame kõik read ja kontrollime esimese veeru elemente el = np.where(b[:, 0] == 1) print(el[0]) ⇒ Väljund: [0 2 3]
Tehted järjendi elementidega
Siin tuleb kõige paremini välja NumPy eelis tavalise Pythoni ees. Oletame, et tahame teha kahe või enama järjendi elementide vahel järgnevaid tehteid: liitmine, lahutamine, korrutamine, korrutamine konstandiga, jagamine, astendamine. Kui Pythonis peab sellise tehte tegemiseks looma tsükli, siis NumPy puhul piisab ühest reast. NB! See toimib nii ainult juhul, kui järjendid sisaldavad sama palju elemente. Vaatame liitmise näidet:
#NumPy järjendite elementide liitmine import numpy as np a = np.array([1,2,3]) b = np.array([10,11,12]) #Järjendite a ja b elementide summa, tagastatakse tulemuse järjend print("Järjendite a ja b elementide summa tulemuse järjend: ", a + b) ⇒ Väljund: Järjendite a ja b elementide summa tulemuse järjend: [11 13 15]
Sarnaselt saab järjendeid omavahel lahutada, korrutada, jagada, korrutada konstandiga, astendada.
CSV faili lugemine
Andmetöötluses on eelnevalt vaja tabel failist sisse lugeda, mis on tihti csv kujul. NumPyga on mugav kasutada funktsiooni genfromtxt()
. Funktsiooni sulgudesse tuleb lisada faili nimi, delimiter
ehk eraldaja väärtus, mis eraldab andmeid teineteisest, ja parameeter names=True
, mille abil saab veeru pealkirja kasutades väga lihtsalt tabelist terve veeru. Näiteks tabel[“sugu”] tagastab kõik väärtused, mis asuvad veerus pealkirjaga “sugu”. Populaarsemad eraldajad on näiteks tühik, koma või semikoolon. Vaatame näidet. Olgu csv faili sisu on selline:
Esimene;Teine;Kolmas 1;11;21 2;12;22 3;13;23 4;14;24
#CSV faili sisselugemine import numpy as np csv = np.genfromtxt('file.csv', delimiter=";", names=True, encoding = 'UTF-8') # Terve tabeli väljastamine print(csv) ⇒ Väljund:[(1., 11., 21.) (2., 12., 22.) (3., 13., 23.) (4., 14., 24.)] #väljastame esimese veeru print("Esimene veerg: ", csv["Esimene"]) ⇒ Väljund: Esimene veerg: [1. 2. 3. 4.] #väljastame teise rea print("Teine rida: ", csv[1]) ⇒ Väljund: Teine rida: (2., 12., 22.)
Tekstifaili salvestamine
NumPyga saab salvestada informatsiooni tekstifaili vaid ühe reaga. Selle jaoks on olemas funktsioon: np.savetxt(fail,sisu,eraldaja)
. Vaatame näidet, kus salvestama kahemõõtmelise järjendi faili ning seejärel avame selle faili ja väljastame sisu.
#Tekstifaili salvestamine ja selle sisu väljastamine import numpy as np #Loome ühe kahemõõtmelise järjendi sisu = np.array([[1,11,21],[2,12,22],[3,13,23],[4,14,24]]) #Salvestame sisu faili fail.txt, eraldajaks määrame tühiku np.savetxt('fail.txt',sisu,delimiter=' ') #Nüüd avame faili fail.txt fail = np.loadtxt('fail.txt') #Väljastame sisu reahaaval for rida in fail: print(rida) ⇒ Väljund: [ 1. 11. 21.] [ 2. 12. 22.] [ 3. 13. 23.] [ 4. 14. 24.]
Allpool on kokkuvõttev tabel, kus on kirjas NumPy sisseehitatud funktsioonid ja nende väljundid. Kõiki funktsioone on selles õppematerjalis eelnevalt kirjeldatud.
Käsk | NumPy lause | Väljund |
---|---|---|
Ühemõõtmelise järjendi loomine | a = np.array([1,2,3]) | [1 2 3] |
Kahemõõtmelise järjendi loomine | a = np.array( |
|
Järjendi pikkuse leidmine a = np.array([1,2,3]) | a.size | 3 |
Ühemõõtmelisest järjendist elemendi võtmine a = np.array([1,2,3]) | a[1] | 2 |
Kahemõõtmelisest järjendist elemendi võtmine a = np.array([[1,2,3],[4,5,6]]) | a[1,2] | 6 |
Järjendi suurim väärtus a = np.array([1,2,3]) | np.amax(a) | 3 |
Järjendi vähim väärtus a = np.array([1,2,3]) | np.amin(a) | 1 |
Ühemõõtmelisse järjendisse elemendi lisamine a = np.array([1,2,3]) | a = np.append(a, 4) | [1 2 3 4] |
Kahemõõtmelisse järjendisse elemendi lisamine a = np.array([[8,9,7],[10,11,12]]) | a = np.append(a, 4) | [8 9 7 10 11 12 4] |
Kahemõõtmelise järjendi teine rida a = np.array([[1,2,3,4],[5,6,7,8]]) | a[1, :] | [5 6 7 8] |
Kahemõõtmelise järjendi esimese rea teine ja neljas element a = np.array([[1,2,3,4],[5,6,7,8]]) | a[0, 1::2] | [2 4] |
Järjendi keskmise väärtuse leidmine a = np.array([2,8,10,6,12]) | np.mean(a) | 7.6 |
Ülesanne
Nüüd on aeg saadud teadmisi praktikas proovida. Allpool on toodud tabel 20 kergejõustiklase tulemustest spordivõistlusel. Võistlejate nimesid ei ole kasutatud, vaid igaühel on vastav ID number (1-20). Lisaks on välja toodud igaühe vanus, sugu ja nelja ala tulemused. Sugu on samuti tähistatud numbriga, kus poisid on tähistatud nulliga ja tüdrukud ühega. Tabeli all on pisikesed ülesanded, mida saab lahendada selle õppematerjali abil. Ülesanded peavad olema lahendatud, kasutades NumPyt. Allpool on näitena toodud tabeli esimesed 5 rida ning tabel on kättesaadav failist tulemused.csv, mille peab programmi sisse lugema. Failis on eraldajaks kasutatud semikoolonit. NB! Failist lugemisel soovitame kasutada parameetrit names=True
, sest siis ei pea veerust andmete kätte saamiseks kasutama tükeldamist, vaid saab kasutada veeru pealkirja (järjend['pealkiri']).
*Kõik andmed on väljamõeldud
- Mis oli odaviske parim tulemus?
*Vihje: Veeru pealkirja kasutamine ja np.amax() - Mis oli kaugushüppe halvim tulemus?
*Vihje: Veeru pealkirja kasutamine ja np.amin() - Leia võistlejate keskmine vanus.
*Vihje: Veeru pealkirja kasutamine ja np.mean() - Mitu poissi osales? Mitu tüdrukut?
*Vihje: Veeru pealkirja kasutamine, np.where() (Vajadusel teisendada funktsiooni tagastus täisarvuks) ja np.size() - Millise IDga osaleja oli kõige kiirem 400 m jooksus?
*Vihje: Veeru pealkirja kasutamine ja np.where() (Vajadusel teisendada funktsiooni tagastus täisarvuks) - Leia võistleja IDga 7 kõik andmed.
*Vihje: Veeru pealkirja kasutamine, np.where() (Vajadusel teisendada funktsiooni tagastus täisarvuks) ja tükeldamine
Tagasiside
Palume, et vastaksite ka tagasiside küsimustikule. Nii saame õppematerjali paremaks muuta.
Tagasiside küsimustiku leiate siit: Tagasiside NumPy õppematerjalile
Kasutatud materjalid
- Chabot-LeClerc, A. (2018). Scientific Computing with Python. Austin: SciPy. Allikas: https://www.youtube.com/watch?v=V0D2mhVt7NE&feature=youtu.be
- Hill, C. (2015) Learning Scientific Programming with Python
- NumPy. (1. märts 2019. a.). Allikas: NumPy: http://www.numpy.org/
- Python For Data Science Cheat Sheet NumPy Basics. (15. märts 2019. a.). Allikas: DataCamp: https://s3.amazonaws.com/assets.datacamp.com/blog_assets/Numpy_Python_Cheat_Sheet.pdf
- NumPy basics. (1. märts 2019. a.). Allikas: SciPy: https://docs.scipy.org/doc/numpy/user/basics.html