Del 1: Introduksjon til programmering i Python¶
Husk:
Shift+Enter
for å kjøre en celle og gå ned til neste celle, ogCtrl+Enter
for å kjøre cellen og bli i samme celle.- Tekstblokkene er også celler som kan kjøres med disse kommandoene, men det eneste som skjer er at teksten formatteres.
- å kjøre cellene i kronologisk rekkefølge.
Del 1: Tall og variabler¶
Til å begynne med trenger man å vite hvordan man lager og bruker variabler, og hvordan man kan jobbe videre med disse variablene. Vi starter med en variabel som vi kaller x
.
x=3
Så snart man har =
har man en ny variabel. For å se variabelen kan man skrive:
x
Om man vil ha litt mer informasjon kan man lage en printsetning for å beskrive variabelen:
print('variabelen som heter x =',x)
Vi lager en ny variabel y
:
y=5
For å printe ut begge disse variablene kan man skrive
x, y
Eller, f.eks.,
print(x)
y
Det er kun den siste linjen i en celle som printes ut automatisk. Skriver man f.eks. som i cellen under blir bare veridien til y
skrevet ut.
x
y
Siden variablene x
og y
er på samme format kan vi f.eks. addere dem sammen og lagre i en ny variabel som kan hete hva du vil, f.eks. resultat
.
resultat=x+y
resultat
print(x+y) # Addere x og y sammen
print(x*y) # Eller gange dem sammen
print(x-y) # Eller subtrahere dem
print(x/y) # Eller dele dem
Stort sett jobber man imidlertid ikke med enkelt-tall: vanligvis har vi lister eller matriser med verdier. Det kan se ut slik som dette:
z=[1,2,3,4,5,6] # Lag variabelen z
z # Skriv ut innholdet til variabelen z
Listen z
er på Python sitt innebygde format for lister. Slike lister er en ok måte å lagre noen typer informasjon på, f.eks. indekser (som vi kommer til litt seinere i denne oppgaven), men vi lagrer ikke faktiske data på dette formatet. Grunnen er at vanlige matematiske vektorregler ikke gjelder for disse listene.
Hvis vi ganger x=3
med z
ville man forvente at alle elementene i z
ble ganget med 3. Men dette er ikke det som skjer:
x*z
Del 2: Numpy¶
I stedet legges x=3
versjoner av z
seg etter hverandre.
På grunn av dette styrer vi unna denne måten å lage lister på, og jobber heller med numpy arrays
. Et array er det samme som en matrise. Numpy er et bibliotek for matriseregning - dette er akkurat det vi trenger når vi skal jobbe med ekte datasett!
Vi må importere Numpy-biblioteket for å kunne bruke funksjonene:
import numpy as np # for matematikk m.m.
Med Numpy får vi tilgang på veldig mange nyttige funksjoner. Man bruker dem som dette: np.navn_på_funksjon(z)
, for eksempel np.mean(z)
. Vi kommer tilbake til funksjoner seinere.
I numpy
kan man definere en vektor (en en-dimensjonal matrise) som dette:
arr1=np.array([1,2,3,4,5,6])
arr1
For Numpy
gjelder vanlige vektorregler.
Addisjon: Vi kan addere arr1
og arr2
fordi de er like lange, men ikke arr1
og arr3
fordi arr3
er kortere enn arr1
:
arr2=np.array([5,3,5,2,4,6])
arr3=np.array([5,2,4,6])
print('arr1+arr2:',arr1+arr2)
arr1+arr2: [ 6 5 8 6 9 12]
Derfor får vi en feilmelding når vi kjører cellen under:
print('arr1+arr3:',arr1+arr3)
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-17-b8d8b624c93a> in <module> ----> 1 print('arr1+arr3:',arr1+arr3) ValueError: operands could not be broadcast together with shapes (6,) (4,)
Multiplikasjon: Hvis vi nå ganger x
med arr1
skjer det vi forventet da vi ganget x
med z
: alle elemetene i arr1
blir ganget med 3:
x*arr1
array([ 3, 6, 9, 12, 15, 18])
array.shape: To veldig nyttige hjelpemiddel når man jobber med lister og matriser er x.shape
og len(x)
, der x er variabelen. Med shape
sjekker man dimensjonene til et array
, mens len()
kan brukes til å sjekke lengden til en liste.
print(len(z)) # listen `z` er len(z)=6 elementer lang
print(z)
6 [1, 2, 3, 4, 5, 6]
arr1.shape # matrisen arr1 har kun 6 rader, altså er arr1 en vektor.
(6,)
2 dimensjoner: Ønsker man en matrise med f.eks. to dimensjoner kan man også bruke np.array()
. Disse to dimensjonene kan være for tid og temperatur - slik som i datasettet dere skal jobbe med seinere.
arr4=np.array([[1,2,3],[3,4,5]])
arr4
array([[1, 2, 3], [3, 4, 5]])
arr4.shape # matrisen arr4 har 2 rader og 3 kolonner.
(2, 3)
Her kommer et viktig poeng: I python er rader første element og kolonner andre element. Når shape
til matrisen/arrayet arr4
er (2,3)
betyr dette altså at arr4
har 2 rader og 3 kolonner. Dette er viktig for indeksering - det kommer vi tilbake til i neste bolk.
Tenk Race Car: Rows then Columns.
Oppgave 1:¶
- Lag tre nye variabler x, y, og z. Når du lager disse overskrives variablene vi laget over. La x og y være heltall eller desimaltall, og la z være et 1D-array.
- Lag en ny variabel som er lik
x+y
. Print ut resultatet. - Lag enda en ny variabel som er lik variabelen
x+y
ganget medz
. - Lag en ny variabel som er et 2D-array med 2 rader og 3 kolonner. Adder dette arrayet med arr4.
- Lag et array med 4 rader og 2 kolonner. Sjekk at dimensjonene er riktige med
.shape
For å lage nye celler for å lage en variabel eller gjøre en beregning kan du enten trykke på +
-tegnet oppe til venstre, eller du kan trykke Esc+b
for en ny celle under den du er i, eller Esc+a
for en ny celle over den du står i.
arr5=np.array([[1,2,3,4],[3,4,5,0.4],[3,4,5,0.4],[3,4,5,0.4]])
arr5
array([[1. , 2. , 3. , 4. ], [3. , 4. , 5. , 0.4], [3. , 4. , 5. , 0.4], [3. , 4. , 5. , 0.4]])
arr5.shape
(4, 4)
x=7
y=10
y
10
Del 3: Indeksering¶
En indeks beskriver hvilken del av et array du ser på eller bruker i beregninger.
Her er er par nyttige huskeregler for indeksering i python:
- Man bruker klammeparanteser
[]
rundt indekser. - Første indeks er alltid 0. Har du f.eks. listen
x=[5, 12, 4, 7, 3, 0]
vilx[0]=5
. - Hvis du kun vil bruke de tre første elementene i x, så skriver du
x[:3]
. - Hvis du kun vil bruke de to siste elementene i x, så skriver du
x[4:]
. - Den siste indeksen du oppgir blir ikke med i resultatet: skriver du
x[2:5]
velger du ut element 2 til MEN IKKE MED element 5.x[2:5]=4, 7, 3
.
Vi tar utgangspunkt i variablene vi lagde i forrige del, arr1
som er 1D og arr4
som er 2D.
1D-indeksering
Lag ett 1D-array
arr1=np.array([5, 12, 4, 7, 3, 0])
Finn verdiene fra indeks 3 og til slutten av arrayet:
arr1[3:]
array([7, 3, 0])
Finn de to første verdiene:
arr1[:2]
array([ 5, 12])
Hvis vi skal ha tak i
- første element i
arr1
- siste element i
arr1
- første til og med andre element i
arr1
- de tre siste elementene i
arr1
kan vi skrive som under:
print('første element i arr1:', arr1[0])
print('siste element i arr1:', arr1[5])
print('første til og med andre element i arr1:', arr1[:2])
print('de tre siste elementene i arr1:', arr1[3:])
første element i arr1: 5 siste element i arr1: 0 første til og med andre element i arr1: [ 5 12] de tre siste elementene i arr1: [7 3 0]
Telle baklengs: Man kan også starte indekseringen på slutten av matrisen og telle bakover. Dette er praktisk når man jobber med lange matriser, eller hvis man f.eks. vil ha tak i de ti siste elementene. Da er det lettere å lese koden om man teller baklengs. Syntaksen er slik: det siste elementet har indeks -1
. Det nest siste har indeks -2
.
Hvis vi skal ha tak i det siste elementet i arr1
har man altså to muligheter:
print(arr1[5])
print(arr1[-1])
0 0
Dersom arr1
var f.eks. 23135 elementer langt er det mye ryddigere å skrive arr1[-1]
enn arr1[23134]
. Med arr1[-1]
skjønner man med en gang at det er snakk om siste element. Med arr1[23134]
må man vite på forhånd at arr1
har 23135 elementer for å skjønne at det er siste element man er ute etter.
For å ha tak i de tre siste elementene i arr1
skriver man:
arr1[-3:]
array([7, 3, 0])
Oppgave 2:¶
- Lag et Numpy-array
x
med 5 elementer. - Finn det første elementet i
x
- Finn element to til og med 4 i
x
. - Finn det siste elementet i
x
på to forskjellige måter. - Finn de tre siste elementene i
x
ved å telle baklengs.
test=np.array([4,65,73,2,91,48.7,85])
test
array([ 4. , 65. , 73. , 2. , 91. , 48.7, 85. ])
test[1:5]
array([65., 73., 2., 91.])
arr6=np.array([34, 23, 1, 4, 75])
np.array([34, 23, 1, 4, 75])
array([34, 23, 1, 4, 75])
arr6[1:4]
array([23, 1, 4])
2D-indeksering
Husk tilbake: I python er rader* første element og kolonner andre element. Når shape
til matrisen/arrayet arr4
er (2,3)
betyr dette altså at arr4
har 2 rader og 3 kolonner. Dette er viktig for indeksering - tenk Race Car: Rows then Columns.*
Vi jobber videre med 2D-arrayet vårt arr4:
arr4
array([[1, 2, 3], [3, 4, 5]])
Hvis vi skal ha tak i elementet på første rad i første kolonne av arr4
skriver man:
arr4[0,0]
1
For å få tak i elementene på
- første rad og andre kolonne
- første rad og andre til og med tredje kolonne
- siste rad og nest siste til og med siste kolonne
- begge rader og de to første kolonnene
print('1)', arr4[0,1])
print('2)', arr4[0,1:])
print('3)', arr4[1,-2:])
print('4)', arr4[:,:2])
1) 2 2) [2 3] 3) [4 5] 4) [[1 2] [3 4]]
Oppgave 3:¶
- Lag et nytt array
y
med tre rader og 4 kolonner. - Finn elementene på første rad og de tre første kolonnene
- Finn elementene på de to siste radene og den siste kolonnen på to forskjellige måter.
arr6=np.array([[2,45,6,34], [7,4,12,76], [3,5,0,13]])
arr6
array([[ 2, 45, 6, 34], [ 7, 4, 12, 76], [ 3, 5, 0, 13]])
Del 4: Last inn et ekte datasett!¶
I denne delen laster vi inn et datasett med årlig temperatur i Bergen siden 1861. Vi bruker en funksjon som heter loadData
som er definert i filen "EkteDataFunk.py" i mappen "Funksjoner". Denne filen er en del av alt dere har lestet ned, og filen "TempBergenYearlyNonan.txt" ligger i mappen "data".
For å få cellen under til å fungere må du bytte stien til mappen "Funksjoner" (altså "W:\Work\Documents\EkteData\EkteData\Funksjoner") med stien til der du har plassert mappen med Ekte Data-filer på din maskin. Dette er sikkert noe slik som "C:\User\Username\Documents...\Funksjoner". Se på filen Huskeregler.ipynb i mappen "Kom_i_gang" for en beskrivelse av hva en "sti" er.
import sys
# !!! Bytt ut W:\Work\Documents\EkteData\EkteData\Funksjoner med sien på
# DIN Pc !!!
sys.path.append(r"W:\Work\Documents\EkteData\EkteData\Funksjoner")
from EkteDataFunk import loadData # for filinnlasting
--------------------------------------------------------------------------- ModuleNotFoundError Traceback (most recent call last) <ipython-input-1-5dc2928a9e4e> in <module> 4 sys.path.append(r"W:\Work\Documents\EkteData\EkteData\Funksjoner") 5 ----> 6 from EkteDataFunk import loadData # for filinnlasting ModuleNotFoundError: No module named 'EkteDataFunk'
file='TempBergenYearlyNonan.txt' # Navnet på filen vi skal laste inn
data = loadData(file, rydd='N') # Bruk funksjonen loadData til å laste inn filen
data # Dette printer ut alle verdiene i "data"
Variabelen data
er på nøyaktig samme format som arrayet arr4
vi så på over. Forskjellen er at arr4
hadde to rader og tre kolonner, mens data
har 160 rader og to kolonner.
print(arr4.shape)
data.shape
(2, 3)
(160, 2)
Nå kan vi bruke det vi har gått gjennom om variabler og indeksering til å lage to nye variabler: en over årene, altså alle radene i den første kolonnen, og en over temperaturen, altså alle radene i den andre kolonnen.
tid=data[:,0] # alle rader ":", første kolonne "0"
tid # print ut variabelen
array([1861., 1862., 1863., 1864., 1865., 1866., 1867., 1868., 1869., 1870., 1871., 1872., 1873., 1874., 1875., 1876., 1877., 1878., 1879., 1880., 1881., 1882., 1883., 1884., 1885., 1886., 1887., 1888., 1889., 1890., 1891., 1892., 1893., 1894., 1895., 1896., 1897., 1898., 1899., 1900., 1901., 1902., 1903., 1904., 1905., 1906., 1907., 1908., 1909., 1910., 1911., 1912., 1913., 1914., 1915., 1916., 1917., 1918., 1919., 1920., 1921., 1922., 1923., 1924., 1925., 1926., 1927., 1928., 1929., 1930., 1931., 1932., 1933., 1934., 1935., 1936., 1937., 1938., 1939., 1940., 1941., 1942., 1943., 1944., 1945., 1946., 1947., 1948., 1949., 1950., 1951., 1952., 1953., 1954., 1955., 1956., 1957., 1958., 1959., 1960., 1961., 1962., 1963., 1964., 1965., 1966., 1967., 1968., 1969., 1970., 1971., 1972., 1973., 1974., 1975., 1976., 1977., 1978., 1979., 1980., 1981., 1982., 1983., 1984., 1985., 1986., 1987., 1988., 1989., 1990., 1991., 1992., 1993., 1994., 1995., 1996., 1997., 1998., 1999., 2000., 2001., 2002., 2003., 2004., 2005., 2006., 2007., 2008., 2009., 2010., 2011., 2012., 2013., 2014., 2015., 2016., 2017., 2018., 2019., 2020.])
temp=data[:,1] # alle rader ":", andre kolonne "1"
temp
Del 5: bruk funksjoner fra Numpy
¶
For å få litt oversikt over den årlige temperaturen i Bergen siden 1861 kan det være nyttig å se på verdier som gjennomsnitt, maksverdi, minverdi, og standardavvik. Numpy
har innebygde funksjoner for dette:
np.mean(temp)
7.6283759469696975
print('Gjennomsnittstemperatur: ', np.mean(temp), '\u2103')
print('Maks-temperatur: ', np.max(temp), '\u2103')
print('Min-temperatur: ', np.min(temp), '\u2103')
print('Standardavvik: ', np.std(temp), '\u2103')
Gjennomsnittstemperatur: 7.6283759469696975 ℃ Maks-temperatur: 9.908333333333333 ℃ Min-temperatur: 5.958333333333332 ℃ Standardavvik: 0.7350653423327863 ℃
De nye variablene temp
og tid
kan indekseres på samme måte som i eksemplene over. Skal vi f.eks. beregne gjennomsnittet av de 10 første årene gjør vi som dette:
np.mean(temp[:10])
7.286969696969697
Skal vi beregne gjennomsnittet over de ti siste årene gjør vi som dette:
np.mean(temp[-10:])
8.740833333333333
Som en test på at dette faktisk er gjennomsnittet av de ti første årene kan du sjekke lengden av temp[:10]
:
temp[:10].shape
(10,)
Oppgave 4:¶
- Finn gjennomsnittstemperatur og standardavvik for de 50 første årene.
- Finn gjennomsnittstemperatur og standardavvik for de 50 siste årene.
Selv om verdier som gjennomsnitt er nyttige for å beskrive temperatur, er det vanskelig å få et ordentlig inntrykk av hvordan den årlige temperaturen siden 1861 har variert kun ved å se på verdier slik som dette. Det beste er å se på en figur av tidsserien.
Del 6: Lag en figur¶
Akkurat som at vi trenger biblioteket Numpy
for å lage matriser og utføre matematiske operasjoner som å finne gjennomsnitt trenger vi et bibliotek for å lage figurer. Vi bruker matplotlib
:
import matplotlib.pyplot as plt
plt.plot(tid, temp)
[<matplotlib.lines.Line2D at 0x280a8f09b80>]
Figuren over gjenspeiler det vi fant med å beregne gjennomsnitt: de første 50 årene var kaldere enn de siste 50 årene, makstemperatur er nesten 10 grader, min temperatur er ca 6 grader, og verdiene holder seg stort sett under en grad unna gjennomsnittet. Men vi får mye mer informasjon på kjøpet, som når det var varmest og kaldest, og at temperaturen ikke har økt jevnt.
Figurer bør alltid kunne tolkes uten særlig mye tilhørende tekst - vi må legge på tittel, navn på aksene etc.
plt.plot(tid, temp)
plt.title('Gjennomsnittlig årsnedbør Bergen')
plt.xlabel('År')
plt.ylabel('Temperatur [\u2103]') # \u2103 er kode for "grader celcius"
# Linjen under avgrenser x-aksen slik at det ikke er "whitespace" på
# endene slik som i figuren over
plt.xlim(tid[0], tid[-1])
# Linjen under gjør bare at informasjon om forrige linje ikke printes ut.
# Du kan kommentere den ut og kjøre denne cellen på nytt for å se
plt.show()
Man kan lage en figur som kun viser en del av datasettet ved å indeksere på samme måte som vi har gjort tidligere. For å f.eks. kun plotte de 100 siste årene gjør man som dette:
plt.plot(tid[-100:], temp[-100:])
plt.title('Gjennomsnittlig årsnedbør Bergen')
plt.xlabel('År')
plt.ylabel('Temperatur [\u2103]')
plt.xlim(tid[-100], tid[-1])
plt.show()
Man kan også plotte flere linjer i samme figur. Da bare legger man til en linje med plt.plot()
for hver ting man vil plotte. Plottelinjene lages da i den rekkefølgen man skriver dem.
Et lite notat om linjen der vi plotter den røde linjen for gjennomsnitt i cellen under: Vi kan skrive plt.hlines()
fordi plt.hlines()
er en innebygd funksjon Matplotlib
har for å plotte horisontale linjer. Tilsvarende finnes plt.vlines()
for vertikale linjer. Vi kommer tilbake til hvordan man finner ut a slike funksjoner finnes og hvordan man bruker dem seinere når vi ser på dokumentasjon. For å gi et hint: jeg ville bare googlet "plot horizontal line matplotlib" hvis jeg ikke husket om det fantes en funksjon for dette eller hvordan den fungerte.
plt.plot(tid, temp) # Plot hele tidsserien
plt.plot(tid[-100:], temp[-100:]) # Plot kun de siste 100 årene
# Plot gjennomsnittet som en rød linje.
plt.hlines(np.mean(temp), tid[0], tid[-1], color='red')
plt.title('Gjennomsnittlig årsnedbør Bergen')
plt.xlabel('År')
plt.ylabel('Temperatur [\u2103]')
plt.xlim(tid[0], tid[-1])
plt.show()
Den oransje linjen er nå de 100 siste årene og er plottet oppå den blå linjen som viser hele tidsserien. Den røde linjen viser gjennomsnittet til hele tidsserien. For å lage denne bruker vi funksjonen plt.hlines()
som står for "horizontal lines". Man gir funksjonen 1) y-verdien linjen skal krysse, 2) startverdien til linjen, og 3) sluttverdien til linjen langs x-aksen. I eksempelet over er dette 1) np.mean(temp)
, 2) tid[0]
, og 3) tid[-1]
.
Oppgave 5:¶
Lag en figur som viser disse tingene:
- hele tidsserien
- de første 75 årene
- gjennomsnittet til hele tidsserien
- gjennomsnittet til de 75 første årene.
Lag så en ny figur som viser
- årene fra det 50ende året frem til det 50ende siste året
- gjennomsnittet til denne perioden
- gjennomsnittet pluss og minus standardavviket til denne perioden.
plt.plot(tid, temp)
plt.plot(tid[:75], temp[:75])
plt.hlines(np.mean(temp), tid[0], tid[-1], color='red')
plt.hlines(np.mean(temp[:75]), tid[0], tid[75], color='red')
plt.title('Gjennomsnittlig årsnedbør Bergen')
plt.xlabel('År')
plt.ylabel('Temperatur [\u2103]')
plt.xlim(tid[0], tid[-1])
plt.show()
plt.plot(tid[50:-50], temp[50:-50])
plt.hlines(np.mean(temp[50:-50]), tid[50], tid[-50], color='red')
plt.hlines(np.mean(temp[50:-50])-np.std(temp[50:-50]), tid[50], tid[-50], color='green')
plt.hlines(np.mean(temp[50:-50])+np.std(temp[50:-50]), tid[50], tid[-50], color='green')
plt.title('Gjennomsnittlig årsnedbør Bergen')
plt.xlabel('År')
plt.ylabel('Temperatur [\u2103]')
plt.xlim(tid[50], tid[-50])
plt.show()
Last ned og prøv selv: