Lese og rydde kjemiske data#
Læringsutbytte
Etter å ha arbeidet med dette temaet, skal du kunne:
forklare hvordan data er organisert i en CSV-fil
lese datafiler med Pandas
undersøke kolonner, datatyper og manglende verdier
filtrere, sortere og gruppere kjemiske data
opprette nye kolonner uten å overskrive rådataene
dokumentere og begrunne valg som tas under datarydding
Data er overalt, men data er ikke automatisk kunnskap. Før vi kan trekke en kjemisk konklusjon, må vi vite hva målingene representerer, hvilke enheter som er brukt, og om datasettet inneholder manglende eller ugyldige verdier.
I dette kapitlet følger vi et UV–Vis-forsøk. Datasettet inneholder blankprøver, kalibreringsstandarder og replikatmålinger av en ukjent prøve. Seinere skal vi bruke standardene til å lage en kalibreringsmodell og bestemme konsentrasjonen i den ukjente prøven. Først må vi lese og undersøke rådataene.
Datafiler#
Vi ønsker ofte å oppbevare og overføre data som råtekst fordi formatet er robust og kan leses av mange programmer. En Word-fil er ikke råtekst, fordi den også inneholder informasjon om blant annet skrifttyper, farger og formatering. .txt- og .csv-filer er vanlige råtekstformater.
Datafil
En datafil lagrer observasjoner i en fast struktur slik at de kan leses og behandles av et program. I en tabulær datafil er hver rad vanligvis én observasjon, mens kolonnene beskriver ulike variabler.
CSV står for comma-separated values. Hver linje representerer vanligvis én observasjon, mens verdiene på linja er skilt med komma:
sample_id,sample_type,concentration_uM,replicate,absorbance
blank_1,blank,0,1,0.010
blank_2,blank,0,2,0.011
std_2_1,standard,2,1,0.171
std_2_2,standard,2,2,0.169
Den første linja inneholder kolonnenavn. Hver av de neste linjene beskriver én måling. Dette kalles ofte et langt eller ryddig dataformat: Hver rad er en observasjon, hver kolonne er en variabel og hver celle inneholder én verdi.
Enheter i data
Enhetene bør være tydelige, men selve måleverdiene bør lagres som tall. Her er enheten lagt inn i kolonnenavnet concentration_uM. Et annet alternativ er å lagre enheter i egne metadata. Verdier som "2 µmol/L" blir tekst og er vanskeligere å regne med.
Lese data med Pandas#
Pandas er et mye brukt bibliotek for behandling av tabulære data. Når vi leser ei fil med read_csv, får vi en dataramme (DataFrame).
Dataramme
En dataramme er en todimensjonal datastruktur med navngitte kolonner og rader. Den kan sammenliknes med en tabell, men kolonnene kan behandles direkte med kode.
import pandas as pd
raw_data = pd.read_csv("data/uvvis_raw.csv")
print(raw_data)
Filbanen data/uvvis_raw.csv betyr at fila ligger i mappa data, som igjen ligger i samme mappe som notebooken eller programmet. Dersom fila ligger et annet sted, må filbanen endres.
Noen filer bruker semikolon som skilletegn og komma som desimalskilletegn. Da kan vi spesifisere dette:
data = pd.read_csv("data/example_semicolon.csv", sep=";", decimal=",")
Det er bedre å beskrive formatet eksplisitt enn å åpne fila manuelt og erstatte tegn uten å dokumentere det.
Undersøke datasettet#
Før vi analyserer dataene, bør vi undersøke hva vi faktisk har lest:
import pandas as pd
raw_data = pd.read_csv("data/uvvis_raw.csv")
print(raw_data.head())
print(raw_data.tail())
print(raw_data.shape)
print(raw_data.columns)
print(raw_data.dtypes)
head()viser de fem første radene.tail()viser de fem siste.shapegir antall rader og kolonner.columnsviser kolonnenavnene.dtypesviser hvilken datatype Pandas har gitt hver kolonne.
Metoden info() gir en samlet oversikt:
raw_data.info()
Tekstkolonner får ofte datatypen object eller string, heltall får int64, og desimaltall får float64. En kolonne som burde være numerisk, men som har datatypen object, kan inneholde tekst, feil desimalskilletegn eller symboler som ikke kan tolkes som tall.
Du kan undersøke et lite UV–Vis-datasett i editoren nedenfor. Datasettet er lagt direkte inn i programmet slik at eksempelet fungerer i nettleseren.
Underveisoppgave
Hvor mange rader og kolonner har datasettet?
Hvilke kolonner inneholder tekst, og hvilke inneholder tall?
Hvorfor er det manglende verdier i
concentration_uMfor den ukjente prøven?Hvor finnes den andre manglende verdien?
Løsningsforslag
Konsentrasjonen mangler for den ukjente prøven fordi dette er størrelsen vi seinere skal bestemme. Det er derfor ikke nødvendigvis en feil. Den manglende absorbansen er derimot en manglende måling og må undersøkes før analysen fortsetter.
Bevar rådataene#
Rådata bør normalt ikke overskrives. Dersom vi endrer verdier direkte i raw_data, kan det bli vanskelig å rekonstruere hva instrumentet faktisk registrerte. Vi lager derfor en kopi som kan bearbeides:
clean_data = raw_data.copy()
Dette gir en enkel arbeidsflyt:
raw_datainneholder dataene slik de ble lest.clean_datainneholder dokumenterte endringer.Analysen utføres på den bearbeidede kopien.
I et større prosjekt bør også selve rådatafila være skrivebeskyttet eller oppbevares separat. Koden fungerer da som en sporbar beskrivelse av hvordan rådata ble behandlet.
Manglende verdier#
Pandas representerer ofte en manglende verdi som NaN, som står for not a number. Vi kan telle manglende verdier slik:
print(raw_data.isna().sum())
Vi kan vise alle radene som mangler absorbans:
missing_absorbance = raw_data[raw_data["absorbance"].isna()]
print(missing_absorbance)
Det finnes ingen automatisk riktig måte å behandle en manglende verdi på. Mulige valg er blant annet å:
undersøke instrumentfila eller laboratorienotatene
utføre målingen på nytt
beholde raden og markere at verdien mangler
utelate raden fra en bestemt analyse
estimere verdien dersom det finnes en faglig og statistisk begrunnelse
I dette caset står det i instrumentloggen at målingen std_6_3 mislyktes fordi kyvetten ikke sto riktig. Vi kan derfor utelate akkurat denne raden fra analyser som krever absorbans:
clean_data = raw_data.copy()
clean_data = clean_data.dropna(subset=["absorbance"])
Vi bruker subset for å spesifisere hvilken kolonne som er relevant. Dersom vi hadde brukt dropna() uten argumenter, ville også alle radene for den ukjente prøven blitt fjernet fordi konsentrasjonen deres med hensikt er ukjent.
Viktig
En manglende verdi og en målt verdi lik null er ikke det samme. Null kan være et gyldig resultat. NaN betyr at verdien ikke er tilgjengelig.
Duplikater#
En rad kan ved en feil ha blitt lagret to ganger. Vi kan undersøke dette med:
duplicates = raw_data.duplicated()
print(raw_data[duplicates])
Fullstendig identiske rader kan fjernes med drop_duplicates, men også dette må begrunnes. To like tallverdier kan være to reelle replikater. De er bare duplikater dersom hele raden representerer den samme registreringen, for eksempel samme sample_id.
duplicate_ids = raw_data.duplicated(subset=["sample_id"], keep=False)
print(raw_data[duplicate_ids])
Filtrere data#
Vi kan velge ut rader ved hjelp av logiske vilkår. Her henter vi bare kalibreringsstandardene:
standards = clean_data[clean_data["sample_type"] == "standard"]
print(standards)
Den logiske testen lager først en serie med True og False. Når serien brukes mellom klammeparentesene, beholdes bare radene der resultatet er True.
Vi kan kombinere flere vilkår. Hvert vilkår må stå i parentes:
selected = clean_data[
(clean_data["sample_type"] == "standard")
& (clean_data["concentration_uM"] >= 4)
]
Andre nyttige operatorer er | for «eller», != for «ikke lik» og ~ for å negere et boolsk uttrykk.
Underveisoppgave
Skriv kode som velger ut:
alle blankprøvene
alle standardene med konsentrasjon mindre enn eller lik 6 µmol/L
alle rader som ikke tilhører den ukjente prøven
Løsningsforslag
blanks = clean_data[clean_data["sample_type"] == "blank"]
low_standards = clean_data[
(clean_data["sample_type"] == "standard")
& (clean_data["concentration_uM"] <= 6)
]
known_samples = clean_data[clean_data["sample_type"] != "unknown"]
Sortere data#
Vi kan sortere etter én eller flere kolonner:
sorted_data = clean_data.sort_values(
by=["sample_type", "concentration_uM", "replicate"]
)
Sortering endrer ikke den kjemiske betydningen av dataene, men kan gjøre det lettere å oppdage uventede verdier eller kontrollere at replikater hører til riktig prøve.
Gruppere og oppsummere data#
Kalibreringsstandardene er målt i replikater. Vi kan gruppere dem etter konsentrasjon og beregne antall målinger, gjennomsnitt og standardavvik:
standards = clean_data[clean_data["sample_type"] == "standard"]
summary = standards.groupby("concentration_uM")["absorbance"].agg(
["count", "mean", "std"]
)
print(summary)
groupby deler først radene i grupper med samme konsentrasjon. agg bestemmer hvilke statistiske størrelser som skal beregnes for hver gruppe.
Du kan rydde og gruppere datasettet i editoren nedenfor.
Underveisoppgave
Legg til
minogmaxi oppsummeringen.Hvorfor mangler standardavviket dersom en gruppe bare har én måling?
Sammenlikn spredningen ved de ulike konsentrasjonene. Er det grunnlag for å si at spredningen øker med absorbansen?
Løsningsforslag
Standardavviket til et utvalg kan ikke estimeres fra én enkelt måling. Med så få replikater er det også vanskelig å konkludere sikkert om hvordan spredningen endres. Dataene kan gi en antydning, men en påstand om økende spredning krever flere målinger og en mer systematisk analyse.
Lage nye kolonner#
Noen behandlingstrinn gir nye verdier som bør lagres uten å slette originalmålingen. Vi kan for eksempel korrigere absorbansen for middelverdien til blankprøvene:
blank_mean = clean_data.loc[
clean_data["sample_type"] == "blank",
"absorbance",
].mean()
clean_data["blank_corrected_absorbance"] = (
clean_data["absorbance"] - blank_mean
)
Den opprinnelige kolonnen absorbance beholdes, mens den nye kolonnen dokumenterer den beregnede verdien. Dette gjør det mulig å kontrollere beregningen og sammenlikne rå og korrigerte data.
loc brukes her til å velge bestemte rader og én bestemt kolonne. Før komma står radvilkåret; etter komma står kolonnenavnet.
Modellvalg
Blankkorreksjon er ikke bare en teknisk Pandas-operasjon. Når vi trekker fra blankverdien, antar vi at blankbidraget kan adderes til prøvens signal, og at det er representativt for målingene som korrigeres.
Fra dataramme til figur#
Pandas-kolonner kan sendes direkte til Matplotlib:
import matplotlib.pyplot as plt
standards = clean_data[clean_data["sample_type"] == "standard"]
plt.scatter(standards["concentration_uM"], standards["absorbance"])
plt.xlabel("Concentration (µmol/L)")
plt.ylabel("Absorbance")
plt.title("UV–Vis calibration standards")
plt.tight_layout()
plt.show()
Her vises alle replikatene. Det gjør spredningen synlig. Dersom vi bare plotter gjennomsnittene, blir figuren ryddigere, men vi mister informasjon om variasjonen mellom målingene.
En reproduserbar arbeidsflyt#
En enkel og ryddig analyse kan bygges opp slik:
import pandas as pd
# 1. Read and preserve raw data
raw_data = pd.read_csv("data/uvvis_raw.csv")
# 2. Inspect
print(raw_data.info())
print(raw_data.isna().sum())
# 3. Create a working copy
clean_data = raw_data.copy()
# 4. Apply a justified cleaning decision
clean_data = clean_data.dropna(subset=["absorbance"])
# 5. Create derived values
blank_mean = clean_data.loc[
clean_data["sample_type"] == "blank",
"absorbance",
].mean()
clean_data["blank_corrected_absorbance"] = (
clean_data["absorbance"] - blank_mean
)
# 6. Save processed data without overwriting the raw file
clean_data.to_csv("data/uvvis_processed.csv", index=False)
Kodekommentarene dokumenterer hva som er gjort, men en fullstendig analyse må også forklare hvorfor valgene er rimelige.
Oppgaver#
Oppgave 2.1
Åpne uvvis_raw.csv som råtekst. Identifiser kolonnenavn, skilletegn, manglende verdier og hvilke kolonner som inneholder enheter.
Oppgave 2.2
Les uvvis_raw.csv med Pandas. Bruk head, shape, columns, dtypes og info til å lage en kort beskrivelse av datasettet.
Oppgave 2.3
Forklar hvorfor det vil være feil å bruke dropna() uten subset på hele UV–Vis-datasettet. Demonstrer hva som skjer, men start på nytt fra rådata etterpå.
Oppgave 2.4
Lag et lite datasett med én fullstendig duplikatrad og to reelle replikater som tilfeldigvis har samme absorbans. Bruk duplicated til å vise hvorfor vi må vurdere mer enn bare måleverdien.
Oppgave 2.5
Velg ut blankprøvene og beregn middelverdien. Opprett en ny kolonne med blankkorrigert absorbans. Kontroller at middelverdien til de blankkorrigerte blankprøvene er omtrent null.
Oppgave 2.6
Grupper standardene etter konsentrasjon og beregn count, mean, std, min og max. Hvilke av størrelsene er vanskeligst å tolke når en gruppe bare har to målinger?
Oppgave 2.7
Fila reaction_kinetics.csv inneholder tid og absorbans. Les fila, undersøk datatypene, sorter etter tid og lag en ny kolonne relative_absorbance der hver absorbans deles på startverdien.
Oppgave 2.8
En fil inneholder kolonnene Temperature, temperature og TEMP. Skriv en kort vurdering av hvorfor automatisk standardisering ikke nødvendigvis er nok. Hvordan kan du finne ut om kolonnene representerer samme størrelse og enhet?
Oppgave 2.9
Lag en figur av alle kalibreringsstandardene fra den ryddede datarammen. Bruk forskjellig markør for hver replikatserie. Vurder om dette gjør figuren mer eller mindre informativ.
Oppgave 2.10 – samlet case
Lag et fullstendig program som leser uvvis_raw.csv, undersøker manglende verdier, lager en bearbeidet kopi, fjerner den dokumenterte mislykkede absorbansmålingen, blankkorrigerer dataene og lagrer resultatet som en ny CSV-fil. Programmet skal aldri endre rådatafila.
Flere oppgaver med andre kjemiske data#
Her skal du bruke framgangsmåtene fra kapitlet på nye typer data. Les forsøksbeskrivelsen, og forklar hva én rad representerer før du begynner å regne. Skriv en kort plan, lag programmet og kontroller at resultatet svarer på spørsmålet.
Alle de nye datafilene nedenfor er syntetiske øvingsdata. De er laget for oppgavene og er ikke resultater fra faktiske laboratorieforsøk. Behold råfilene og lagre bearbeidede data under et nytt navn.
Oppgave 2.11–2.14 kan gjøres nå eller etter kapitlet om visualisering. Oppgave 2.15 forutsetter kalibrering. Oppgave 2.16 kombinerer kalibrering med numerisk integrasjon og kan brukes som frivillig egenkontroll før eksamen.
Last ned filene for oppgaven du skal løse, og legg dem i ei mappe som heter data ved siden av notebooken din.
Visualisering med Seaborn#
Oppgave 2.11–2.14 har valgfrie visualiseringsutvidelser. Seaborn kan bruke datarammen direkte: data angir tabellen, mens x og y angir kolonnenavnene. hue gir farger etter en kolonne, og style kan gi forskjellige markører eller linjetyper. Matplotlib brukes fortsatt til aksetitler, referanselinjer og visning.
import seaborn as sns
import matplotlib.pyplot as plt
sns.set_theme(style="whitegrid")
Kodehintene bruker Seaborn 0.12 eller nyere. Velg hva figuren skal vise før du velger plottype. For få observasjoner er enkeltpunkter ofte nyttige. Et standardavvik og et konfidensintervall viser forskjellige størrelser. Angi derfor eksplisitt hva eventuelle feilstolper skal representere.
Dokumentasjon: scatterplot, stripplot, pointplot og lineplot.
Oppgave 2.11 – Hvilke ledningsevnemålinger kan vi bruke?
Kan gjøres etter dette kapitlet.
Datafiler: ledningsevne.csv.
Et laboratorium måler ledningsevnen i fem NaCl-løsninger ved 25 °C. Hver løsning er lest av tre ganger. Én rad er én instrumentavlesning, ikke et nytt forsøk på å lage løsningen.
Fila ledningsevne.csv inneholder measurement_id, concentration_mmol_L, replicate, conductivity_uS_cm, status og comment. comment er bare fylt ut når noe spesielt har skjedd.
Fra laboratorienotatene: Avlesningen L025_2 ble ikke lagret. Under L100_3 var proben ikke nedsenket i løsningen. L050_2 ble eksportert to ganger og har derfor samme measurement_id på to rader. De to like verdiene ved 2,00 mmol/L er derimot to forskjellige, gyldige avlesninger.
a) Undersøk fila. Hvor mange avlesninger var planlagt, og hvorfor er ikke antallet rader det samme? Hvilke manglende verdier er et problem for analysen?
b) Lag en bearbeidet kopi med gyldige avlesninger. Dokumenter hvilke rader du utelater og hvorfor. Bruk samme skrivemåte for statusverdiene.
c) Vis antall gyldige avlesninger og gjennomsnittlig ledningsevne ved hver konsentrasjon. Lag en figur som viser sammenhengen mellom konsentrasjon og ledningsevne. Bruk riktige enheter.
d) En student foreslår først å fjerne alle rader med tomme felt og deretter fjerne gjentatte ledningsevneverdier. Forklar hva som går galt med begge forslagene. Lagre den bearbeidede datarammen i en ny CSV-fil.
e) Visualisering med Seaborn: Lag et punktplott av de opprinnelige ledningsevnemålingene der farge og markør viser status. Rydd først skrivemåten i statuskolonnen, men behold foreløpig både gyldige og ugyldige målinger. Sammenlikn med figuren fra de ryddede dataene. Hvilket problem blir synlig? Kan figuren alene avsløre eksportkopien og den manglende avlesningen?
Hint
Rydd tekst med .str.strip().str.lower(). Se etter gjentatte measurement_id, og skill mellom en manglende kommentar og en manglende måleverdi. Du kan bruke groupby eller en løkke til å oppsummere dataene.
Seaborn-hint
import seaborn as sns
sns.scatterplot(data=data, x="concentration_mmol_L",
y="conductivity_uS_cm", hue="status", style="status")
Her skal data være en kopi av rådataene med standardisert status. Legg selv til aksetitler, enheter og plt.show().
Oppgave 2.12 – Hvilken pipette leverer nærmest riktig volum?
Kan gjøres etter dette kapitlet. Standardavvik er en valgfri utvidelse etter statistikkapitlet.
Datafiler: pipettekontroll.csv.
To pipetter, A og B, er stilt inn på 1,000 mL. For hver pipette utføres seks separate pipetteringer av vann. Massen av et tomt oppsamlingsbeger og massen etter tilsetting av vann registreres ved hver pipettering. Én rad i pipettekontroll.csv beskriver én fullstendig pipettering.
Kolonnene er pipette, replicate, nominal_volume_mL, tare_mass_g, total_mass_g og temperature_C. Under B, replikat 4, ble massen etter tilsetting ikke notert. Alle forsøkene ble gjort ved 25 °C. Bruk vanntettheten \(\rho=0{,}9970\ \mathrm{g/mL}\) som oppgitt beregningsverdi.
a) Forklar hvordan de to massekolonnene kan brukes til å bestemme volumet som faktisk ble levert. Skriv en kort analyseplan før du lager programmet.
b) Lag nye kolonner for vannmassen, levert volum og relativt avvik fra innstilt volum, i prosent. Behold de opprinnelige kolonnene.
c) Sammenlikn pipettene med en oversikt over gyldige pipetteringer og gjennomsnittlig levert volum. Lag en figur som viser avviket ved hver pipettering. Hvilken pipette leverer i gjennomsnitt nærmest det innstilte volumet? Kan gjennomsnittet alene fortelle hvilken som har best presisjon?
d) Lagre resultatene i en ny fil. Forklar hvordan fortegnet til det relative avviket skal tolkes.
Valgfri utvidelse: Beregn empirisk standardavvik for levert volum fra hver pipette. Hva tilfører dette sammenlikningen?
e) Visualisering med Seaborn: Vis levert volum med pipette på x-aksen og én prikk per gyldig pipettering. Bruk sns.stripplot med litt horisontal forskyvning (jitter) så punkter ikke skjuler hverandre. Legg inn en horisontal linje ved 1,000 mL. Hva viser denne figuren som et diagram med bare gjennomsnittene ikke viser? Representerer den horisontale forskyvningen forskjeller i målt volum?
Etter statistikkapitlet: Legg gjennomsnitt og ett empirisk standardavvik over punktplottet med sns.pointplot(errorbar="sd"). Forklar forskjellen mellom disse stolpene og et 95 % konfidensintervall. Bruk antallet gyldige pipetteringer fra hver pipette i vurderingen.
Hint
Bruk \(m_{\mathrm{vann}}=m_{\mathrm{etter}}-m_{\mathrm{tom}}\), \(V=m_{\mathrm{vann}}/\rho\) og relativt avvik \(100(V-V_{\mathrm{innstilt}})/V_{\mathrm{innstilt}}\). En tom masseverdi er ikke en målt masse på null.
Seaborn-hint
sns.stripplot(data=pipette_data, x="pipette", y="delivered_volume_mL",
order=["A", "B"], jitter=0.08)
plt.axhline(1.000, color="black", linestyle="--")
Etter statistikkapitlet kan du legge til sns.pointplot på de samme aksene. Bruk samme order, errorbar="sd" og linestyles="none". Uten en eksplisitt innstilling velger pointplot normalt et konfidensintervall, ikke standardavvik.
Oppgave 2.13 – Er kloridresultatene sammenliknbare?
Kan gjøres etter dette kapitlet. Oppgaven kan løses med filtrering og en løkke. Kobling med merge er vist i hintet som et alternativ.
Datafiler: klorid_titrering.csv, klorid_ionekromatografi.csv.
Et laboratorium har analysert vannprøver med to metoder. Titreringsresultatene i klorid_titrering.csv er oppgitt i mg klorid per liter. Resultatene fra ionekromatografi i klorid_ionekromatografi.csv er oppgitt i mmol klorid per liter.
Begge filene har kolonnen sample_id. Målekolonnene heter henholdsvis chloride_mg_L og chloride_mmol_L. Én rad er ett rapportert analyseresultat. Rekkefølgen på prøvene er forskjellig i de to filene. Enkelte prøver finnes bare i én fil. Bruk molarmassen \(M(\mathrm{Cl^-})=35{,}45\ \mathrm{g/mol}\) som oppgitt beregningsverdi.
a) Undersøk hvilke prøver som finnes i begge filer, og hvilke som mangler et resultat fra den andre metoden. Hvorfor er det feil å trekke tallkolonnene direkte fra hverandre i den rekkefølgen de står?
b) Lag en tabell der resultatene for samme prøve står på samme rad og har samme enhet. Behold prøve-ID. Forklar enhetsomregningen.
c) Beregn forskjellen «ionekromatografi minus titrering» for hver sammenliknbar prøve. Vis forskjellene i en figur, og finn den gjennomsnittlige forskjellen. Beskriv hva fortegnet betyr.
d) En kollega sier at de to metodene er like gode fordi resultatene følger hverandre. Hvilken ytterligere informasjon ville du trengt for å vurdere hvor riktige analyseresultatene er? Du skal ikke gjennomføre en hypotesetest her.
e) Visualisering med Seaborn: Lag et spredningsplott med titreringsresultatet på x-aksen og ionekromatografiresultatet på y-aksen. Bruk mg/L på begge akser. Legg inn linja \(y=x\) med lik lengdeskala på aksene. Hva ville det bety om punktene lå på denne linja?
Sammenlikn med figuren av metodeforskjellene fra del c. Hvilken figur viser best hvor stor forskjellen er? Ser forskjellen omtrent konstant ut, eller øker den med konsentrasjonen? Begrunn med både tall og figur.
Hint
Du kan gå gjennom prøve-ID-ene med en løkke og velge ut samme prøve i hver fil. Du kan også koble tabellene med:
paired = titration.merge(chromatography, on="sample_id", how="inner")
inner beholder bare prøve-ID-er som finnes i begge filer. Her finnes hver ID høyst én gang i hver fil. Husk å gjøre enhetsomregningen før du sammenlikner måleverdiene.
Seaborn-hint
sns.scatterplot(data=paired, x="chloride_mg_L", y="chloride_ic_mg_L")
Lag referanselinja med plt.plot([0, maksimum], [0, maksimum], "--"). plt.axis("equal") gir samme lengdeskala for like konsentrasjonsforskjeller på begge akser. Linja \(y=x\) er en referanse for samsvar, ikke en tilpasset regresjonslinje.
Oppgave 2.14 – Hvor mye endres surhetsgraden?
Kan gjøres etter dette kapitlet og kapitlet om visualisering. Sammenhengen som trengs mellom pH og konsentrasjon, er gitt nedenfor.
Datafiler: ph_lagring.csv.
pH er målt flere ganger under lagring av to forskjellige, fortynnede løsninger, A og B. ph_lagring.csv inneholder sample_id, time_h og pH. Fila bruker semikolon som skilletegn og komma som desimalskilletegn. Radene står ikke i tidsrekkefølge.
Hver rad er én måling på et bestemt tidspunkt. Målingene ved forskjellige tider er ikke replikater av samme tilstand. For denne oppgaven bruker vi tilnærmingen
a) Les og kontroller dataene. Vis utviklingen i pH med en egen kurve for hver løsning. Sørg for at punktene kobles sammen i riktig rekkefølge.
b) Legg til en kolonne med beregnet hydroniumkonsentrasjon. Lag en ny figur med denne konsentrasjonen som funksjon av tid.
c) Finn startverdien og sluttverdien for hver løsning. Hvor mange ganger større er hydroniumkonsentrasjonen ved slutten enn ved starten? Hvilken løsning har størst sluttkonsentrasjon, og hvilken har størst relativ økning?
d) En student sier: «pH har sunket med omtrent ti prosent, så hydroniumkonsentrasjonen har økt med omtrent ti prosent.» Vurder påstanden ved hjelp av dataene. Kan disse målingene alene fortelle hvorfor løsningene blir surere?
e) Visualisering med Seaborn: Lag figurene fra del a og b med sns.lineplot. Bruk hue="sample_id" og style="sample_id", slik at løsningene skilles både med farge og linje-/markørtype. Forklar hva hver av parameterne x, y, hue og style viser.
Bruk estimator=None og errorbar=None for å tegne de registrerte tidsseriene direkte. Hvorfor ville et usikkerhetsbånd mellom tidspunktene vært misvisende som mål på måleusikkerheten i dette datasettet?
Hint
Etter innlesing kan du velge én løsning om gangen og sortere med sort_values("time_h"). Finn startverdien for hver løsning separat. Ikke bruk første rad i den usorterte fila som startverdi for hele datasettet.
Seaborn-hint
sns.lineplot(data=ph_data, x="time_h", y="pH",
hue="sample_id", style="sample_id", markers=True,
estimator=None, errorbar=None)
Lag deretter en ny figur med den beregnede konsentrasjonskolonnen som y. lineplot sorterer normalt punktene etter x innen hver serie. Det er likevel fortsatt nødvendig å velge riktig start- og sluttmåling i egne beregninger.
Oppgave 2.15 – Natrium med flammeemisjon
Samleoppgave etter kapitlet «Kalibrering og sammenlikning av resultater».
Datafiler: natrium_flammeemisjon.csv.
Et laboratorium bestemmer natrium i vannprøver ved flammeemisjon. Instrumentet registrerer et lyssignal fra natrium. I det undersøkte området modelleres sammenhengen som
der \(S\) er instrumentets signal i counts og \(c\) er natriumkonsentrasjonen i mg/L. Bruk et fritt konstantledd. Dataene skal ikke blankkorrigeres i tillegg.
natrium_flammeemisjon.csv inneholder sample_id, sample_type, concentration_mg_L, replicate, signal_counts og dilution_factor. Hver standard og ukjent prøve er lest av tre ganger fra samme løsning. Én standardavlesning ved 4 mg/L ble ikke lagret.
Standardenes konsentrasjoner gjelder løsningene som ble analysert. Konsentrasjonsfeltet er tomt for ukjente prøver fordi konsentrasjonen skal bestemmes. dilution_factor er bare fylt ut for de ukjente prøvene. Faktoren er totalvolum delt på volumet av den opprinnelige prøven. Faktor 1 betyr at prøven ikke er fortynnet.
Oppdrag: Bestem hvilke ukjente prøver som kan gis et konsentrasjonsestimat fra denne kalibreringen, og rapporter konsentrasjonen i de opprinnelige prøvene.
Skriv først en kort plan. Lag deretter et program og en relevant kalibreringsfigur. Dokumenter databehandlingen, rapporter stigningstall og konstantledd med enheter, og begrunn om hvert prøveresultat ligger innenfor metodens undersøkte område. Foreslå neste handling for en prøve som ikke kan bestemmes forsvarlig med disse målingene.
Avslutt med å vurdere påstanden: «Hvis originalprøvens konsentrasjon er større enn høyeste standard, har vi alltid ekstrapolert.»
Hint
Skill mellom standarder og ukjente før du håndterer manglende konsentrasjoner. Vurder først konsentrasjonen i løsningen som faktisk ble målt. Fortynningsfaktoren brukes deretter til å regne tilbake til den opprinnelige prøven.
Oppgave 2.16 – Frivillig egenkontroll: koffein i en drikkevare
Gjøres etter kalibrering og numerisk integrasjon. Sett av omtrent 45–60 minutter til et første forsøk.
Datafiler: koffein_standarder.csv, koffein_prove.csv.
Et laboratorium skal bestemme koffeinkonsentrasjonen i en drikkevare ved kromatografi. Koffein gir en topp i detektorens signal. I denne metoden er arealet under toppen tilnærmet lineært avhengig av koffeinkonsentrasjonen innenfor standardenes område.
Du har to filer:
Fil |
Hva er målt? |
|---|---|
|
Kolonnene |
|
Kolonnene |
Prøvesignalet er korrigert for konstant bakgrunn. Ingen andre stoffer bidrar til signalet i dette tidsintervallet. Fila inneholder gyldige målinger, men radene står ikke i tidsrekkefølge og tidsintervallene er ikke like. Bruk en lineær kalibrering med fritt konstantledd. Det er ikke nødvendig med ytterligere bakgrunnskorreksjon.
Før analysen ble 5,00 mL drikkevare fortynnet til et totalvolum på 25,00 mL. Standardenes konsentrasjoner gjelder løsningene som ble analysert.
Oppdrag: Bestem koffeinkonsentrasjonen i den opprinnelige drikkevaren og vurder om resultatet ligger innenfor kalibreringens undersøkte område.
Skriv en kort analyseplan før du begynner å kode. Ta vare på planen og det første kodeforsøket.
Lag programmet. Vis målesignalet og kalibreringsdataene i relevante figurer. Rapporter konsentrasjonen med enhet og forklar beregningsgangen.
Beskriv to kontroller av resultatet. Forklar også forskjellen mellom replikatene i standardfila og målepunktene langs prøvetoppen. Kan du bruke de sistnevnte som replikater for å beregne usikkerheten i den ukjente konsentrasjonen?
Prøv først uten KI og uten en ferdig løsning på akkurat denne oppgaven. Du kan bruke nettsidene og vanlig dokumentasjon for Python-bibliotekene. Hvis du står fast, skriv ned hvor og hvorfor før du søker hjelp. Målet er å finne ut hvilke deler du kan sette sammen selv.
Videoer#
I videoene nedenfor kan du få en innføring eller repetisjon i filinnlesing og databehandling med Pandas.