Tilbake
3.5
Algoritmisk problemløsning i praksis

3.5 Algoritmisk problemløsning i praksis

Problemdekomponering, grådige algoritmer og backtracking.

60 min
6 oppgaver
ProblemløsningGrådige algoritmerBacktracking
Du leser den tradisjonelle versjonen
Din fremgang i kapitlet
0 / 6 oppgaver

Databehandling og filhåndtering

I den virkelige verden ligger data sjelden ferdig i en Python-liste. Data lagres i filer, databaser og på nettet. For å bruke disse dataene må du kunne lese dem inn, behandle dem og ofte lagre resultatene tilbake.

I dette kapittelet skal du lære:
- Lese og skrive tekstfiler i Python
- Jobbe med CSV-filer (kommaseparerte verdier)
- Lese og skrive JSON-data
- Grunnleggende datarensing
- Introduksjon til pandas for dataanalyse

Disse ferdighetene er essensielle for alle som jobber med data, enten det er vitenskapelig forskning, webutvikling eller dataanalyse.

Filhåndtering: Prosessen med å lese fra og skrive til filer på datamaskinen.

Grunnleggende konsepter:

Åpne en fil:

fil = open("filnavn.txt", modus)

Moduser:

ModusBeskrivelse
"r"Lese (read) - standard
"w"Skrive (write) - overskriver filen
"a"Legge til (append) - legger til på slutten
"x"Opprett ny fil - feil hvis filen finnes

Viktig: Bruk with-blokk!
# Anbefalt: with lukker filen automatisk
with open("data.txt", "r") as fil:
    innhold = fil.read()
# Filen er nå lukket automatisk

# IKKE anbefalt: Må huske å lukke selv
fil = open("data.txt", "r")
innhold = fil.read()
fil.close()  # Lett å glemme!
Tegnsett (encoding):
For norske tegn (æ, ø, å), bruk UTF-8:
with open("norsk.txt", "r", encoding="utf-8") as fil:
    innhold = fil.read()
Skrive til fil:

# Skrive tekst til fil
with open("dagbok.txt", "w", encoding="utf-8") as fil:
    fil.write("Dag 1: Lærte om filhåndtering\n")
    fil.write("Dag 2: Lærte om CSV-filer\n")
    fil.write("Dag 3: Lærte om JSON\n")

# Legge til mer tekst
with open("dagbok.txt", "a", encoding="utf-8") as fil:
    fil.write("Dag 4: Lærte om pandas\n")

Lese fra fil:

# Les hele filen som én streng
with open("dagbok.txt", "r", encoding="utf-8") as fil:
    innhold = fil.read()
    print(innhold)

# Les linje for linje
with open("dagbok.txt", "r", encoding="utf-8") as fil:
    for linje in fil:
        print(linje.strip())  # strip() fjerner \n

# Les alle linjer til en liste
with open("dagbok.txt", "r", encoding="utf-8") as fil:
    linjer = fil.readlines()
    print(linjer)
    # ['Dag 1: ...\n', 'Dag 2: ...\n', ...]

Praktisk eksempel: Behandle en loggfil

def analyser_logg(filnavn):
    """Analyserer en loggfil og teller feilmeldinger"""
    feil_teller = 0
    advarsel_teller = 0

    with open(filnavn, "r", encoding="utf-8") as fil:
        for linje in fil:
            if "ERROR" in linje:
                feil_teller += 1
            elif "WARNING" in linje:
                advarsel_teller += 1

    print(f"Feil: {feil_teller}")
    print(f"Advarsler: {advarsel_teller}")

# Lagre rapport
def lagre_rapport(filnavn, data):
    """Lagrer en rapport til fil"""
    with open(filnavn, "w", encoding="utf-8") as fil:
        fil.write("=== Rapport ===\n\n")
        for nøkkel, verdi in data.items():
            fil.write(f"{nøkkel}: {verdi}\n")
    print(f"Rapport lagret til {filnavn}")

rapport = {"Antall brukere": 150, "Aktive i dag": 42, "Nye i uka": 12}
lagre_rapport("rapport.txt", rapport)

Hva skriver denne koden til filen "tall.txt"?

with open("tall.txt", "w") as fil:
    for i in range(1, 4):
        fil.write(str(i * 10) + "\n")

with open("tall.txt", "a") as fil:
    fil.write("Ferdig!")

CSV: Et tekstbasert filformat der data er organisert i rader og kolonner, separert med komma (eller semikolon).

Eksempel på CSV-fil (elever.csv):

navn,alder,karakter
Anna,17,5
Bob,18,4
Charlie,17,6

Hvorfor CSV?
- Enkelt og lesbart format
- Kan åpnes i Excel, Google Sheets, etc.
- Lett å eksportere fra databaser
- Standard format for datautveksling

Pythons csv-modul:

import csv

Viktige funksjoner:
- csv.reader() - Leser CSV som lister
- csv.DictReader() - Leser CSV som ordbøker
- csv.writer() - Skriver lister til CSV
- csv.DictWriter() - Skriver ordbøker til CSV

Vanlige problemer:
- Norske filer bruker ofte semikolon (;) som separator
- Tegnsett: Bruk UTF-8 for norske tegn
- Desimaltall: Norsk format bruker komma (3,14) vs punkt (3.14)

Lese CSV med csv.reader:

import csv

with open("elever.csv", "r", encoding="utf-8") as fil:
    leser = csv.reader(fil)
    overskrift = next(leser)  # Hopp over overskriftsraden
    print(f"Kolonner: {overskrift}")

    for rad in leser:
        navn, alder, karakter = rad
        print(f"{navn} er {alder} år og har karakter {karakter}")

Lese CSV med DictReader (anbefalt):

import csv

with open("elever.csv", "r", encoding="utf-8") as fil:
    leser = csv.DictReader(fil)

    for elev in leser:
        print(f"{elev['navn']}: karakter {elev['karakter']}")

DictReader bruker første rad som nøkler, så du kan referere til kolonner med navn.

Skrive CSV:

import csv

elever = [
    {"navn": "Diana", "alder": 18, "karakter": 5},
    {"navn": "Erik", "alder": 17, "karakter": 4},
    {"navn": "Fiona", "alder": 18, "karakter": 6}
]

with open("nye_elever.csv", "w", encoding="utf-8", newline="") as fil:
    felter = ["navn", "alder", "karakter"]
    skriver = csv.DictWriter(fil, fieldnames=felter)

    skriver.writeheader()  # Skriv overskriftsrad
    for elev in elever:
        skriver.writerow(elev)

Norsk CSV med semikolon:

import csv

# Les norsk CSV med semikolon
with open("norsk_data.csv", "r", encoding="utf-8") as fil:
    leser = csv.reader(fil, delimiter=";")
    for rad in leser:
        print(rad)

Praktisk eksempel: Beregne gjennomsnitt fra CSV

import csv

def beregn_snitt(filnavn, kolonne):
    """Beregner gjennomsnittet av en numerisk kolonne i CSV"""
    verdier = []

    with open(filnavn, "r", encoding="utf-8") as fil:
        leser = csv.DictReader(fil)
        for rad in leser:
            verdier.append(float(rad[kolonne]))

    snitt = sum(verdier) / len(verdier)
    return round(snitt, 2)

snitt_karakter = beregn_snitt("elever.csv", "karakter")
print(f"Gjennomsnittskarakter: {snitt_karakter}")

Du har en CSV-fil "temperaturer.csv" med dette innholdet:

by,temperatur
Oslo,5.2
Bergen,8.1
Tromsø,-3.4
Trondheim,4.7

Skriv kode som leser filen og finner byen med høyest temperatur.

JSON: Et tekstbasert format for å lagre og utveksle strukturerte data. Brukes mye i web-APIer og konfigurasjoner.

JSON-format:

{
    "navn": "Anna",
    "alder": 17,
    "fag": ["matte", "norsk", "engelsk"],
    "aktiv": true,
    "adresse": {
        "gate": "Storgata 1",
        "by": "Oslo"
    }
}

JSON vs Python:

JSONPython
object {}dict
array []list
string ""str
numberint/float
true/falseTrue/False
nullNone

Pythons json-modul:
import json
Viktige funksjoner:
- json.load(fil) - Les JSON fra fil
- json.loads(streng) - Les JSON fra streng
- json.dump(data, fil) - Skriv JSON til fil
- json.dumps(data) - Konverter til JSON-streng

Fordeler med JSON:
- Lesbart for mennesker

- Støtter nestede strukturer
- Standard format for web-APIer
- Støttes av nesten alle programmeringsspråk

Skrive JSON til fil:

import json

elever = [
    {
        "navn": "Anna",
        "alder": 17,
        "fag": ["matte", "norsk", "IT"],
        "karakterer": {"matte": 5, "norsk": 4, "IT": 6}
    },
    {
        "navn": "Bob",
        "alder": 18,
        "fag": ["matte", "engelsk"],
        "karakterer": {"matte": 4, "engelsk": 5}
    }
]

# Skriv til fil
with open("elever.json", "w", encoding="utf-8") as fil:
    json.dump(elever, fil, indent=2, ensure_ascii=False)
    # indent=2 gjør filen lesbar
    # ensure_ascii=False bevarer norske tegn

Lese JSON fra fil:

import json

with open("elever.json", "r", encoding="utf-8") as fil:
    elever = json.load(fil)

for elev in elever:
    print(f"{elev['navn']} tar {len(elev['fag'])} fag")
    for fag, karakter in elev['karakterer'].items():
        print(f"  {fag}: {karakter}")

JSON fra streng (f.eks. fra web-API):

import json

json_streng = '{"by": "Oslo", "temperatur": 5.2, "nedbør": true}'
data = json.loads(json_streng)
print(data["by"])          # Oslo
print(data["temperatur"])  # 5.2

# Tilbake til streng
ny_streng = json.dumps(data, ensure_ascii=False)
print(ny_streng)

Praktisk eksempel: Konfigurasjonsfil

import json

def les_konfig(filnavn="config.json"):
    """Leser konfigurasjon fra JSON-fil"""
    try:
        with open(filnavn, "r", encoding="utf-8") as fil:
            return json.load(fil)
    except FileNotFoundError:
        # Returner standardverdier
        return {"tema": "lys", "språk": "nb", "font_størrelse": 14}

def lagre_konfig(konfig, filnavn="config.json"):
    """Lagrer konfigurasjon til JSON-fil"""
    with open(filnavn, "w", encoding="utf-8") as fil:
        json.dump(konfig, fil, indent=2, ensure_ascii=False)

# Bruk
konfig = les_konfig()
konfig["tema"] = "mørk"
lagre_konfig(konfig)

Hvilken påstand om CSV og JSON er riktig?

Datarensing: Prosessen med å oppdage og korrigere feil, mangler og inkonsistenser i data.

Vanlige problemer i reelle data:

ProblemEksempelLøsning
Manglende verdiertom celle, "N/A"Fjerne rad eller fylle inn
Feil datatype"atten" i stedet for 18Konvertere eller fjerne
DuplikaterSamme rad to gangerFjerne duplikater
Inkonsistent format"Oslo", "oslo", "OSLO"Standardisere
Whitespace" Oslo "strip()
UteliggereAlder: 999Vurdere og eventuelt fjerne

Steg i datarensing:
1. Inspiser: Se på dataene, finn problemer
2. Valider: Sjekk datatyper, verdier og formater
3. Rens: Fiks problemer systematisk
4. Verifiser: Sjekk at rensingen var vellykket
Tommelregel: Du bruker ofte 80% av tiden på datarensing og bare 20% på selve analysen!

La oss rense et datasett med elever som har diverse problemer:

import csv

def les_og_rens(filnavn):
    """Leser CSV og renser dataene"""
    renset_data = []
    forkastet = 0

    with open(filnavn, "r", encoding="utf-8") as fil:
        leser = csv.DictReader(fil)

        for rad in leser:
            # 1. Fjern whitespace fra alle verdier
            renset = {k: v.strip() for k, v in rad.items()}

            # 2. Standardiser navn (stor forbokstav)
            renset["navn"] = renset["navn"].title()

            # 3. Sjekk manglende verdier
            if not renset["navn"] or not renset["alder"]:
                forkastet += 1
                continue

            # 4. Konverter og valider alder
            try:
                alder = int(renset["alder"])
                if alder < 15 or alder > 20:
                    forkastet += 1
                    continue
                renset["alder"] = alder
            except ValueError:
                forkastet += 1
                continue

            # 5. Konverter og valider karakter
            try:
                karakter = int(renset["karakter"])
                if karakter < 1 or karakter > 6:
                    forkastet += 1
                    continue
                renset["karakter"] = karakter
            except ValueError:
                renset["karakter"] = None  # Manglende karakter OK

            renset_data.append(renset)

    print(f"Beholdt {len(renset_data)} rader, forkastet {forkastet}")
    return renset_data

# Fjerne duplikater
def fjern_duplikater(data, nøkkel="navn"):
    """Fjerner duplikater basert på en nøkkel"""
    sett = set()
    unik = []
    for rad in data:
        if rad[nøkkel] not in sett:
            sett.add(rad[nøkkel])
            unik.append(rad)
    return unik

Vanlige rensefunksjoner:

# Standardisere tekst
def rens_tekst(tekst):
    """Renser og standardiserer tekst"""
    tekst = tekst.strip()       # Fjern whitespace
    tekst = tekst.lower()       # Til lowercase
    tekst = " ".join(tekst.split())  # Fjern ekstra mellomrom
    return tekst

# Håndtere manglende verdier
def fyll_manglende(data, kolonne, standardverdi):
    """Fyller inn manglende verdier"""
    for rad in data:
        if rad[kolonne] is None or rad[kolonne] == "":
            rad[kolonne] = standardverdi
    return data

# Konvertere datoformat
def standardiser_dato(dato_tekst):
    """Konverterer ulike datoformater til standard"""
    from datetime import datetime
    formater = ["%d.%m.%Y", "%d/%m/%Y", "%Y-%m-%d"]
    for fmt in formater:
        try:
            return datetime.strptime(dato_tekst, fmt).strftime("%Y-%m-%d")
        except ValueError:
            continue
    return None

Du har denne listen med data:

data = [
    {"navn": "  Anna ", "alder": "17", "karakter": "5"},
    {"navn": "bob", "alder": "atten", "karakter": "4"},
    {"navn": "Charlie", "alder": "18", "karakter": ""},
    {"navn": "Anna", "alder": "17", "karakter": "5"},
    {"navn": "Diana", "alder": "200", "karakter": "3"}
]

Hvilke rader bør forkastes og hvorfor?

pandas: Et kraftig Python-bibliotek for dataanalyse og manipulasjon. Det er standard verktøyet for å jobbe med strukturerte data i Python.

Hovedkonsepter:

DataFrame: En tabell med rader og kolonner (som et regneark)

import pandas as pd

df = pd.DataFrame({
    "navn": ["Anna", "Bob", "Charlie"],
    "alder": [17, 18, 17],
    "karakter": [5, 4, 6]
})

Series: En enkelt kolonne (som en liste med indeks)

alder = df["alder"]  # Series

Hvorfor pandas?
- Raskere enn løkker for store datasett
- Innebygde funksjoner for datarensing
- Enkel fillesing (CSV, JSON, Excel, etc.)
- Kraftig filtrering og gruppering
- Statistiske funksjoner innebygd

Installasjon:

pip install pandas

Import-konvensjon:

import pandas as pd
Lese data:

import pandas as pd

# Les fra CSV
df = pd.read_csv("elever.csv", encoding="utf-8")

# Les fra JSON
df = pd.read_json("elever.json", encoding="utf-8")

# Les norsk CSV med semikolon
df = pd.read_csv("norsk_data.csv", sep=";", encoding="utf-8")

Inspeksjon av data:

import pandas as pd

df = pd.read_csv("elever.csv")

print(df.head())         # Første 5 rader
print(df.info())         # Kolonnetyper og manglende verdier
print(df.describe())     # Statistikk for numeriske kolonner
print(df.shape)          # (antall_rader, antall_kolonner)
print(df.columns.tolist()) # Kolonnenavn

Velge data:

# Velg kolonne
navn = df["navn"]

# Velg flere kolonner
utvalg = df[["navn", "karakter"]]

# Filtrere rader
voksne = df[df["alder"] >= 18]
flinke = df[df["karakter"] >= 5]

# Kombinert filter
flinke_voksne = df[(df["alder"] >= 18) & (df["karakter"] >= 5)]

Beregninger:

# Statistikk
print(df["karakter"].mean())     # Gjennomsnitt
print(df["karakter"].median())   # Median
print(df["karakter"].max())      # Maks
print(df["karakter"].min())      # Min
print(df["karakter"].std())      # Standardavvik

# Gruppering
per_alder = df.groupby("alder")["karakter"].mean()
print(per_alder)

Datarensing med pandas:

# Fjern rader med manglende verdier
df_ren = df.dropna()

# Fyll inn manglende verdier
df["karakter"] = df["karakter"].fillna(df["karakter"].mean())

# Fjern duplikater
df_unik = df.drop_duplicates()

# Endre datatype
df["alder"] = df["alder"].astype(int)

# Standardiser tekst
df["navn"] = df["navn"].str.strip().str.title()

Lagre resultat:

df.to_csv("resultat.csv", index=False, encoding="utf-8")
df.to_json("resultat.json", orient="records", force_ascii=False)

Gitt denne DataFrame:

import pandas as pd

df = pd.DataFrame({
    "navn": ["Anna", "Bob", "Charlie", "Diana", "Erik"],
    "fag": ["matte", "norsk", "matte", "norsk", "matte"],
    "karakter": [5, 4, 6, 5, 3]
})

Hva gir df.groupby("fag")["karakter"].mean()?

Oppsummering

Filhåndtering:
- Bruk alltid with open(...) as fil: for automatisk lukking
- Moduser: "r" (les), "w" (skriv), "a" (legg til)
- Bruk encoding="utf-8" for norske tegn

CSV-filer:
- Tabellformat med rader og kolonner
- Bruk csv.DictReader() for enkel lesing
- Bruk csv.DictWriter() for skriving
- Husk delimiter=";" for norske filer

JSON:
- Støtter nestede strukturer (objekter og lister)
- json.load() / json.dump() for filer
- json.loads() / json.dumps() for strenger
- Bruk indent=2 for lesbarhet

Datarensing:
- Fjern whitespace: strip()
- Standardiser: lower(), title()
- Valider datatyper: try/except med int(), float()
- Håndter manglende verdier
- Fjern duplikater

pandas:
- pd.read_csv() / pd.read_json() for innlesing
- df.head(), df.info(), df.describe() for inspeksjon
- Filtrering: df[df["kolonne"] > verdi]
- Gruppering: df.groupby("kolonne").mean()
- Rensing: dropna(), fillna(), drop_duplicates()

Filformat-sammenligning:

FormatStrukturBruksområdeLesbarhet
TXTUstrukturertLogger, notaterGod
CSVFlat tabellRegneark, enkel dataGod
JSONNestede objekterAPIer, konfigurasjonGod

Samleoppgaver

Oppgaver som kombinerer filhåndtering, datarensing og analyse:

Du har en CSV-fil "salg.csv" med disse kolonnene: produkt, antall, pris, dato.

Beskriv stegene for en komplett databehandlingspipeline som:
1. Leser inn dataene
2. Renser dataene (håndterer manglende verdier og feil)
3. Beregner total omsetning per produkt
4. Lagrer resultatet som JSON

For hvert scenario, velg riktig filformat (TXT, CSV eller JSON) og begrunn valget:

A) Lagre en liste med 1000 temperaturer med tidspunkt og sted
B) Lagre brukerinnstillinger for en app (tema, språk, varsler, favoritter)
C) Lagre en loggfil med hendelser som skjer i et program
D) Eksportere data fra en database som skal åpnes i Excel

Dette kapitlet er skrevet av Anthropics toppmodeller (Claude Opus og Claude Fable) og er foreløpig ikke manuelt gjennomgått — kvalitetskontrollen gjøres av uavhengige KI-agenter, og innmeldte feil rettes fortløpende. Funnet en feil? Meld fra, så retter vi den. Les mer om hvordan innholdet lages.