Behandling av store datamengder i Python
Nedlasting av datafiler fra Statistisk Sentralbyrå
Når vi skal jobbe med store sett med data, er programmering et nyttig verktøy. Mye kan også gjøres i regneark, men her skal vi se på hvordan vi kan bruke Python til å behandle store datasett.
Når vi skal behandle data i Python, er det første vi må gjøre, å laste ned ei fil med dataene og lagre den i et hensiktsmessig format. Gode formater å jobbe med er .txt og .csv. Når vi laster ned filer med stort tallmateriale fra ulike statistikker, er det ofte lurt å bruke .csv.
Vi skal se på noen data om mediebruk fra Statistisk sentralbyrå (SSB). Du finner datasettet som ei nedlastbar fil nederst på denne siden, men prøv helst å laste ned fila selv, fra nettsiden https://www.ssb.no/statbank/table/04495/.
Datasettet som er brukt i eksempelet, er hentet fra Statistikkbanken til SSB. Datasettet inneholder opplysninger om hvor mange minutter en gjennomsnittsnordmann brukte på ulike medier per dag de siste årene. Følg framgangsmåten nedenfor for å velge ut data fra nettsiden:
- Gå til nettsiden (se over).
- Sørg først for at "Minutter brukt til ulike medier en gjennomsnittsdag" er valgt i boksen "Statistikkvariabel".
- Velg deretter alle medietypene i boksen "Medietype" ved å klikke på knappen med grønn hake (eller velg alle manuelt i menyen).
- Velg årene 2010 til 2019 i boksen "År".
Trykk på knappen "Vis tabell".
Når du har gjort dette, vil nettsiden vise en tabell som du kan se utdrag fra nedenfor:
Medium | 2010 | 2011 | 2012 |
---|---|---|---|
Papiravis | 23 | 24 | 21 |
Fjernsyn | 152 | 157 | 131 |
Radio | 81 | 86 | 88 |
Spørsmål
Hva betyr tallet 131 i ruta for fjernsyn i året 2012?
Svar
Tabellen viser minutter brukt på ulike medier en gjennomsnittsdag. Tallet 131 for fjernsyn i året 2012 viser at en nordmann i gjennomsnitt brukte 131 minutter per dag til å se på fjernsyn i 2012.
For å laste ned ei fil med disse dataene gjør du følgende:
- Velg "Lagre data som..." til venstre for tabellen.
- Velg "Semikolonseparert med overskrift (csv)".
- Trykk "Lagre".
- Kopier fila over til samme mappe på pc-en som Python-programmene dine ligger i. Det gjør det lettere å referere til fila i programmet som skal bruke den.
- Endre filnavnet til "ssbmedier.csv".
Innlesing av datafila
Python-modulen Pandas bruker vi både til å lese datafila inn i Python og til å behandle dataene etterpå. Pandas organiserer dataene i en såkalt dataframe (dataramme), som er en tabell med kolonne- og radoverskrifter, ikke ulikt et regneark.
Før vi leser datafila inn i Python, kan vi kort se på den med et regnearkprogram. Bruk datafila du har lastet ned (ssbmedier.csv), eller last ned datafila nederst på denne siden. Åpne fila i et regneark. Datafila ser slik ut (ikke alle kolonner er tatt med):
Det er tre problemer med denne datafila:
- De to første radene må fjernes.
- Det mangler tall flere steder. På slike steder står det enten ett eller to punktum, avhengig av hvorfor det mangler tall (se forklaring på nettsida med tabellen).
- Kolonneoverskriftene er veldig lange. På bildet over har vi utvidet kolonne B slik at vi får med hele overskriften. Også de andre tallkolonnene har den samme lange overskriften. Vi, derimot, vil bare ha årstallene.
De to første problemene ordner vi under selve innlesingen. Det siste fikser vi etterpå.
Kode for innlesingen
Kopier koden nedenfor og lim den inn i programmeringseditoren du vanligvis bruker. Pass på at fila har samme navn i filstrukturen på pc-en som i programkoden. Kjør programmet. Får du utskrift av dataene? Du får ganske sikkert en dårlig lesbar utskrift, men dette kan du ordne senere.
Forklaring av koden
Først må vi importere modulen Pandas. Ved å importere den som "pd" slipper vi å skrive hele modulnavnet når vi skal referere til den.
Kommandoen vi bruker for å lese inn fila, er "read_csv()". Variabelen data
blir da en dataframe. Vi må sette inn mange såkalte attributter i kommandoen for at innlesingen skal gå smertefritt:
ssbmedier.csv
: Her skriver vi filnavnet (og eventuell adresse) på datafila som skal leses.index_col = 0
: (Attributtet "index_col" får verdien 0.) Her forteller vi Python at første kolonne skal være overskrifter.skiprows
= (0, 1)
: Dette betyr at de to første radene (rad nummer 0 og 1) i fila skal hoppes over. (Husk at Python begynner nummerering på null.)- Vi deler opp den lange kodelinja med tegnet
\
. Husk at neste linje må rykkes inn. sep = ";"
: Dersom vi ser på datafila med en enkel editor, som for eksempel Notisblokk i Windows, vil vi finne at alle dataene er atskilt fra hverandre med semikolon. Dette attributtet forteller programmet at semikolon betyr "nytt tall".na_
values
= [".", ".."]
: Her lister vi opp det som skal betraktes som manglende data eller "ikke-data". Akkurat i denne fila er manglende data symbolisert ved enten ett eller to punktum, men hvilke(t) tegn som brukes, kan variere fra fil til fil. Attributtetna_
values
sørger for at tegnet blir oversatt til "NaN", eller "Not_a_Number" i den interne datatabellen. Da skaper det ikke mer krøll under den videre behandlingen.encoding
= "latin-1"
: Dersom vi legger til dette attributtet, tar programmet høyde for at datafila inneholder skandinaviske bokstaver som æ, ø eller å. Dersom dette ikke fungerer, prøv verdien"utf-8"
.
Til slutt skriver vi ut innholdet av variabelen data
på vanlig måte med kommandoen print(data)
.
Nye kolonneoverskrifter
Dessverre blir utskriften dårlig lesbar på grunn av de lange kolonneoverskriftene ("Minutter brukt til ..."). Vi skal erstatte overskriftene med bare årstallene. Det gjør vi ved å lage ei liste med årstallene og rett og slett skrive inn de nye kolonneoverskriftene i variabelen data
. Siden vi har statistiske data for hvert år, kan vi bruke ei for-løkke til å generere lista, som vi her har kalt K
for kolonneoverskrift:
Kopier inn koden over rett før print()-kommandoen. Det kan hende at det blir med noe "rusk" under kopieringen; dette må i så fall fjernes i programmeringseditoren. I for-løkka blir det for hver runde lagt til et tall i lista K
som er 1 større enn det forrige. I programkoden har vi lagt til kommentarer ved hjelp av tegnet #
.
Får du en mer lesbar tabell nå, dersom du legger til koden over før du skriver ut innholdet av variabelen data
? Det kan hende at du bare får utskrift av tallene for de 3–4 første årene og for de 3–4 siste. Det er helt normalt. Nå er dataene klar for mer behandling!
Statistiske data med kommandoen describe()
Modulen Pandas har en egen kommando for å hente ut ulike statistiske mål i en dataframe. Vi skriver følgende:
Resultatet skal ligne på tabellen nedenfor, der vi bare har skrevet inn tallene for året 2010:
2010 | |
---|---|
count | 11.000000 |
mean | 44.727273 |
std | 48.203923 |
min | 1.000000 |
25% | 8.000000 |
50% | 23.000000 |
75% | 78.500000 |
max | 152.000000 |
Forklaring på dataene
- count
- tallet på observasjoner vi har i kolonnen
- mean
- gjennomsnittet av verdiene i kolonnen
- std
- standardavviket i kolonnen. Standardavviket forteller oss noe om hvor stor spredning det er i datamaterialet. Hvis standardavviket er stort, betyr det at vi har mange observasjoner som ligger langt unna gjennomsnittet. Hvis vi beveger oss ett helt standardavvik opp og ned fra gjennomsnittsverdien, skal vi ha cirka 2/3 av alle observasjonene i dette intervallet.
- min
- minimumsverdien i kolonnen
- 25%
- den nederste kvartilen. Dette tallet forteller oss at 25 prosent av observasjonene i kolonnen er lavere enn denne verdien.
- 50%
- medianen. Dette tallet forteller oss at 50 prosent av observasjonene i kolonnen er lavere enn denne verdien.
- 75%
- den øverste kvartilen. Dette tallet forteller oss at 75 prosent av observasjonene i kolonnen er lavere enn denne verdien (og at 25 prosent av observasjonene er høyere enn denne verdien).
- max
- maksimumsverdien i kolonnen
Grafisk framstilling av dataene
Modulen Pandas har sin egen plot()-kommando, som i sin tur bruker modulen Pyplot sin plot()-kommando (se teorisiden "Tegne grafer med Pyplot") til å lage framstillingen.
Vi ønsker å lage en framstilling der vi ser hvordan utviklingen har gått for de ulike medietypene. Det betyr at vi ønsker å ha årstallene på -aksen.
Vi skriver følgende for å lage et linjediagram av tallene i variabelen data
:
Da får vi følgende grafiske framstilling:
Tips om du ikke får fram den grafiske framstillingen
Dersom du bruker Jupyter Notebook:
Skriv
%matplotlib
inline
øverst i koden.
Dersom du bruker Spyder:
Grafiske framstillinger dukker opp i vinduet "Object", som ofte ligger over konsollvinduet til høyre ved standard oppsett i Spyder. Objektvinduet viser som standard hjelpeinformasjon, du må derfor velge "Plots" nederst i dette vinduet.
Generelt tips:
- Skriv
import matplotlib.pyplot as plt
øverst i koden. - Skriv
plt.show()
nederst i koden.
Spørsmål
Hva viser denne grafiske framstillingen?
Forklaring
Vi har fått en grafisk framstilling som viser hvordan brukstallene for de ulike mediene varierer innenfor det enkelte året. For eksempel starter året 2019 med tallet 9 for papiravis, fortsetter med tallet 78 for fjernsyn og så videre. (Vi kunne iallfall ha lest denne informasjonen ut av framstillingen om de enkelte medietypene hadde stått oppført langs
Vi ønsker oss uansett det motsatte, nemlig å se for eksempel at tallene for papiravis starter på 23 i 2010 og øker til 24 i 2011. Problemet er at årstall ikke ble oppfattet som den kategorien som skal være på
Framstillingen blir feil. Vi kan fikse dette ved å bytte om på rader og kolonner i variabelen data
før vi lager plottet. Dette gjør vi med kommandoen transpose, se linje 1 i koden nedenfor. I tillegg ønsker vi å unngå at forklaringen kommer oppå grafikkfeltet. Det fikser vi ved å legge til metoden "legend" til plot()-kommandoen og la attributtet "bbox_to_anchor" få verdien "(1, 1)", som er koordinatene til øvre høyre hjørne av plottet. Se linje 2.
Da får vi følgende figur:
Nå ble framstillingen riktig fordi vi kjørte kommandoen "transpose()" som transponerer tabellen ved å la radene bli kolonner. Forklaringen la seg dessuten pent på sida av grafikkfeltet.
Spørsmål
Hvorfor slutter grafen for hjemme-pc i året 2014, mens grafen for digitale spill starter i 2016?
Forklaring
Grafene er avkortet når det ikke er tall for årene før eller etter i tabellen. På den originale nettsiden til SSB er det brukt ett eller to punktum for å markere år uten tall.
Plotting av enkeltkolonner
Dersom vi ønsker å sammenlikne bruken av fjernsyn med bruken av internett, kan vi lage en ny dataframe som bare inneholder de kolonnene vi er interessert i. Først velger vi ut radene med fjernsyn og internett fra dataframe-variabelen data
, så legger vi dem i en ny dataframe, og til slutt transponerer vi denne. Vi skriver følgende:
Her lager vi en ny dataframe-variabel utdrag
som bare inneholder rad nummer 1 og 10 fra variabelen data
, ved hjelp av metoden iloc.
NB: Husk å fjerne tidligere kommandolinjer med "transpose()" fra programmet ditt når du setter inn linjene over.
Spørsmål
Hvorfor brukte vi tallene 1 og 10 i argumentet til metoden iloc?
Svar
Tallene for fjernsyn står i andre rad, og tallene for internett står i 11. rad. Siden radnummereringen begynner på 0, må vi bruke 1 og 10 i kommandoen for å få vist disse radene.
Spørsmål
Er det tilfeldig at tallene 1 og 10 er argumenter både i range-funksjonen i for-løkka og i kommandoen med iloc?
Svar
Ja. Hvis vi velger andre medietyper enn fjernsyn og internett, påvirker ikke dette for-løkka, men i iloc-kommandoen må vi sette inn nye tall.
Forbedring av den grafiske framstillingen
Vi kan forbedre den grafiske framstillingen ved hjelp av modulen Pyplot.
Spørsmål
Hva kan vi gjøre dersom vi vil forbedre den grafiske framstillingen av tallene for fjernsyn og internett? Hva mangler i figuren?
Forslag
- Det mangler aksetitler.
- Det kunne vært en tittel på diagrammet øverst.
- Statistisk sentralbyrå har gitt dataene sine til allmennheten, men på det vilkåret at de blir oppgitt som kilde. Det bør altså stå "Kilde: Statistisk sentralbyrå" ett eller annet sted på framstillingen.
- Det kunne ha vært rutenett, for da blir det lettere å lese verdier ut av diagrammet.
Oppgave
Kommandoene nedenfor endrer den grafiske framstillingen i samsvar med forslaget vårt. Skriv dem inn og observer hva som skjer. Prøv å forklare hva hver av de fire kommandoene gjør.
Skriv øverst i programkoden (om du ikke alt har gjort det):
Dette må du gjøre for å kunne bruke funksjonene i Pyplot i programmet. Skriv så nederst i programkoden:
Løsningsforslag
plt.x
label
lager tittel på x-aksen.plt.y
label
lager tittel på y-aksen.plt.
title
lager tittelen over diagrammet.plt.
suptitle
lager kildehenvisningen til Statistisk sentralbyrå og plasserer den over hovedtittelen. (Det er mulig du må justere fontstørrelsen til noe annet enn 8.)plt.
grid
slår på rutenett.
Det kan hende du må skrive plt.show()
for å få fram figuren.
Se også teorisiden "Tegne grafer med Pyplot" om du vil lese mer om forbedret framstilling av grafer.
Filer
Oppgave
Lag en tilsvarende grafisk framstilling der du sammenlikner to eller tre ulike medietyper som du kan tenke deg å studere nærmere.