Visualisering av kjemiske data#
Læringsutbytte
Etter å ha arbeidet med dette temaet, skal du kunne:
velge en visualisering som passer til kjemiske data
bruke Matplotlib til å lage punkt- og linjeplott
lage figurer med aksetitler, enheter, tegnforklaring og hensiktsmessig skalering
visualisere flere dataserier og flere plott i samme figur
forklare hva en figur viser, og hva den ikke viser
Håndtering av data blir bare viktigere og viktigere. En viktig del av datahåndtering er å kunne lage informative figurer som beskriver dataene på en god måte. Programmering gir oss stor kontroll over hvordan dataene behandles og visualiseres, og gjør det mulig å gjenta den samme framgangsmåten når vi får nye data.
En figur er likevel ikke bare pynt. Valg av plott, akser og skala påvirker hvilke mønstre vi legger merke til. En god kjemisk figur skal gjøre det lettere å svare på et faglig spørsmål.
Datavisualisering
Datavisualisering betyr å framstille data grafisk slik at mønstre, variasjon og sammenhenger blir lettere å undersøke og formidle.
Før vi velger figur, bør vi derfor spørre:
Hva representerer hvert datapunkt?
Hvilken variabel har vi kontrollert, og hvilken har vi målt?
Er datapunktene uavhengige, eller følger de en naturlig rekkefølge?
Skal figuren vise rådata, en oppsummering eller en modell?
Punktplott av måledata#
Hvis vi har få datapunkter, kan vi skrive dem inn i lister direkte i programmet. Vi tar utgangspunkt i et eksempel der damptrykket til vann er målt ved ulike temperaturer:
Temperatur (°C) |
Damptrykk (kPa) |
|---|---|
16 |
1,817 |
18 |
2,063 |
20 |
2,339 |
22 |
2,644 |
24 |
2,984 |
import matplotlib.pyplot as plt
temperature_C = [16, 18, 20, 22, 24]
vapor_pressure_kPa = [1.817, 2.063, 2.339, 2.644, 2.984]
plt.scatter(temperature_C, vapor_pressure_kPa)
plt.xlabel("Temperature (°C)")
plt.ylabel("Vapor pressure (kPa)")
plt.show()
Funksjonen scatter lager et punktplott. Hvert punkt kobler sammen én temperatur og det tilhørende damptrykket. Dette er måledata: Temperaturen er den uavhengige variabelen vi har valgt, mens damptrykket er den avhengige variabelen vi har målt.
Det er viktig at listene har like mange elementer. Elementer med samme indeks hører sammen. Den første temperaturen kobles til det første damptrykket, den andre temperaturen til det andre damptrykket, og så videre.
Enheter og aksetitler#
En figur uten aksetitler og enheter er vanskelig å tolke. xlabel og ylabel brukes til å beskrive hva aksene viser. Enheten bør stå i parentes. Selve tallene i datasettet skal normalt ikke inneholde enhetstekst, fordi Python da ikke lenger kan behandle dem som tall.
Vi kan også legge til tittel, rutenett, merkelapp og tegnforklaring:
import matplotlib.pyplot as plt
temperature_C = [16, 18, 20, 22, 24]
vapor_pressure_kPa = [1.817, 2.063, 2.339, 2.644, 2.984]
plt.scatter(temperature_C,
vapor_pressure_kPa,
color="#176b87",
s=55,
label="Measurements")
plt.xlabel("Temperature (°C)")
plt.ylabel("Vapor pressure (kPa)")
plt.title("Vapor pressure of water")
plt.grid(alpha=0.25)
plt.legend()
plt.tight_layout()
plt.show()
tight_layout justerer avstanden mellom elementene slik at for eksempel aksetitler ikke blir kuttet. Farge og punktstørrelse kan gjøre figuren tydeligere, men utformingen bør ikke overdøve dataene.
Du kan kjøre og endre damptrykksprogrammet i editoren nedenfor.
Underveisoppgave
Endre farge og punktstørrelse.
Fjern én av aksetitlene. Hvilken informasjon går tapt?
Utvid datasettet med en måling ved 26 °C og 3,36 kPa.
Bytt om listene i
plt.scatter. Hvordan endrer det den faglige framstillingen?
Løsningsforslag
Et nytt datapunkt legges til ved å føye 26 til temperature_C og 3.36 til vapor_pressure_kPa. Listene må fortsatt ha samme lengde. Dersom listene byttes om, framstilles temperatur som en funksjon av damptrykk. Punktene inneholder den samme informasjonen, men figuren svarer på et annet spørsmål.
Skal punktene bindes sammen?#
Funksjonen plot tegner som standard linjer mellom punktene. Det kan være hensiktsmessig når dataene følger en naturlig rekkefølge, for eksempel en tidsserie:
import matplotlib.pyplot as plt
time_s = [0, 10, 20, 30, 40, 50, 60]
absorbance = [0.812, 0.673, 0.552, 0.458, 0.378, 0.313, 0.260]
plt.plot(time_s, absorbance, marker="o")
plt.xlabel("Time (s)")
plt.ylabel("Absorbance")
plt.title("Absorbance during a reaction")
plt.show()
Her viser linja rekkefølgen på målingene og gjør tidsutviklingen lettere å følge. Linja betyr likevel ikke at vi har målt alle tidspunktene mellom punktene. Den er en visuell forbindelse, ikke i seg selv en kontinuerlig kjemisk modell.
For kalibreringsstandarder er et punktplott ofte et bedre utgangspunkt. Standardene er selvstendige prøver, og en eventuell linje bør komme fra en regresjonsmodell. Vi bør ikke la plot koble dem sammen bare fordi de står i stigende rekkefølge.
Huskeregel
Bruk punktplott når du vil vise enkeltmålinger og sammenhengen mellom to størrelser. Bruk linjer når rekkefølgen mellom punktene er viktig, eller når linja representerer en eksplisitt modell.
Du kan undersøke tidsserien i editoren nedenfor.
Underveisoppgave
Bytt
plt.plotmedplt.scatter. Hva blir lettere eller vanskeligere å se?Fjern markørene fra linjeplottet. Hvilken informasjon blir mindre tydelig?
Beskriv den kjemiske utviklingen i figuren uten å hevde mer enn dataene viser.
Løsningsforslag
Absorbansen avtar raskt i starten og langsommere seinere. Dersom absorbansen er proporsjonal med konsentrasjonen til én absorberende forbindelse, er dette konsistent med at konsentrasjonen til forbindelsen avtar. Figuren alene viser ikke hvilken reaksjonsorden eller mekanisme som gjelder.
Flere dataserier i samme figur#
Vi kan sammenlikne dataserier ved å plotte dem i samme koordinatsystem. Da må de få ulike markører eller linjestiler og tydelige merkelapper:
import matplotlib.pyplot as plt
time_s = [0, 20, 40, 60, 80, 100]
absorbance_298_K = [0.812, 0.552, 0.378, 0.260, 0.181, 0.128]
absorbance_308_K = [0.809, 0.476, 0.284, 0.172, 0.108, 0.071]
plt.plot(time_s, absorbance_298_K, marker="o", label="298 K")
plt.plot(time_s, absorbance_308_K, marker="s", label="308 K")
plt.xlabel("Time (s)")
plt.ylabel("Absorbance")
plt.title("Reaction at two temperatures")
plt.legend()
plt.tight_layout()
plt.show()
En god tegnforklaring gjør det mulig å skille dataseriene uten å være avhengig av farge alene. Dette er viktig både ved utskrift i gråtoner og for personer med redusert fargesyn.
Underveisoppgave
Hvilken reaksjonsblanding ser ut til å reagere raskest? Er figuren alene tilstrekkelig til å konkludere med at temperatur er årsaken til forskjellen?
Løsningsforslag
Absorbansen avtar raskest ved 308 K. Dersom temperatur er den eneste systematiske forskjellen mellom forsøkene, støtter dataene at reaksjonen går raskere ved høyere temperatur. Figuren dokumenterer ikke forsøksdesignet, og kan derfor ikke alene utelukke andre forskjeller mellom prøvene.
Flere plott i samme figur#
Noen ganger blir én akse overfylt. Da kan vi bruke subplots til å lage flere akser i samme figur:
import matplotlib.pyplot as plt
time_s = [0, 20, 40, 60, 80, 100]
absorbance_298_K = [0.812, 0.552, 0.378, 0.260, 0.181, 0.128]
absorbance_308_K = [0.809, 0.476, 0.284, 0.172, 0.108, 0.071]
fig, axes = plt.subplots(1, 2, figsize=(10, 4), sharey=True)
axes[0].plot(time_s, absorbance_298_K, marker="o")
axes[0].set_title("298 K")
axes[0].set_xlabel("Time (s)")
axes[0].set_ylabel("Absorbance")
axes[1].plot(time_s, absorbance_308_K, marker="s", color="#b23a48")
axes[1].set_title("308 K")
axes[1].set_xlabel("Time (s)")
fig.suptitle("Reaction at two temperatures")
fig.tight_layout()
plt.show()
Variabelen axes inneholder de to koordinatsystemene. Vi bruker axes[0] for den første og axes[1] for den andre. sharey=True gir dem samme y-akse, slik at kurvene kan sammenliknes visuelt uten at skalaen endres.
Aksegrenser og visuell redelighet#
Aksegrensene kan justeres med xlim og ylim, men valget må være faglig begrunnet:
plt.ylim(0, 0.9)
En svært smal y-akse kan få små forskjeller til å virke dramatiske. En svært bred akse kan skjule reelle variasjoner. Det finnes ikke én riktig grense for alle figurer, men leseren må få et ærlig bilde av størrelsene og variasjonen.
Logaritmiske akser kan være nyttige når verdiene dekker flere størrelsesordener. De skal merkes tydelig og brukes fordi de hjelper oss å undersøke et faglig spørsmål, ikke bare fordi figuren ser penere ut.
Hva er en god kjemisk figur?#
Før du avslutter en figur, kan du kontrollere følgende:
Er datapunktene eller modellen som vises, tydelig identifisert?
Har begge aksene navn og enhet?
Er skalaen hensiktsmessig og redelig?
Kan dataseriene skilles uten bare å bruke farge?
Er tegnforklaringen nødvendig og forståelig?
Viser figuren rådata, middelverdier eller en modell?
Dersom figuren har feilstolper: Er det oppgitt hva de representerer?
Kan du formulere en kjemisk tolkning uten å overtolke dataene?
Oppgaver#
Oppgave 1.1
Lag et punktplott av temperaturene [10, 20, 30, 40, 50] °C og løselighetene [21.2, 31.6, 45.8, 63.9, 85.5] g per 100 g vann. Gi figuren aksetitler, enheter og en faglig tittel.
Oppgave 1.2
Tegn løselighetsdataene fra oppgave 1.1 både med scatter og plot. Forklar hvilken versjon du foretrekker, og hva linja mellom punktene eventuelt antyder.
Oppgave 1.3
Programmet nedenfor lager en figur som er vanskelig å tolke. Finn minst fire forbedringer.
import matplotlib.pyplot as plt
x = [0, 1, 2, 3, 4]
y = [7.02, 6.81, 6.60, 6.42, 6.25]
plt.plot(y, x, color="yellow")
plt.title("Results")
plt.show()
Oppgave 1.4
Les fila reaction_kinetics.csv med Pandas og visualiser absorbansen som funksjon av tid. Bruk både punkter og linje. Beskriv utviklingen med kjemiske ord.
Oppgave 1.5
Lag to realistiske dataserier som viser absorbansen gjennom en reaksjon ved to temperaturer. Vis seriene i samme koordinatsystem og deretter i to delplott. Diskuter hvilken figur som gjør sammenlikningen enklest.
Oppgave 1.6
En student viser gjennomsnittsverdier med feilstolper, men skriver bare «error bars» i figurteksten. Forklar hvorfor dette er utilstrekkelig. Hvilke ulike statistiske størrelser kan feilstolpene representere?
Oppgave 1.7
Lag en figur der en misvisende y-akse får to nesten like måleserier til å se svært forskjellige ut. Lag deretter en mer redelig versjon. Forklar hvilke valg du gjorde.
Oppgave 1.8 – samlet case
Fila uvvis_calibration.csv inneholder blankprøver, kalibreringsstandarder og en ukjent prøve. Lag en første utforskende figur av absorbans som funksjon av konsentrasjon. Vis bare standardene. Hvilken informasjon mister du dersom du først beregner ett gjennomsnitt for hver konsentrasjon?
Video#
I videoen nedenfor kan du få en innføring eller repetisjon i hvordan du plotter i Python.