Altair

Det er flere ulike Python-bibliotek vi kan bruke for å visualisere data. Her skal vi undersøke data ved å bruke to populære bibliotek: pandas og Vega-Altair. Etter denne modulen vil du kunne:

Hva er Altair?

Altair er et deklarativt bibliotek for statistisk visualisering i Python. Det er basert på Vega-Lite, et høynivå-grammatikk for interaktiv grafikk.

Med deklarativ mener vi at man kan oppgi en høynivå-spesifikasjon av hva man vil at visualiseringen skal inneholde: basert på data, grafiske markører og kodingskanaler. Man slipper å implementere visualiseringen ved hjelp av for-løkker, lavnivå grafikkkommandoer og lignende.

Kjerneideen er at man deklarerer koblinger mellom datafelter og visuelle kanaler som x-aksen, y-aksen og farge. De øvrige detaljene i plottet håndteres automatisk. Som et resulat av dette, kan et stort antall visualiseringer tegnes ved å bruke enkle kommandoer.

Ved å bruke Altair, har man en vennlig Python-API (Application Programming Interface) for å generere visuelle spesifikasjoner i interaktive miljøer som Jupyter Notebooks eller i en vanlig Python-fil, som deretter vises i nettleseren.

Multiple plots via Altair

Image credit: Screenshot from Vega-Altair

Importer Altair

Først må vi importere bibliotekene som trengs: pandas for dataframes og altair for visualisering. Vi vil tildele korte aliaser, pd for pandas og alt for Altair, som vi vil bruke gjennom hele koden vår.

import pandas as pd
import altair as alt

Last inn dataframen

Data i Altair er basert på pandas dataframes, som består av tabeller med rader og kolonner. Disse radene refereres ofte til som items eller entries, mens kolonnene som attributter, felt eller variabler.

Som på Dataanalyse-kursnotatet, laster vi inn datasettet som en dataframe ved å bruke den innebygde funksjonen i pandas: read_csv(). La oss lese inn Hawks-datasettet.

Husk: Installer først Altair med pip install altair.

hawks = pd.read_csv('https://raw.githubusercontent.com/vincentarelbundock/Rdatasets/refs/heads/master/csv/Stat2Data/Hawks.csv', index_col=0)
hawks.head()

Chart-objektet

I Python er objekter spesielle variabler som ikke kun inneholder data, men også sine egne funksjoner og metoder som kan brukes til å manipulere data.

Det grunnleggende objektet i Altair er Chart. Vi kan kalle på dette objektet fra Altair-biblioteket ved å skrive alt.Chart(). Dette objektet tar inn dataframen som et parameter, slik som Hawks-datasettet som vi har lagret i variabelen hawks.

alt.Chart(hawks) ## dette kommer til å krasje

Det er likevel ikke nok å definere Chart-objektet alene. Hva mer må vi fortelle Altair for å tegne dataene?

Mark og Kanaler

Når vi har definert Chart-objektet og satt inn hawks-dataframen, kan vi spesifisere hvordan vi vil visualisere det.

Vi introduserer rollene til mark og kanaler. En mark er en geometriske formen vi bruker for å markere dataelementer på grafen vår. Kanaler er den visuelle stylingen/ karakteristikken vi tilegner mark-ene. Dette inkluderer hvor og hvordan vi plasserer merket, og fargen vi tilegner det.

Her indikerer vi først hva slags merke vi skal bruke for å representere dataene. Vi kan sette mark-attributten til objektet ved å bruke en mark_*-metode.

Her er et eksempel med mark_tick().

alt.Chart(hawks).mark_tick()

Her viser utskriften kun en vertikal linje. Dette skjer fordi vi tegner ett merke per rad, men alle plottes direkte oppå hverandre fordi vi ennå ikke har spesifisert posisjoner for disse merkene.

For å skille punktene, kan man koble kanaler til datakolonner i datasettet. Wing-kolonnen kan for eksempel kobles til X-kanalen som representerer x-aksen/ horisontal posisjon. Her bruker vi encode()-metoden og legger til denne etter mark_tick()-metoden.

encode()-metoden kobler de visuelle kanalene (X, Y, farge, form, størrelse osv.) med datasettets kolonner/ felt. Altair gjør det mulig å definere disse kanalene med ulike syntax/ kodesnutter. For eksempel alt.X(“Kolonnenavn”)

alt.Chart(hawks).mark_tick().encode(alt.X("Wing"))

Nå er alle merkene spredt langs x-aksen i Chart der hvert merke angir vingelengden til en bestemt hauk. Her kan man altså se hvordan vingelengden er fordelt gjennom datasettet vårt.

Aggregere data

Selv om vi har fordelt dataene etter “Wing”, er det fortsatt mange målinger som overlapper (flere fugler med samme vingelengde).

Vi kan videre separere disse målingene ved å bruke en Y-kanal som representerer y-aksen/vertikal posisjon. Y kan vise antall målinger gjort av hver vingelengde. Her bruker vi mark_bar() istedenfor mark_tick().

alt.Chart(hawks).mark_bar().encode(
    alt.X("Wing"),
    alt.Y("count()")
)

count() er den enkleste måten å gjøre dette. Denne metoden teller hvor mange ganger hver måling “Wing” dukker opp i datasettet. Vi kan også gruppere disse Wing-målingene sammen slik at figuren blir lettere å lese. Her ser man ikke nødvendigvis hver enkelt måling, men heller trender i dataene. Dette er en parameter bin=True. Med denne måten kan man lage et histogram. Et histogram kan brukes til å oppsummere kontinuerlige data og vise fordelingen av numerisk variabel (tall).

alt.Chart(hawks).mark_bar().encode(
    alt.X("Wing", bin=True),
    alt.Y("count()")
)

Farge og interaksjon

Y-kanalen kan også settes til noe helt annet, som for eksempel “Weight”. Dette viser hvordan lengde på vingen og vekten henger sammen. Man kan altså få en ide om korrelasjonen mellom disse. Her brukes mark_circle() for å markere målingene.

alt.Chart(hawks).mark_circle().encode(
    alt.X("Wing"),
    alt.Y("Weight")
)

Ved å studere denne visualiseringen, ser man tydelig to eller tre samlinger av data. Hva kan være årsaken for disse grupperingene? Kan det ha noe med de ulike artene å gjøre? Vi kan sjekke denne hypotesen ved å farge prikkene etter art. Vi gjør dette ved å knytte color-kanalen til Species-kolonnen.

alt.Chart(hawks).mark_circle().encode(
    alt.X("Wing"),
    alt.Y("Weight"),
    color="Species"
)

Med denne visualiseringen får vi nå en oversikt over de generelle trendene mellom vekt, vingelengde og artene i datasettet vårt. Denne figuren er statisk - for å gjøre den interaktiv kan man kalle på metoden interactive(). Da blir det mulig og zoome inn og ut.

alt.Chart(hawks).mark_circle().encode(
    alt.X("Wing"),
    alt.Y("Weight"),
    color="Species"
).interactive()

Vi kan også tilpasse grafen ved å for eksempel velge en farge som passer bedre med datesettet. Et eksempel kan være å velge en gjennomsiktig brunfarge og endre gjennomsiktigheten til merkene for å vise tettheten av datapunktene.

Dette kan gjøres på to måter: inne i mark_*-metoden eller inne i encode()-metoden. Begge disse kodene vil gi samme resultat:

alt.Chart(hawks).mark_circle(color="brown", opacity=0.2).encode(
    alt.X("Wing"),
    alt.Y("Weight")
)
alt.Chart(hawks).mark_circle().encode(
    alt.X("Wing"),
    alt.Y("Weight"),
    color=alt.value("brown"),
    opacity=alt.value(0.2)
)

Repeterende Charts

Med Altair, kan man også kombinere flere charts sammen i en visualisering. Her kommer et eksempel med en spredningsplott-matrise. Dette brukes for å se korrelasjoner i dataene.

For eksempel man kan ha vekt, lengde på vingene og lengde på halen plottes i en spredningsplott-matrise med til sammen 9 spredningsplotter (som plottene nedenfor).

Dette kan også gjøres på to måter:

Vi kan implementere visualiseringen ved hjelp av for-løkker.

base = alt.Chart().mark_circle().encode(
    color='Species'
)

chart = alt.vconcat(data=hawks)
for y_encoding in ['Weight', 'Wing', 'Tail']:
    row = alt.hconcat()
    for x_encoding in ['Weight', 'Wing', 'Tail']:
        row |= base.encode(x=x_encoding, y=y_encoding) #create individual charts and stack horizontally into rows
    chart &= row # stack rows vertically into columns
chart

Eller vi kan bruke repeat()-metoden fra Altair.

alt.Chart(hawks).mark_circle().encode(
    alt.X(alt.repeat("column"), type='quantitative'),
    alt.Y(alt.repeat("row"), type='quantitative'),
    color='Species'
    ).repeat(
        row=["Weight", "Wing", "Tail"],
        column=["Weight", "Wing", "Tail"]
    )

Lagre visualiseringen

Etter man er ferdig med å visueliasere data, kan man lagde figuren til et HTML-dokument for å bruke senere:

chart = alt.Chart(hawks).mark_circle().encode(
    alt.X("Wing"),
    alt.Y("Weight"),
    color="Species"
)

chart.save("hawks.html") # or any file name/path of choice

Du kan åpne denne HTML-filen i en nettleser (f.eks. Safari, Google Chrome) for å se visualiseringen du har laget.