10 NumPy pakkinn¶
10.1 Inngangur¶
NumPy pakkinn er ætlaður fyrir vinnu með vigra (vectors) og fylki (matrices) í Python og auk þess ýmsa tölulega reikninga (numerical computations) af einfaldara tagi. Pakkinn SciPy er síðan ætlaður fyrir allskyns sérhæfðari vísindalega reikninga.
10.1.1 Vigrar og fylki í stærðfræði¶
Nákvæmar skilgreingar á stærðfræðilegum vigrum og fylkjum og skyldum hugtökum eru umfjöllunarefni í námskeiðum um línuleg algebru. Hér látum við duga styttri útgáfur.
Vigur (vector) er runa af endanlega mörgum tölum sem gefið er nafn og notuð sem ein heild. Einstakar tölur nefnast stök (elements), þau eru oftast tölusett 1, 2, 3… en stundum 0, 1, 2…, og i-ta stak vigurs \(a\) er táknað \(a_i\). Vigur \(a\) með tölunum 1, 2 og 4 má rita
Fylki (matrix) er tafla með tölum sem gefið er nafn og notuð sem heild. Tölur í fylki heita líka stök. Stakið í línu \(i\) og dálki \(j\) í fylki \(A\) er táknað \(a_{ij}\). Í stærðfræðilegri umfjöllun er oftast byrjað að telja í 1 svo stakið efst til vinstri er \(a_{11}\), en þegar verið er reikna í tölvum er oft byrjað að telja í 0. Fylki með \(m\) línum og \(n\) dálkum er kallað \(m\) sinnum \(n\) fylki, táknað \(m \times n\). Hér er dæmi um \(2 \times 3\) fylki:
10.1.2 Um orðið Fylki¶
Skv. Tölvuorðasafninu hefur orðið fylki tvær merkingar á íslensku:
[einkum í stærðfræði] rétthyrnd tafla af tölum (eða öðrum gildum) = e. matrix.
[einkum í tölvufræði] samsteypa (aggregate) hluta af sama tagi þar sem hægt er að vísa í einstök stök með vísi eða vísum (index, indices) = e. array.
Í seinni merkingunni er fylki notað sem samheiti yfir vigra, tvívíð fylki, og margvíð fylki (þar sem vísarnir eru 3 eða fleiri). Stundum er talað um vigra sem einvíð fylki.
Aðvörun
Þar sem NumPy er beggja megin veggjar, í stærðfræði og í tölvufræði, verður orðið fylki notað í báðum merkingunum hér – lesandi þarf stundum af ráða af samhenginu við hvað er átt.
10.1.3 Import-skipanir fyrir NumPy¶
Í NumPy er undirpakki sem heitir numpy.linalg
sem er talsvert notaður. Hann geymir meðal annars föll til að reikna norm vigurs og til að leysa jöfnuhneppi. Alsiða er að skammstafa numpy með np og numpy.linalg með la, sem sé að flytja inn með:
import numpy as np
import numpy.linalg as la
Síðan er sett np.
eða la.
á undan NumPy-skipunum og -föllum sem notuð eru.
10.2 Vigrar í NumPy¶
Vigur í NumPy er að mörgu leyti líkur venjulegum Python lista. Aðalmunurinn er sá að í vigrum verða öll stök að vera af sama gagnatagi, og með því sparast minnispláss og auk þess fæst mun hraðvirkari vinnsla þegar unnið er með mörg stök. Eins og við munum gildir slík skorða ekki um lista, þeir geta innihaldið blöndu gagnataga.
10.2.1 Vigur gefið gildi¶
NumPy er viðbót við Python, og öfugt við grunntögin sem öll gefa kost á að búa til fasta af hverju tagi (sjá kafla 4.1 og 5.1) er ekki boðið upp á vigur-fasta, heldur þarf að nota NumPy-föll til að búa til vigra.
Eitt þeirra er fallið np.array
sem breytir venjulegum Python-lista af tölum
í vigur. Til að búa til vigurinn \(x = (1,2,3,4,6)\) má nota skipunina:
x = np.array([1,2,3,4,6])
Svo eru til skipanir til að búa til ýmsa sérstaka vigra, til dæmis fæst núllvigur með 3 stökum, \(z = (0,0,0)\), með:
z = np.zeros(3)
Loks skal tekið fram að ef vigur er gefið gildi með öðrum vigri (t.d. y = x
)
er ekki tekið afrit heldur er búin til ný tilvísun í vigurinn, sbr. kafla
5.3.4 og 6.2.
Til að taka afrit mætti nota:
y = x.copy()
10.2.2 Einstök stök og hlutvigrar¶
Vísað í einstök stök í vigrum með hornklofum, alveg eins og í listum, og fyrsta
stakið er líka númer 0. Ef x er \((1,2,3,4,6)\) þá væri x[2]
= 3,
x[2:]
væri NumPy vigurinn \((3,4,6)\) og x[::2]
væri vigurinn
\((1,3,6)\).
Æfing: Fyrsta NumPy-æfingin
Prófið skipanirnar í næsta kafla á undan (10.2.1) og þessum kafla
10.2.3 Einföld útprentun vigra¶
Til að prenta út vigur x er hægt að skrifa einfaldlega
print(x)
eðaprint("x =", x)
Það er hægt að stjórna fjölda aukastafa sem print
, sbr. kafla
10.6. Svo er hægt að prenta einstök stök í
for-lykkju, og þá er hægt að nota f-strengi, sbr. eftirfarandi dæmi
a = np.array([5.55,7.77])
for i,ai in enumerate(a):
print(f"a[{i}] = {ai}")
sem mundi prenta
a[0] = 5.55
a[1] = 7.77
10.2.4 Föll af vigrum¶
Föllin sem sagt var frá í köflum 6.2 og 6.3
og hægt er að nota á lista af tölum er líka hægt að nota á vigra. Það eru einkum
len, min, max
og sum
sem eru nytsamleg. Með NumPy má auk þessara falla
nota np.argmin(x)
og np.argmax(x)
sem skila sætisnúmeri minnsta eða
stærsta staks x, np.mean(x)
sem reiknar meðaltal stakanna og la.norm(x)
sem skilar norminu af x, \(\|x\|\), en norm af n-staka vigur x er
skilgreint með:
10.2.5 Aðferðir í stað falla¶
Öll föllin sem nefnd eru hér næst á undan nema len og norm eru líka til sem aðferðir.
Ef x er vigur má sem sé skrifa x.sum()
í stað np.sum(x)
(og spara tvo stafi). Þetta er ekki hægt ef x er listi. Hér fylgir tafla yfir öll umrædd föll og aðferðir:
fall |
aðferð |
skilagildi |
---|---|---|
|
– |
fjöldi staka í x |
|
|
summa stakanna í x |
|
|
minnsta stak í x |
|
|
stærsta stak í x |
|
|
sæti minnsta staks í x |
|
|
sæti stærsta staks í x |
|
|
meðaltal stakanna í x |
|
– |
normið af x, \(\|x\|\) |
Takið eftir að ekki þarf að setja np.
fremst í fyrstu fjögur föllin, sem eru
innbyggð í Python-málið.
Æfing: Nokkur NumPy föll
Búið til vigur \((2,3,5,7,11)\), prentið hann út, og prófið svo öll föllin sem hér voru talin upp
10.2.6 Föll til að búa til vigra¶
Nokkur þægileg og mikilvæg föll má nota til að búa til vigra. Við höfum þegar séð fallið zeros en auk þess er til ones og tvö föll til að búa til vigra með hlaupandi stökum:
kall |
skilar |
---|---|
|
vigur með n núllum |
|
vigur með n ásum, \((1,1,1...)\) |
|
n-staka vigur jafnt dreifður á bilið \([a,b]\) |
|
\((a, a+1, a+2,...,b-1)\) |
|
\((a, a+d, a+2d,...,b-d)\) |
Við tökum eftir að í arange er b ekki með í x, alveg eins og með innbyggða fallinu range
.
Æfing: Vigratilbúningur
Búið til vigurinn \((3, 4, 5, 6, 7)\) bæði með linspace og arange
Búið til \((2.0, 2.1, 2.2,\ldots, 3.9, 4.0)\) með linspace og arange
10.3 Útreikningur með vigrum¶
10.3.1 Reiknað með vigrum í stærðfræði¶
Í stærðfræði, nánar tiltekið undirgrein hennar sem kallast línuleg algebra, er fjallað um ýmsa útreikninga með vigrum. Það er hægt að leggja saman vigra, draga þá hvern frá öðrum og margfalda þá með tölum. Það er líka hægt að reikna innfeldi (scalar product) tveggja vigra og fá út tölu, og svo má reikna norm vigurs með fyrrnefndu norm-falli
Sýnidæmi: Vigurreikningar
Lát \(x = (2,3,6)\) og \(y = (1,1,2)\). Þá gildir:
Aðgerðin í neðstu línunni nefnist innfeldi, og það er skilgreint með:
\[x \cdot y = x_0 y_0 + x_1 y_1 + \ldots + x_{n-1} y_{n-1}\]
þar sem bæði \(x\) og \(y\) eru \(n\)-staka vigrar.
10.3.2 Plús, mínus, margföldun og deiling í NumPy¶
Rifjum upp þegar aðgerðunum plús og sinnum (+
og *
) er beitt á lista þá
skeyta þær saman listum eða fjölfalda þá. Hér skilur leiðir með listum og
vigrum: Þegar þessar aðgerðir eru notaðar á vigra þá leggjast þeir saman eða
margfaldast eins og í stærðfræði. Hér er tafla yfir helstu NumPy reikniaðgerðir,
þar sem x, y og z eru vigrar en a er tala:
útreikningur |
skilar |
---|---|
|
margfaldar öll stök í x með tölunni a |
|
deilir með tölu a upp í öll stök x |
|
leggur a við öll stök x |
|
dregur a frá öllum stökum x |
|
leggur saman tilsvarandi stök, |
|
dregur frá, |
|
margfaldar tilsvarandi stök, |
|
innfeldi x og y |
Takið eftir margföldunarvirkinn *
reiknar ekki innfeldi heldur margfaldast
tilsvarandi stök saman. Slík notkun á margföldunarvirkja er ekki hefðbundin í
stærðfræði. Í Python er notaður sérstakur virki sem reiknar innfeldi, @
. Í
stærðfræði er líka óhefðbundið að leggja tölu við vigur eða draga frá.
Æfing: Vigurreikningar
Búið til vigrana \(x = (2,4,6)\) og \(y = (3,4,5)\) og reiknið í framhaldi:
\(x + y\)
\(3x - 2y\)
innfeldið \(x\cdot y\)
vigurinn \(z\) sem gefinn er með \(z_i = 2x_iy_i + 3x_i\)
10.3.3 Venjulegum stærðfræðiföllum beitt á vigra¶
Í NumPy eru sérstakar útgáfur af venjulegu stærðfræðiföllunum, sqrt, exp, log, sin,
cos o.s.frv. sem reikna fallsgildi í öllum stökum vigurs sem þeim er beitt á.
Þannig gefur np.sqrt(np.array([4,9,25]))
vigurinn \((2, 3, 5)\).
Æfing: Stærðfræðiföll af vigrum
Búið til vigurinn \((0, \pi/2, \pi, 3\pi/2, 2\pi)\) með því að byrja á að
búa til \((0, 1, 2, 3, 4)\) með np.arange
og margfalda hann svo með
\(\pi\) og deila með tveimur. Reiknið svo sínus, kósínus og tangens af
þessum vigri með np.
-hornaföllunum.
10.4 Rökvigrar og rökvísun¶
10.4.1 Rökvigrar (logical vectors)¶
Við höfum aðeins fengið nasasjón af listum með rökgildum í kafla 6.3. Slíkir listar (reyndar vigrar) eru talsvert notaðir þegar unnið er með NumPy. Það eru nefnilega ekki bara reiknivirkjarnir +, – * og / og stærðfræðiföll sem virka stakvís á vigra heldur gildir það líka um samanburðarvirkjana, < > <= >= == og !=.
Ef x og y eru jafnlangir vigrar þá er x < y
vigur af rökgildum með
\(i\)-ta sæti satt (True
) ef \(x_i < y_i\). Slíkan vigur má líka
reikna með yfirgripi (comprehension) sbr. kafla 6.7 þannig að:
x < y
er vigurinnnp.array(xi < yi for (xi,yi) in zip(x,y))
.
Svo mætti líka nota range
og len
til að fá sömu niðurstöðu með
np.array([x[i] < y[i] for i in range(len(x))])
. Í framhaldi má svo nota
innbyggðu föllin \(any\) og \(all\) til að athuga hvort eitthvert eða
öll stök rökvigranna séu sönn.
Sýnidæmi: Jákvæð stök og samanburður vigra
Lát \(x = (-1,3,-2,5)\) og \(y = (-2,2,3,4)\). Þá má gefa x og y gildi og finna út hvar stök \(x\) og \(y\) eru jákvæð og hvar \(x < y\) með Python forritsbútnum:
x = np.array([-1,3,-2,5])
y = np.array([-2,2,3,4])
xpos = x > 0
ypos = y > 0
xlessy = x < y
og svo má kanna t.d. hvort öll y-in séu jákvæð (sem þau eru ekki) með
if all(ypos):... # eða:
if all(y > 0):...
10.4.2 Rökvísun (logical indexing)¶
Hægt er að nota rökvigur sem vísi í vigur. Ef x er einhver vigur af tölum og I er vigur með rökgildum þá er x(I) vigur með stökum í sætum þar sem tilsvarandi sæti í I er satt. Skoðum þetta betur í næsta sýnidæmi.
Sýnidæmi: Rökvísun
Reiknum í framhaldi af síðasta sýnidæmi:
z = x[x < 0]
w = y[ypos]
Þá verður z vigurinn \((-1,-2)\) og w verður \((-1,-2)\). Það mætti líka nota skilyrt yfirgrip til að búa til z:
z = np.array([xi for xi in x if xi < 0]
Það er líka hægt að nota svona rökvísun vinstra megin í gildisgjafarsetningu til að breyta hluta af stökum vigurs eins og gert er í sýnidæminu í næsta kafla.
10.4.3 Stakvísir rökvirkjar¶
Ef beita á rökaðgerðunum og/eða/ekki stakvíst (element-wise) á öll stök vigra
er Python með sérstaka rökvirkja, nefnilega &
, |
og ~
í stað
venjulegu virkjanna and, or og not. Ef x og y eru eins og í sýnidæminu í kafla
10.4.1 þá verður xpos & ypos
rökvigur sem segir okkur hvar bæði
x og y eru jákvæðir (sem sé (False, True, False, True)
), xpos | ypos
segir hvar annar hvor er jákvæður ((False, True, True, True
) og ~xpos
segir hvar x er ekki jákvæður ((True, False, True, False)
).
Ath. ef formúla er með bæði samanburðarvirkja og stakvísan rökvirkja þarf að slá svigum utan um samanburðinn, t.d. bothpos = (x > 0) & (y > 0)
.
Hér er sýnidæmi sem sýnir hvernig má nota rökvísun og stakvísan ekki-virkja til að reikna vigur með gildum falls sem skilgreint er með gaffalformúlu:
Sýnidæmi:
Lát:
og x vera vigur af þétt liggjandi gildum t.d. x = np.linspace(-2,2)
. Þá
er hægt að reikna fallsgildi í öllum x-unum með
I = x < 0
y = np.zeros(len(x))
y[I] = x[I]**2
y[~I] = x[~I]**3
Svo mætti teikna fallið með plt.plot(x,y)
, því að Matplotlib getur teiknað
hvort sem er lista af tölum eða NumPy vigra.
Æfing: Rökvigrar
Látið \(x\) og \(y\) vera vigrana \((0, 14, 15, 16, 15, 13)\) og \((5,8,7,0,2,4)\). Finnið rökvigra sem svara til \(x_i \neq 0\), \(y_i \neq 0\) og í framhaldi vigur með True þar sem bæði \(x_i \neq 0\) og \(y_i \neq 0\). Búið svo til punktarit (scatter-plot) af jákvæðum pörum \((x_i,y_i)\).
10.5 Fylki í NumPy¶
10.5.1 Fylki er listi af listum¶
Í NumPy er fylki búið til með því að nota np.array
fallið á lista af listum, sem hver um sig gefur eina línu í fylkinu, og NumPy skrifar líka fylki út með svipuðum hætti.
Sýnidæmi: Fyrsta NumPy fylkið
Hér er forrit sem býr til fylkið \(A\) í kafla 10.1 og skrifar það út:
A = np.array([[1,2,3],
[6,7,8]])
print(A)
Forritið prentar út:
[[1 2 3]
[6 7 8]]
Það væri líka hægt að búa A til á einni línu með A = np.array([[1,2,3],[6,7,8]])
.
10.5.2 Stök fylkis, línur og dálkar¶
Hægt er að vísa í \(a_{ij}\) (þ.e.a.s. stakið í línu \(i\) og dálki
\(j\)) með A[i,j]
. Lína i fæst með A[i]
eða A[i,:]
og dálkur j
fæst með A[:,j]
. Eins og fyrir vigra þá byrjar Python að telja í 0 og þessar
vísanir má líka nota vinstra megin í gildisgjöf til að breyta stökum, línum eða
dálkum, t.d. A[0,0]=37
, A[0,:]=[2,2,2]
eða A[:,0]=0
(setur öll stök
í fremsta dálki = 0)`.
Athugasemd: Gildisgjöf gefur tilvísun
Ef gefin er skipunin
a0 = A[0,:]
þá er búin til tilvísun í fyrstu línuna en ekki ný breyta með gildi hennar
(sbr. kafla 5.3.4, 6.2 og 10.2.1). Í raun er verið að gefa línunni
nafn, þannig að framhaldsskipunin a0 = [2,2,2]
mundi breyta fyrstu
línunni í A. Á sama hátt mundi skipunin
B = A
búa til tilvísun í fylkið. Til að taka afrit á nýjan stað í minni tölvnnar má
nota aðferðina copy
, t.d. a0 = A[0,:].copy()
eða B = A.copy()
.
10.5.3 Núllfylki¶
Til að fá \(m \times n\) núllfylki má nota Z = np.zeros((m,n))
og Z =
np.zeros((m,n),int)
gefur heiltölu-núllfylki (það má líka skrifa
np.zeros((m,n),dtype=int)
).
Æfing: Margföldunartafla
Búið til \(2 \times 2\) núllfylki og prentið það út
Búið til fylkin
\[\begin{split}C = \begin{pmatrix}1 & 2\\3 & 4\end{pmatrix}\;\text{ og }\; D = \begin{pmatrix}5 & 0\\0 & 5\end{pmatrix}\end{split}\]Leggið svo neðri línu \(D\) við efri línu \(C\) og prentið út nýja \(C\)-ið.
Búið til \(10 \times 10\) fylki \(M\) með margföldunartöflu með því að byrja með heiltölu-núllfylki og reikna svo (í tvöfaldri for-lykkju):
\[m_{ij} = (i+1)(j+1)\quad (i=0,\ldots,9, j=0,\ldots, 9)\]
10.5.4 Bylting¶
Bylting (transpose) fylkis fæst með því að skipta á línum og dálkum.
Stærðfræðilegi rithátturinn fyrir byltingu fylkis \(A\) er \(A^T\),
lesið „A bylt“. Í NumPy má rita A.T
til að bylta fylki A
, til dæmis:
import numpy as np
A = np.array([
[3,2,1],
[0,1,0],
[2,2,2]])
B = A.T
print(B)
# Skrifar:
[[3 0 2]
[2 1 2]
[1 0 2]]
Athugasemd: Bylta fylkið er tilvísun
Fylkið B í dæminu hér að framan verður tilvísun í A bylt, sem uppfærist sjálfkrafa
ef A breytist. Til að fá nýtt fylki mætti nota B = A.copy().T
.
10.5.5 Afpökkun¶
Í ýmsu samhengi virkar fylki eins og samstæða af línum sínum, bæði þegar því er gefið gildi (eins og við höfum séð) en líka þegar það er notað til að gefa gildi. Ef A er 3 x 3 fylki má þannig skrifa
(u,v,w) = A
til að setja línur A
inn í u
, v
og w
. Það má líka sleppa svigunum: u,v,w = A
. Hér virkar A
eins og þrennd af línum sínum, og þegar þrennd er gefið gildi með A
fer hver lína inn í sitt stak – eftir par = (3,4); (u,v) = par
verður u=3
og v=4
. Þetta er kallað afpökkun (unpacking).
Slík afpökkun er notuð í næsta kafla þegar lesið er inn í NumPy vigra úr línum eða dálkum í skrá, og byltingin úr síðasta kafla er líka notuð.
Æfing: Bylting og afpökkun
Búið til fylkið:
Náið svo í dálka þess inn í tvo vigra með því að bylta því fyrst og afpakka svo.
10.5.6 Föll af fylkjum¶
Numpy er með ýmis föll sem hafa fylki sem viðfang. Fyrst má nefna NumPy-útgáfur
af venjulegum stærðfræðiföllum, sem beita má stakvís á fylki jafnt sem vigra,
sbr. grein 10.3.3. Í grein
11.5 eru föllin np.det
og np.inv
, sem reikna
ákveður og andhverfur, kynnt til sögunnar, og loks skulu nefnd föllin np.sum
sem finnur summu allra staka í fylki og np.shape
sem skilar tvennd með
fjölda lína og dálka. Hér hafa aðeins verið talin örfá af þeim fjölda
fylkjafalla sem NumPy hefur.
10.5.7 Föll til að búa til fylki¶
Við höfum þegar séð hvernig hægt er að búa til fylki með því að telja upp stökin
í því og nota np.array
, og líka hvernig búa má til núllfylki með fallinu
np.zeros
. Hér er tafla yfir þessi og fleiri föll til að búa til fylki, m.a.
nokkur sem verður nánar lýst í seinni köflum.
|
Býr til nýtt fylki úr L1, L2,… sem hver um sig er listi af stökum til að setja í línur fylkisins (allir jafn langir) |
|
Skilar \(m \times n\) núllfylki |
|
\(n \times n\) einingafylki, sjá kafla 11.2 |
|
(fyrir \(n\)-vigur |
|
\(m \times n\) slembifylki (sjá kafla 13.2) |
|
(fyrir \(n\)-vigra |
|
(fyrir n-vigra |
Í kaflanum um slembitölur (13.2) er lýst fleiri
föllum til að búa til slembifylki. Varðandi neðstu tvö föllin þá eru líka til
np.r_
og np.hstack
til að skeyta saman lóðrétt og lárétt en notkun
þeirra er óþægilegri en þessara tveggja.
10.5.8 Breytt um lögun¶
Hægt er að breyta um lögun fylkja ef fjöldi staka helst óbreyttur, og sömuleiðis
má breyta vigrum í fylki eða öfugt. Til dæmis má breyta \(3 \times 4\) fylki
í \(6 \times 2\) fylki. Hér er tafla sem sýnir ýmsa möguleika. Í töflunni
tákna A
og B
fylki og x
vigur.
|
breytir |
|
tekur stök |
|
Allar þessar skipanir taka stök |
|
Býr til \(n \times 1\) fylki úr \(n\text{-vigrinum}\) x (dálkfylki, column matrix) |
|
Býr til \(1 \times n\) fylki úr \(n\text{-vigrinum}\) x (línufylki, row matrix) |
Í öllum tilvikum má ekkert stak ganga af, t.d. þarf fjöldi staka í x
að vera
\(mn\) efst í töflunni. Nota má -1
fyrir víddir sem hægt er að reikna
út, t.d eru x.reshape(4,3)
og x.reshape(-1,3)
jafngildar ef x
hefur
12 stök.
Til að fara í gegn um stökin dálk fyrir dálk má nota byltingu, t.d. x = A.T.flatten()
eða B = A.T.reshape(m,n).T
.
Sýnidæmi: Bankayfirlit
Fyrir liggja upplýsingar um heildarfærslur tveggja bankareikninga í fjórum dálkum sbr. eftirfarandi mynd. Til að sýna sömu upplýsingar með nýju skipulagi í tveimur dálkum má nota skipun:
nýtt = gamalt.reshape(4,2)
Æfing: Bylting og ný lögun
Hægt er að nota byltingu og reshape saman til að gera frekari breytingar á skipulagi upplýsinga í töflum:
Hvernig töflu mundi gamalt.T.reshape(2,4) skila?
Búið til skipanir til að fá tvo dálka, einn fyrir hvort ár, og fjórar línur, fyrri tvær með innborgunum á A og B og seinni tvær með útborgunum.
10.6 Útskrift vigra og fylkja¶
10.6.1 Útprentun á skjá¶
Eins og sýnt hefur verið framar í þessum kafla má nota print-fallið til að
prenta bæði vigra og fylki á skjá. Slík útprentun inniheldur hins vegar mismarga
aukastafi, eftir því hve marga þarf til að sýna tölurnar með 8 stafa nákvæmni,
og auk þess er bætt við hornklofum fremst og aftast. Úr þessum göllum má bæta
með tvennu móti, með því að nota np.set_printoptions
eða np.savetxt
.
Næstu greinar útskýra þessa kosti.
10.6.2 Stjórn útprentunar¶
Með fallinu np.set_printoptions
má stjórna sniði útprentunar. Þetta fall
hefur ýmsa stika en hér látum við duga að segja frá þremur: precision = n
og
floatmode = "fixed"
gefur alltaf n aukastafi (án floatmode koma ≤ n
stafir), og suppress = True
þýðir að engar tölur eru prentaðar með
tugveldistáknun (t.d. -6.33e08 eða 5.22e-12). Til að prenta öll stök vigurs eða
fylkis án tugveldisvísis og með nákvæmlega þremur aukastöfum má nota:
np.set_printoptions(suppress=True, floatmode="fixed", precision=3)
Án suppress=True
hefur eitt lítið stak í vigri áhrif á prentun allra
stakanna, og án floatmode="fixed"
getur vantað 0 aftast í aukastöfunum. Hér
er dæmi til skýringar:
Lát x = np.array([0.000002, 1.25, 12.345]). Þá prentar print(x) út:
- með suppress=False: [2.000e-06 1.250e+00 1.235e+01]
- með suppress=True: [ 0.000 1.250 12.345]
- án floadmode="fixed": [ 0. 1.25 12.345]
10.6.3 Útprentun með savetxt¶
Annar möguleiki til að fá snyrtilega útprentun er að nota savetxt
-fallið með sniði:
from sys import stdout
np.savetxt(stdout, fylki, fmt="%w.df")
þar sem w er breidd hvers sviðs (hverrar tölu) og d er fjöldi aukastafa (t.d.
fmt="%6.2f")
. Þá sleppur maður við hornklofana í útprentuninni, en hinsvegar
verður að vita fyrirfram hver mesta breidd dálks þarf að vera.
10.7 Innlestur úr skrám¶
10.7.1 Talnalestur¶
Það er fremur auðvelt að lesa fylki úr textaskrá með fallinu loadtxt
.
Skráin verður að hafa jafnmörg svið (jafnmargar tölur) í hverri línu og sjálfgefið er að sviðin séu afmörkuð með bilum (sbr. kafla 8.3.4). Fyrir utan
textaskrár sem geymdar eru í núverandi möppu getur loadtxt
lesið skrár sem
eru á netinu án vandkvæða. Hér eru nokkur dæmi sem skýra notkunina:
skrá = 'datafile.txt' #
A = np.loadtxt(skrá) # les alla skrána inn í eitt fylki A
x,y,z = np.loadtxt(skrá) # les þriggja línu skrá inn í þrjá vigra
x,y,z = np.loadtxt(skrá).T # les þriggja dálka skrá inn í þrjá vigra
A = np.loadtxt(skrá, skiprows=1) # sleppir fyrstu línunni
A = np.loadtxt(skrá, usecols=(0,1)) # les bara fyrstu tvo dálkana
A = np.loadtxt(skrá, delimiter=',') # les csv-skrá
url = 'https://cs.hi.is/python/' #
netskrá = url + 'hiti-urkoma.txt' # skrá á netinu
(ár,hiti,úrk) = np.loadtxt(netskrá).T # les hana inn í þrjá vigra
Þessi dæmi miðast við að skráin innihaldi bara tölur, en þó mega vera
textastrengir í fyrstu línunni ef henni er sleppt með skiprows
, og eins mega
vera dálkar með strengjum ef þeim er sleppt með usecols
. Takið sérstaklega
eftir hvernig bylting er notuð í fjórðu línunni, og líka í neðstu línunni, til
að breyta þremur dálkum í þrjár línur, sem svo er afpakkað inn í þrjá vigra. Í
næsta kafla sjáum við hvernig hægt er að lesa inn textadálka.
Æfing: loadtxt
Lesið skrána https://cs.hi.is/python/hiti-urkoma.txt og plottið svo ártal og úrkomu.
Lesið https://cs.hi.is/python/malmar.txt og teiknið punktarit. Það þarf að sleppa bæði fyrstu línunni og fyrsta dálkinum.
10.7.2 Innlestur skráa með textadálkum¶
Í Numpy er hægt að lesa textafylki með því nota loadtxt(..., dtype=str)
.
Síðan er hægt að nota aðferðirnar astype
til að ná í talnadálka og
tolist
til að breyta textadálkum í lista af strengjum. Þetta er útskýrt með
eftirfarandi dæmi.
Sýnidæmi: Lestur textadálka
Skráin https://cs.hi.is/python/malmar.txt er með streng í fyrsta dálki, kommutölu í öðrum dálki og heiltölu í þeim þriðja. Hún er líka með titillínu. Hér er forrit sem les skrána
skrá = "https://cs.hi.is/python/malmar.txt"
(m,e,b) = np.loadtxt(skrá, skiprows=1, dtype=str).T
málmur = m.tolist()
eðlisþ = e.astype(float)
bræðslum = b.astype(int)
print(málmur)
print(eðlisþ)
print(bræðslum)
Forritið prentar út
['Ál', 'Járn', 'Kopar', 'Gull']
[ 2.7 7.87 8.96 19.3 ]
[ 933 1538 1085 1064]
Það mætti líka lesa með A = np.loadtxt(skrá...).T
og ná svo t.d. í
málmanöfnin með málmur = A[0].tolist()
.
10.7.3 CSV-skár úr Excel¶
Til að lesa Excel-skrár eru tvær leiðir bestar:
Að byrja að vista þær sem csv-skrár og lesa inn með NumPy
Að nota Pandas
Lítum hér á fyrri möguleikann. Í skránni https://cs.hi.is/python/allir-malmar.xlsx eru upplýsingar um alla 70 málmana sem hafa sætistölu minni en 94 (plúton), nánar tiltekið (dæmi í svigum):
efnatákn (Fe)
íslenskt nafn (járn)
sætistala (26)
eðlisþyngd (7,87)
bræðslumark (1535)
enskt nafn (iron)
Í Excel er hægt að vista skrána sem csv-skrá með því að velja File – Save As…. Það hefur þegar verið gert og niðurstaðan skrifuð í
Þetta var gert með tölvuna stillta á íslensku og þá koma kommur í stað punkta í eðlisþyngdirnar. CSV-skrána má lesa inn með:
skrá = "https://cs.hi.is/python/allir-malmar.txt" A = np.loadtxt(skrá, skiprows=1, delimiter=';', dtype='str').T efnatákn = A[0].tolist() nafn = A[1].tolist() sætistala = A[2].astype(int) A3 = np.char.replace(A[3], ",", ".") eðlisþyngd = A3.astype(float) bræðslumark = A[4].astype(int) enskt_nafn = A[5].tolist()
Hér hefur fallið np.char.replace
verið notað til að breyta kommutölunum í
enska útgáfu, sem er sú eina sem Python skilur.
Æfing: Allir málmar
Smellið bæði á Excel-skrána (ef þið eruð með Excel) og CSV-skrána og skoðið innihaldið
Lesið csv-skrána með því að keyra forritsbútinn hér á undan og búið svo til punktarit af sætistölu og eðlisþyngd.
Búið til súlurit af bræðslumarki
Opnið Excel-skrána og búið til csv-skrá (ef þið hafið Excel)
10.8 Listi yfir skrár á cs.hi.is/python¶
Eftirfarandi skrár sem koma við sögu ýmist í sýnidæmum, æfingum eða verkefnum í
þessum fyrirlestrarnótum eru á https://cs.hi.is/python
. Þær má nota til að
prófa ýmsar aðferðir til að lesa skrár og vinna með gögn í NumPy (eða Pandas).
Aðferðirnar sem lýst er að framan duga ekki til að lesa skrána simaskra.txt, en hún er með dálka aðskilda með kommu og runu af bilum. Til að lesa hana má nota:
(nafn, sími, heimili) = np.genfromtxt(
'https://cs.hi.is/python/simaskra.txt',
skip_header = 1,
delimiter = ',',
autostrip = True,
dtype = str).T.tolist()
Fallið genfromtxt er systurfall loadtxt með aðeins aðra valkosti, m.a.
autostrip, auk þess sem skip_header kemur í stað skiprows. Vegna þess að
það eru engir talnadálkar er hægt er að hengja .tolist()
aftan á
innlestrarskipunina til að breyta öllum dálkunum í venjulega lista af strengjum
í einu lagi.
Önnur skrá sem er sérstök er flokksnofn.txt sem er með svið aðskilin með
tab-táknum. Til að lesa hana með np.loadtxt
dugar að setja delimiter =
'\t'
. Svo eru heldur engir talnadálkar í þeirri skrá svo það er líka hægt að
hengja .T.tolist()
aftan á loadtxt
-kallið (sjá verkefni
16c).