43 CSV faili lugemine ja kirjutamine
CSV failist lugemine
Andmetöötluses on eelnevalt vaja tabel failist sisse lugeda, mis on tihti CSV formaadis. NumPyga saab 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 failis ei tohi olla veeru nimedes tühikuid, need võib asendada _ -ga (alakriipsuga). Näiteks Keskmine hinne → Keskmine_hinne.
# CSV faili sisselugemine import numpy as np csv = np.genfromtxt('fail.csv', delimiter=";", names=True, encoding = 'UTF-8') # Terve tabeli väljastamine print(csv)
>>> %Run guido.py [(1., 11., 21.) (2., 12., 22.) (3., 13., 23.) (4., 14., 24.)]
# Väljastame esimese veeru print("Esimene veerg: ", csv["Esimene"])
>>> %Run guido.py Esimene veerg: [1. 2. 3. 4.]
# Väljastame teise rea print("Teine rida: ", csv[1])
>>> %Run guido.py Teine rida: (2., 12., 22.)
Näeme, et väljund ei ole tüüpilisel Numpy kahemõõtmelise järjendi kujul, sest elementideks oleks justkui ennikud. Tegelikult on tegemist record array tüüpi järjendiga, mis üks Numpy järjendi tüüpidest, mis lubabki veeru eralda, selle nime järgi. Proovi ära võtta names = True
argument ja väljasta kogu tabel. Mis juhtub? Kas tulemus oli midagi sellist?
[[nan nan nan] [ 1. 11. 21.] [ 2. 12. 22.] [ 3. 13. 23.] [ 4. 14. 24.]]
Nimelt on võib Numpy üheks puuduseks pidada seda, et tabelis olevad väärtused peavad olema sama tüüpi. Vaikimisi on failist loetud tabel alati ujukomaarvu tüüpi ja kui tabelis on ka teksti, siis need on Numpy jaoks tundmatud, mis tähistatakse nan
(not a number, tundmatu).
Juhul kui on vaja analüüsida tabelit, kus on erinevat tüüpi andmeid, siis on kolm võimalust, kuidas ikkagi andmeid sobilikul kujul kasutada. Esimene võimalus on failist lugemisel määrata ära iga veeru andmetüüp.
Olgu meil järgmised andmed.
Nimi;Vanus;Punktid Tiina;11;21 Kalle;12;42 Kustav;13;23 Salme;14;34 Örli;11;23
Näeme, et esimese veeru andmed on sõned ja teise ning kolmanda veerud andmed on täisarvud.
Loeme andmed, kasutades eelnevalt demonstreeritud funktsiooni genfromtxt
. Erinevalt eelmisest näitest, lisame juurde ka dtype
argumendi, mille väärtuseks on järjend, kus iga element tähistab veeru tüüpi, kasutades tüüpide koode. Tekstina esitatud nimed määrame tabelis UNICODE sõne tüüpi. Me ei kasuta tavalist sõne tüüpi (str või “S”), sest faili kodeering on UTF-8, siis selleks, et NumPy oskaks kuvada failis olevaid nimesid õigesti, tuleb kasutada UNICODE sõne tüüpi.
csv = np.genfromtxt('fail.csv', delimiter=";", encoding = 'UTF-8', dtype=["U25", "i4", "i4"], names=True) print(csv["Nimi"]) print(csv["Vanus"])
>>> %Run guido.py ['Tiina' 'Kalle' 'Kustav' 'Salme' 'Örli'] [11 12 13 14 11]
Teine võimalus on muuta kogu tabel sõne tüüpi. Selleks määrame parameetri dtype
väärtuseks srt
. Samuti lisame parameetri skip_header
, mille väärtuseks on 1
. Selle tulemusel ei ole tabelis enam veeru pealkirjade rida.
csv = np.genfromtxt('fail.csv', delimiter=";", encoding = 'UTF-8', dtype=str, skip_header=1) # Terve tabeli väljastamine print(csv)
>>> %Run guido.py [['Tiina' '11' '21'] ['Kalle' '12' '42'] ['Kustav' '13' '23'] ['Salme' '14' '34'] ['Örli' '11' '23']]
Nüüd kui soovime leida näiteks keskmist vanust, tuleks kasutada tükeldamist ja saadud veeru tüüp teisendada ujukomaarvuks.
teine_veerg = csv[:, 1] print(teine_veerg) vanus = teine_veerg.astype(float) print("Keskmine vanus:", np.mean(vanus))
>>> %Run guido.py ['11' '12' '13' '14' '11'] Keskmine vanus: 12.2
Kolmas võimalus on kasutada Pandase moodulit (loe lisa Pandase kohta peatükist Pandas) CSV failide lugemiseks, sest sel juhul ei ole vaja muretseda, et andmed on tabelis erinevat tüüpi. See on väga hea viis kasutada ära mõlema mooduli head küljed. Esmalt tuleb aga Pandase moodul importida.
import pandas as pd
Loeme andmed failist kasutades Pandase read_csv
funktsiooni.
x = pd.read_csv("fail.csv", sep=";").values print(x)
>>> %Run guido.py [['Tiina' 11 21] ['Kalle' 12 42] ['Kustav' 13 23] ['Salme' 14 34] ['Örli' 11 23]]
Andmed võib lugeda ka veebist. Lisades juurde mooduli URLLib, millega saab faile veebist lugeda ning kasutada veebilinki, kus andmed asuvad.
from urllib.request import urlopen # Andmed url = 'http://kodu.ut.ee/~merka123/plotly/haigusjuhtumid.csv' andmed = urlopen(url) csv = np.genfromtxt(andmed, delimiter=";", names=True, encoding = 'UTF-8', dtype=['U20', 'i4', 'i4', 'i4', 'i4','i4'])
CSV faili salvestamine
NumPyga saab salvestada informatsiooni tekstifaili vaid ühe reaga. Selle jaoks on olemas funktsioon: np.savetxt(fail, sisu, eraldaja)
. Vaatame näidet, kus salvestame kahemõõtmelise järjendi faili ning seejärel avame selle faili ning 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.csv, eraldajaks määrame semikooloni np.savetxt('fail.csv', sisu, delimiter=';') # Nüüd avame faili fail.txt fail = np.genfromtxt('fail.csv', delimiter=";", encoding = 'UTF-8') # Väljastame sisu print(fail)
>>> %Run guido.py [[ 1. 11. 21.] [ 2. 12. 22.] [ 3. 13. 23.] [ 4. 14. 24.]]