12  Typiske feil vi (jeg) gjør og hvordan fikse dem

Det er uendelig mange måter å gjøre noe feil på. Dette gjelder egentlig uansett hvilket program du arbeider i. Noe som er fint i R er at du vanligvis får en klar feilmelding når noe går galt. Noe som er mindre fint er at denne feilmeldinga ikke alltid er så enkel å tolke. Likevel, se alltid på meldinga først. Her får du en tydlige pekepinn på hva som gikk galt. Man lærer seg etter hvert hvordan å lese disse meldingene, skjønt de kan virke gresk i starten.

Her har jeg samla noen av de feila som jeg enten gjør oftest, eller som jeg tenker mange gjør feil. Hvis ingenting av dette hjelper, kan man alltids spørre om hjelp online. Mitt foretrukne nettsted for dette er StackOverlow. Undersida deres, CrossValidated, kan også brukes. Kvaliteten på meldingene her er høy, men det går tidvis på bekostning av normal høflighet. Hvis man følger reglene deres og gir et representativt eksempel vil de vanligvis være greie. Dette er forøvrig en bra måte å be om hjelp på uansett.

  1. Forklar tydlig hva du lurer på: hva ønsker du å få som utfall?
  2. Forklar hva du hva forsøkt
  3. Gi eksempeldatasett slik at hjelperne kan bruke det når de gir råd

Uansett, her er min liste over typiske feil

12.1 Glemt å laste inn en pakke

Jeg starter alle R-sesjoner med å laste inn pakker, og jeg laster nesten alltid inn tidyverse. Hvis jeg glemmer det, vil funksjoner fra denne pakka ikke være tilgjengelig.

12.2 Laster inn pakker i feil rekkefølge

Det lønner seg å laste inn pakker i omvendt prioritert rekkefølge. Dette er fordi en del pakker inneholder funksjoner med samme navn, men ulik bruksområde. Da vil den siste pakka du laster inn maskere den tidligere funksjonen. For eksempel inneholder stats funksjonen filter(). Denne blir erstatte med dplyrs filter() når vi laster inn den pakka (often via tidyverse). Jeg pleier dermed ofte å laste inn tidyverse sist. Denne feilen er vanskelig å feilsøke, fordi du kan få en feilmelding uten å ha gjort noe som helst endring i koden. (Les: jeg har kasta bort mye tid på å feilsøke når det viste seg at det eneste jeg hadde gjort var å endre rekkefølgene pakkene blei lasta inn på, slik an funksjon jeg var avhengig av fra pakke1 blei bytta ut med en annen funksjon med samme navn fra pakke2.)

Husk at det går an å bruke en pakkes funksjon uten å laste den inn ved å bruke ::, slik som i dplyr::filter(). Det bidrar til at å unngå at du får lasta inn for mange pakker som overskriver hverandres funksjoner. Spesielt hvis du bare bruker få funksjoner noen få ganger, kan dette lønne seg. Jeg gjør vanligvis dette når jeg importerer datasett, siden dette er noe jeg kun gjør én gang per prosjekt. Hvis jeg derimot skal eksportere mange filer, vil det spare tastaturet mitt å bare laste inn pakka.

Forøvrig har vi en liknende feil

12.3 “Jeg har ikke gjort noen endringer, men plutselig funker ikke koden min!”

Dette er i prinsippet umulig å feilsøke. Heldigvis kan vi benytte oss av et smertelig nyttig prinsipp: Årsaken er alltid at du har gjort en feil.

Dette skjer typisk dersom du har arbeida lenga i en sesjon uten å restarte R. Første gang du restarter R og kjører koden på nytt får du feilmelding. Da er ofte problemet at du på et tidspunkt har lagra noe i miljøet (environment), som ikke lengre er tilstede i koden. Hvis andre deler av koden er avhengig av dette objektet, vil de feile nå som objektet ikke lengre er tilstede. Du må rett og slett finne ut hvor bruddet skjer, og fikse det.

En måte å forebygge dette på er ved å ta i bruke functional programming. Det vil si at vi bruker funksjoner i stor grad og sjelden lagrer objekter direkte i miljøet. Brodrigues forklarer det bedre.

En annen måte å forebygge det på er å restarte R-sesjonen ofte. Da unngår du at du arbeider på et gammelt objekt som ikke lenger er fundert i det nåværende skriptet. Jeg pleier alltid restarte R-sesjonen når jeg har fullført et delmål i skriptet. Ofte finner jeg en feil da, f.eks. har jeg gitt nytt navn til en funksjon eller objekt og glemt å endre det i skriptet. Se mer om dette i sec-rstudio.

12.4 Sender et objekt via pipe til en funksjon som ikke er pipevennlig

Pipa (%>%) er nyttig. Så nyttig at jeg bruker den hele tida for å gjøre koden min mer leselig. Vanligvis sender jeg et datasett videre til neste funksjon, for å gjøre noe med datasettet. Det er slik tidyverse-funksjonene funker. Noen ganger sender jeg datasettet til en funksjon som ikke forventer et datasett, og som ikke funker med tidyselect. F.eks. slik vi så i (med-pipe?).

# Dette funker ikke
mtcars %>% sum(wt)

# Dette funker
sum(mtcars$wt)

# Eller dette
mtcars %>% sum(.$wt)

12.5 Glemmer å bruke hermetegn / bruker hermetegn når vi ikke trenger hermetegn

Her varierer det nok ut ifra hvor god man er på å forstå strukturer. Jeg gjør denne feilen stadig. Har ikke noe bedre råd enn å alltid prøve begge veier. Det er så klart smart å finne ut av hvorfor man noen ganger bruker hermetegn rundt noe og andre ganger ikke. Essensielt handler det om: Når du bruker hermetegn rundt noe viser du at det er en tekststreng. Når du ikke bruker hermetegn rundt tekst viser du at et er et objekt. Da må objektet finnes i miljøet for at det skal kunne tas i bruk. tidyverse kompliserer dette litt ved at de lar oss henvise til f.eks. kolonnenavn som om de er objekter, f.eks. i:

library(tidyverse)

# OK
starwars %>% 
  select(name)

# Feilmelding
starwars[name]

# OK
starwars["name"]

# OK
starwars$name

# Også OK
starwars$"name"

Denne kompliseringa godtar vi, for det er så mange fordeler med at tidyverse lar oss henvise direkte til kolonner i datasett som om de var objekter.

12.6 Har brukt feil skråstrek

Skjer oftest på maskiner med Windows som operativsystem og når du leser eller skriver filer. Husk at vi i R må bruke /, ikke \. Se mer om dette i sec-slash.

12.7 Forveksler = og ==

== brukes når du skal sammenlikne to betingelser. = brukes enten til assignment hvis du ikke bruker <-, eller i argumenter. Eksempel:

trondelag %>% 
  filter(kommune == "Trondheim")

befolkning %>% 
  mutate(er_tronder = if_else("skinnvest" == TRUE & "bart" == TRUE, 
                           "tronder", 
                           "ikke_tronder"))

12.8 Tegnkode

Tegnkoding er dessverre noe besværlig. Det er flere ting som kan skje her:

  • Fila vi laster inn har en spesifikk tegnkode og vi må definere denne når vi laster inn
  • R eller Rstudio sin standardtegnkode er ikke den vi vil ha.
  • R eller Rstudio skifte uforvarende tegnkode uten at vi veit hvorfor.

Jeg tror noe av dette skyldes bugs i R og Rstudio, for endringsloggen har nevnt at de har fiksa problemer knytta til character encoding.

Se sec-tegnkoding for mer om dette.

Ellers er min erfaring at det ofte hjelper å restarte R-sesjonen dersom filene du laster inn plutselig mangler æ, ø og å når de tidligere hadde dem. I arbeidet med SSBs API opplevde jeg at filer som tidligere blei lasta inn med norske bokstaver rett som det var dukka opp med andre tegn istedenfor. Her fant jeg aldri ut hva som forårsaka det, men det funka alltid å restarte R-sesjonen. Kanskje var det noen pakker som når de blei lasta inn overskreiv noe annet. Dette gir oss en R-aforisme:

Det er bedre å fikse et problem enn å forstå problemet.

12.9 Jeg har prøvd alt, men ingenting løser problemet mitt

Her er en generell sti du kan gå ned når du skal løse et problem i R:

  1. Restart R-sesjonen
  2. Restart Rstudio
  3. Restart datamaskina
  4. Oppdater R (valgfri, noen gang skummelt)
  5. Oppdater Rstudio
  6. Spør en kollega
  7. Spør på StackOverflow eller CrossValidated (husk å gi det et reproduserbart eksempel!)