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 filhandtering

I den verkelege verda ligg data sjeldan ferdig i ei Python-liste. Data blir lagra i filer, databasar og på nettet. For å bruke desse dataene må du kunne lese dei inn, behandle dei og ofte lagre resultata tilbake.

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

Desse ferdigheitene er essensielle for alle som jobbar med data, anten det er vitskapleg forsking, webutvikling eller dataanalyse.

Filhandtering: Prosessen med å lese frå og skrive til filer på datamaskina.

Grunnleggjande konsept:

Opne ei fil:

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

Modusar:

ModusSkildring
"r"Lese (read) - standard
"w"Skrive (write) - overskriv fila
"a"Leggje til (append) - legg til på slutten
"x"Opprett ny fil - feil viss fila finst

Viktig: Bruk with-blokk!
# Anbefalt: with lukkar fila 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!
Teiknsett (encoding):
For norske teikn (æ, ø, å), 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 frå 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 ei 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)

Kva skriv denne koden til fila "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: Eit tekstbasert filformat der data er organisert i rader og kolonnar, separert med komma (eller semikolon).

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

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

Kvifor CSV?
- Enkelt og lesbart format
- Kan opnast i Excel, Google Sheets, etc.
- Lett å eksportere frå databasar
- Standard format for datautveksling

Pythons csv-modul:

import csv

Viktige funksjonar:
- csv.reader() - Les CSV som lister
- csv.DictReader() - Les CSV som ordbøker
- csv.writer() - Skriv lister til CSV
- csv.DictWriter() - Skriv ordbøker til CSV

Vanlege problem:
- Norske filer bruker ofte semikolon (;) som separator
- Teiknsett: Bruk UTF-8 for norske teikn
- Desimaltal: 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øklar, så du kan referere til kolonnar med namn.

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: Berekne gjennomsnitt frå 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 ei CSV-fil "temperaturer.csv" med dette innhaldet:

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

Skriv kode som les fila og finn byen med høgast temperatur.

JSON: Eit tekstbasert format for å lagre og utveksle strukturerte data. Blir brukt mykje i web-APIar og konfigurasjonar.

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 funksjonar:
- json.load(fil) - Les JSON frå fil
- json.loads(streng) - Les JSON frå streng
- json.dump(data, fil) - Skriv JSON til fil
- json.dumps(data) - Konverter til JSON-streng

Fordelar med JSON:
- Lesbart for menneske

- Støttar nesta strukturar
- Standard format for web-APIar
- Blir støtta 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 frå 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 frå streng (f.eks. frå 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)

Kva for ein påstand om CSV og JSON er riktig?

Datareinsking: Prosessen med å oppdage og korrigere feil, manglar og inkonsistensar i data.

Vanlege problem i reelle data:

ProblemEksempelLøysing
Manglande verdiartom celle, "N/A"Fjerne rad eller fylle inn
Feil datatype"atten" i staden for 18Konvertere eller fjerne
DuplikatSame rad to gongerFjerne duplikat
Inkonsistent format"Oslo", "oslo", "OSLO"Standardisere
Whitespace" Oslo "strip()
UteliggjararAlder: 999Vurdere og eventuelt fjerne

Steg i datareinsking:
1. Inspiser: Sjå på dataene, finn problem
2. Valider: Sjekk datatypar, verdiar og format
3. Reins: Fiks problem systematisk
4. Verifiser: Sjekk at reinskinga var vellukka
Tommelregel: Du bruker ofte 80% av tida på datareinsking og berre 20% på sjølve analysen!

Lat oss reinske eit datasett med elevar som har diverse problem:

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

Vanlege reinskefunksjonar:

# 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 lista 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"}
]

Kva for rader bør forkastast og kvifor?

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

Hovudkonsept:

DataFrame: Ein tabell med rader og kolonnar (som eit rekneark)

import pandas as pd

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

Series: Ein enkelt kolonne (som ei liste med indeks)

alder = df["alder"]  # Series

Kvifor pandas?
- Raskare enn løkker for store datasett
- Innebygde funksjonar for datareinsking
- Enkel fillesing (CSV, JSON, Excel, etc.)
- Kraftig filtrering og gruppering
- Statistiske funksjonar 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

Velje 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)]

Berekningar:

# 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)

Datareinsking 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]
})

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

Oppsummering

Filhandtering:
- Bruk alltid with open(...) as fil: for automatisk lukking
- Modusar: "r" (les), "w" (skriv), "a" (legg til)
- Bruk encoding="utf-8" for norske teikn

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

JSON:
- Støttar nesta strukturar (objekt og lister)
- json.load() / json.dump() for filer
- json.loads() / json.dumps() for strengar
- Bruk indent=2 for lesbarheit

Datareinsking:
- Fjern whitespace: strip()
- Standardiser: lower(), title()
- Valider datatypar: try/except med int(), float()
- Handter manglande verdiar
- Fjern duplikat

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()
- Reinsking: dropna(), fillna(), drop_duplicates()

Filformat-samanlikning:

FormatStrukturBruksområdeLesbarheit
TXTUstrukturertLoggar, notatGod
CSVFlat tabellRekneark, enkel dataGod
JSONNesta objektAPIar, konfigurasjonGod

Samleoppgåver

Oppgåver som kombinerer filhandtering, datareinsking og analyse:

Du har ei CSV-fil "salg.csv" med desse kolonnane: produkt, antal, pris, dato.

Skildre stega for ein komplett databehandlingspipeline som:
1. Les inn dataene
2. Reinskar dataene (handterer manglande verdiar og feil)
3. Bereknar total omsetnad per produkt
4. Lagrar resultatet som JSON

For kvart scenario, vel riktig filformat (TXT, CSV eller JSON) og grunngi valet:

A) Lagre ei liste med 1000 temperaturar med tidspunkt og stad
B) Lagre brukarinnstillingar for ein app (tema, språk, varsel, favorittar)
C) Lagre ei loggfil med hendingar som skjer i eit program
D) Eksportere data frå ein database som skal opnast 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.