Uke 13 — numpy ============== Numpy er en av de mestbrukte eksterne biblioteker for Python. Ved bruk av den nye datatypen ``numpy.array`` kan vi lagre store mengder numerisk data på en effektiv måte. For mer detalj, se på https://numpy.org/doc/stable/user/absolute_beginners.html Eksempler --------- Her viser vi ting i en REPL - python's interaktiv modus. Du kan gjøre det samme ved **VSCode -> View -> Command Palette -> Python: Start REPL** (eller skriv `python` i terminalen på Mac/Linux). Bruk ``exit()`` for å avslutte REPL. Vi kan lage et array direkte fra en liste og vi kan bruke den samme indeks-notasjonen:: >>> import numpy as np >>> a = np.array([1., 4., 5., 8.]) >>> a array([1., 4., 5., 8.]) >>> type(a) >>> a[:2] array([1., 4.]) >>> a[3] 8.0 >>> a[1:3] = 99 >>> a array([1., 99., 99., 8.]) >>> a[:] = 11 >>> a array([11., 11., 11., 11.]) For flerdimensionale (nøstete) arrays har vi en enklere indeks-notasjon:: >>> a = np.array( [ [1., 2., 3.], [4., 5., 6.] ] ) >>> a[0,0] # a[0][0] 1.0 >>> a[1,2] # a[1][2] 6.0 >>> a.shape (2,3) Vi kan ha (nesten) så mange dimensjoner vi vil. Her er et 3D array:: >>> b = np.array([[[111., 112.], [121., 122.]], [[211., 212.], [221., 222.]]]) >>> b array([[[111., 112.], [121., 122.]], [[211., 212.], [221., 222.]]]) >>> b.shape (2, 2, 2) >>> b[1,1,1] 222.0 >>> b[0,0,0] 111.0 Det finnes flere hjelpefunksjoner for å lage nye arrays. For hver metode nedenfor, kan du fortelle hva skjer?:: >>> np.arange(1., 2., 0.1) # fast skrittstørrelse array([1. , 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9]) >>> np.linspace(30,40,5) # fast start/end, fast antall verdier array([ 30. , 32.5, 35. , 37.5, 40. ]) >>> np.ones((2,3)) array([[ 1., 1., 1.], [ 1., 1., 1.]]) >>> np.zeros(7) array([0., 0., 0., 0., 0., 0., 0.]) >>> np.full((2,2), 7.) array([[7., 7.], [7., 7.]]) >>> np.random.random_sample((2,2)) array([[0.33896244, 0.75553158], [0.42116679, 0.32801477]]) Alle matematiske operasjonene skjer samtidig for alle elementer, vi bør ikke skrive en løkke:: import numpy as np a = np.arange(10.) print(a) # [[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]] b = a + 7 print(b) # [[ 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. ]] c = b ** 2 print(c) # [[ 49. 64. 81. 100. 121. 144. 169. 196. 225. 256. ]] print(c - b) print(a + b) print(b * a) print(np.sin(a)) Numpy kan også brukes til matriseregning:: >>> a = np.array( [ [1., 2.], [3., 4.] ] ) >>> b = np.array( [ [4., 3.], [2., 1.] ] ) >>> np.dot(a, b) # matrise-multiplikasjon ("matrix dot product") array([[ 8., 5.], [20., 13.]]) >>> a @ b # lettere måte å skrive det samme ("a ganger b") array([[ 8., 5.], [20., 13.]]) >>> a * b # OBS: ikke matrise-multiplikasjon array([[4., 6.], [6., 4.]]) >>> np.linalg.det(b) # determinanten til en matrise -2.0 >>> np.linalg.inv(b) # inversen til en matrise array([[-0.5, 1.5], [ 1. , -2. ]]) >>> b @ np.linalg.inv(b) # b ganger sin egen invers er identiteten (hurra) array([[1., 0.], [0., 1.]]) Numpy kan stort sett gjøre alt du trenger med matriser. Alle funksjonene finnes her: https://numpy.org/doc/stable/reference/routines.linalg.html numpy og matplotlib er enkelt å bruke sammen:: import numpy as np import matplotlib.pyplot as plt xs = np.linspace(0, 5, 100) ys = np.sin(xs) + 1/3 * np.sin(3 * xs) plt.plot(xs, ys) plt.show() Vi kan også sammenligne arrays, resultatet blir et array av bool:: >>> a = np.array([[6, 4], [5, 9]]) >>> a >= 6 array([[ True, False], [False, True]], dtype=bool) Slike boolean-arrays kan brukes som index:: >>> a = np.arange(10.) >>> filt = a ** 2 > 25 # kvadrat større enn 25 >>> a[filt] array([6., 7., 8., 9.]) Og i vår plot-eksempel:: import numpy as np import matplotlib.pyplot as plt xs = np.linspace(0, 5, 100) ys = np.sin(xs) ys[ys > 0.5] = 0.5 # Hva skjer her? Hvilke verdier endres? ys[ys < -0.5] = -0.5 # Hva skjer her? Hvilke verdier endres? plt.plot(xs, ys) plt.show() Større numpy/matplotlib eksempler (animation er ikke pensum) ------------------------------------------------------------ .. toctree:: :maxdepth: 2 landcover/index animation/index Oppgaver -------- Oppgave 1 .......... Lag et numpy-array av den følgende lista og bruk nøstet index-notasjon (f.eks `a[2, 0]`) til å printe verdien 93:: xs = [[34, 13, 7], [86, 96, 93], [72, 47, 42]] Oppgave 2 .......... Ta numpy-arrayet du lagde i forrige oppgave og bruk slice notasjon til å printe den første kolonnen. Oppgave 3 .......... Ta igjen numpy-arrayet du lagde i den første oppgaven og bruk slice notasjon til å printe verdiene til de to siste radene i de to første kolonnene. Oppgave 4 .......... Bruk `numpy.arange` til å lage et numpy-array med alle oddetallene fra 43 (inkludert 43) til 100. Print ut resultatet. Oppgave 5 .......... Bruk `numpy.linspace` til å lage en numpy-array med 9 elementer som er likt fordelt mellom 0 og 3 (lik forskjell mellom alle elementene). Print ut resultatet. Oppgave 6 .......... Bruke numpy.reshape til å konvertere numpy-arrayet ``arr`` til et array med 3 rader og 5 kollonner:: import numpy as np arr = np.arange(1,16) Print ut resultatet. Oppgave 7 .......... En parabel er gitt av andregradsfunksjonen .. math:: y = ax^2 + bx + c . Last ned :download:`uke13_oppgave_7.py ` og fyll inn funksjonen `parabola` slik at den returnerer et numpy-array og programmet tegner en parabel. Bruk numpy-funksjonalitet, **ikke** en løkke. Oppgave 8 .......... Bruk numpy til å skrive ut alle partallene fra numpy-arrayet ``arr``:: import numpy as np arr = np.arange(1,16) Bruk **bare** numpy-funksjonalitet, **ikke** en løkke. Oppgave 9 .......... Bruk numpy til å bytte ut alle partallene fra numpy-arrayet ``arr`` med verdien ``0``:: import numpy as np arr = np.arange(1,16) Bruk **bare** numpy-funksjonalitet, **ikke** en loop. Skriv ut resultatet. Oppgave 10 .......... .. toctree:: :maxdepth: 1 randomwalk/walk