Bakåtsnedstreck \ är escape-tecken i Python. \n = radbryt, \t = tab osv.
En Windows-sökväg som C:\Users\namn tolkas fel utan r"".
Lösning: lägg alltid r framför: r"C:\Users\namn\fil.xlsx"
Python använder indragning (4 mellanslag) istället för måsvingar {}.
Fel indragning = programmet kraschar. Det är inte bara estetik.
def min_funktion():
x = 1 # inuti funktionen
if x > 0:
print(x) # inuti if-satsen
Ingen deklaration behövs. Python räknar ut typen själv.
x = 5 # int
x = "hej" # nu är x en sträng – helt OK
x = 3.14 # nu är x ett flyttal
Risk: om en kolumn innehåller text när du förväntar dig siffror får du ett fel först vid körning.
"hej världen".upper() # → "HEJ VÄRLDEN"
[3, 1, 2].sort() # sorterar listan
df["kolumn"].mean() # medelvärde på en Pandas-kolumn
Sista raden är felet. Raden ovanför är var i koden det hände.
File "garmin_export.py", line 86, in extrahera_puls
merged = pd.merge_asof(...)
ValueError: Merge keys contain null values on left side
→ Rad 86, funktionen extrahera_puls, null-värden i merge-nyckeln.
| Power Query | Pandas |
|---|---|
| Filtrera rader | df[df["kolumn"] > 5] |
| Lägg till kolumn | df["ny"] = df["a"] + df["b"] |
| Gruppera + summera | df.groupby("datum")["värde"].sum() |
| Slå ihop tabeller | pd.merge(df1, df2, on="datum") |
| Sortera | df.sort_values("datum") |
| Ta bort dubbletter | df.drop_duplicates(subset=["tid"]) |
# Filtrera bort felaktiga värden
df = df[df["puls_bpm"] > 30]
# Konvertera text till datetime
df["lokal_tid"] = pd.to_datetime(df["lokal_tid"])
# Beräkna timme från datetime
df["timme"] = df["lokal_tid"].dt.hour
# Rullande medelvärde (30 min)
df["puls_rull"] = df.set_index("lokal_tid")["puls_bpm"].rolling("30min").mean()
# Resampla till 5-minutersintervall
df = df.set_index("lokal_tid").resample("5min").mean()
NaN = Not a Number, Pandas sätt att representera saknad data.
pd.isna(värde) # True om NaN
df.dropna(subset=["kolumn"]) # ta bort rader där kolumnen är NaN
df.fillna(0) # ersätt NaN med 0
| Bibliotek | Används till |
|---|---|
pandas |
Tabellhantering, tidsserier |
openpyxl |
Läsa/skriva Excel-filer |
fitparse |
Läsa Garmins FIT-filer |
requests |
Hämta data från API (SMHI pollen) |
datetime |
Datum- och tidsberäkningar |
import pandas as pd # pd är standard-alias
import numpy as np # np är standard-alias
from datetime import datetime, timedelta
from fitparse import FitFile
from datetime import datetime, timedelta
datum = "2026-04-09" # uppvakningsdatum
somnade = "22:45" # kvällen innan
steg_upp = "07:15" # morgonen
ins = datetime.strptime(f"{datum} {somnade}", "%Y-%m-%d %H:%M") - timedelta(days=1)
upp = datetime.strptime(f"{datum} {steg_upp}", "%Y-%m-%d %H:%M")
langd_h = (upp - ins).total_seconds() / 3600
# → 8.5 timmar
Om insomning är efter midnatt (< 03:00) subtraheras inte en dag.
Starta ny chatt per delområde En chatt per tydligt avgränsat ämne: Garmin-pipeline, Excel-formulär, Supabase-uppladdning, HTML-dashboard. Kortare chattar = lägre kostnad.
Beskriv fel i text istället för att ladda upp filen "Rad 86 i garmin_export.py ger ValueError: merge keys contain null" räcker ofta för att Claude ska kunna fixa det.
Ladda upp bara relevant data En flik från Excel istället för hela arbetsboken. Felmeddelandet som skärmdump istället för hela loggen.
Klistra in kontextfilen i början av nya chattar
Använd bsl_kontext.md – klistra in relevanta sektioner.
Exempel på chattstart:
"BSL-projekt, kontext nedan. Idag ska vi bygga uppladdningsskriptet till Supabase. [klistra in relevanta delar av bsl_kontext.md]"
Bilder är billigare än man tror En skärmdump av ett felmeddelande är ofta mer effektivt än att skriva ut det.
Claude kan spara fakta mellan chattar. Be Claude spara stabila fakta:
"Kom ihåg att BSL-projektet använder uppvakningsdatum och klockslag som HH:MM-text"
Passar för: personlig kontext, projektbeslut, tekniska konventioner. Passar inte för: kod som förändras, temporär data.
| Vad | Format | Varför |
|---|---|---|
| Klockslag | Text HH:MM |
Undviker Excels interna decimalformat |
| Datum | YYYY-MM-DD |
ISO-standard, sorterar rätt, fungerar direkt i Python |
| Sömnlängd | Decimal 7.5 |
Enkel att beräkna med, 7.5 = 7h30min |
| Sökvägar | r"C:\Users\..." |
Undviker escape-tolkningar |
| Sömnens datum | Uppvakningsdatum | Matchar Garmin Connect, naturlig inmatning på morgonen |
timestamp_16 = sekunder från intern Garmin-epoch (varierar per fil, inte UTC/lokal midnatt)monitoring-rad med känt UTC-timestamplocal_timestamp = lokal tid (UTC + offset), används för ankardatumstress_level_value = inverterad HRV (hög stress = låg HRV)