Översätt provresultat till betyg i R
Apr 9, 2020
Filip Wästberg
4 minute read

Jag har länge varit imponerad av David Stavegård och hans #torsdagstips i Excel där han med konkreta exempel visar hur man löser verkliga databearbetningsproblem med Excel.

Jag har tagit mig friheten att översatta några av dessa #torsdagstips till hur jag skulle lösa dem i programmeringsspråket R.

I det här torsdagstipset har vi Excel-fil med provresultat från en klass och vi vill göra om resultaten till betyg. I Excel använder David funktionen ifs(). I R använder vi funktionen case_when() från paketet dplyr.

Det här problemet kanske låter banalt, men för mig var det här en av de svårare sakerna att göra när jag började programmera i R. Men så är det, det som känns otroligt enkelt idag var svårt igår.

Vi vet att provresultatet ska leda till följande betyg:

  • A >= 95
  • B >= 85
  • C >= 75
  • D >= 65
  • E >= 55
  • F > 54

Vi kan börja med att generera en slumpmässig fil med provresultat. Tack vara Peter Dahlgren på Stockholm universitet, som lagt upp en fil med svenska namn, kan vi generera 30 svenska kill- och tjejnamn utan att först behöva skriva dem.

Jag har skapat en enkel funktion för det här som heter skapa_klass() som skapar ett fiktivt dataset med provresultat för \(n\) antal elever. Är du nyfiken kan du läsa den nedan, annars är det bara att hoppa över.

skapa_klass <- function(antal_elever = 30){
    män <- read_csv("https://raw.githubusercontent.com/peterdalle/svensktext/master/namn/mansnamn.csv", col_names = FALSE, locale = locale(encoding = "Latin1"))
    kvinnor <- read_csv("https://raw.githubusercontent.com/peterdalle/svensktext/master/namn/kvinnonamn.csv", col_names = FALSE, locale = locale(encoding = "Latin1"))
    
    alla_namn <- bind_rows(män, kvinnor) %>% 
        rename(namn = X1)
    
    klass <- tibble(
        namn = sample(alla_namn$namn, 30, replace = TRUE),
        provresultat = sample(c(40:100), 30, replace = TRUE))
    
    klass
}

Vi kan börja med att skapa en klass på 30 elever.

Hur kan vi göra om det här till betyg?

library(tidyverse)
klass1 <- skapa_klass(antal_elever = 30)

klass1
## # A tibble: 30 x 2
##    namn      provresultat
##    <chr>            <int>
##  1 Hakon               76
##  2 Zejnep              79
##  3 Belal               93
##  4 Fathi               79
##  5 Haxhere             95
##  6 Milania             87
##  7 Katharina           84
##  8 Hermon              53
##  9 Fariborz            57
## 10 Setayesh            43
## # … with 20 more rows

Det enklaste sättet att göra om provresultateten till betyg i R är genom funktionen case_when() som vi använder i mutate(). Det här gäller så klart inte bara provresultat utan du kan sätta upp vilka typer av villkor du vill, och de behöver inte bara vara numeriska.

klass1 <- klass1 %>% 
    mutate(betyg = case_when(
        provresultat >= 95 ~ "A",
        provresultat >= 85 ~ "B",
        provresultat >= 75 ~ "C",
        provresultat >= 65 ~ "D",
        provresultat >= 55 ~ "E",
        provresultat < 55 ~ "F",
    ))

klass1
## # A tibble: 30 x 3
##    namn      provresultat betyg
##    <chr>            <int> <chr>
##  1 Hakon               76 C    
##  2 Zejnep              79 C    
##  3 Belal               93 B    
##  4 Fathi               79 C    
##  5 Haxhere             95 A    
##  6 Milania             87 B    
##  7 Katharina           84 C    
##  8 Hermon              53 F    
##  9 Fariborz            57 E    
## 10 Setayesh            43 F    
## # … with 20 more rows

Lätt som en plätt!

Varför göra det här i R?

Genom att skriva det här som ett skript kan du enkelt byta ut din datafil och kör om resultatet och på så sätt spara tid.

För att illustrera det här har jag skapa 24 olika klasser där vi ska göra samma sak för alla klasser. Hade vi gjort det i Excel hade det inneburit mycket klippa och klistra, och här vill vi verkligen inte gör fel.

Istället kan vi skapa en enkel funktion som tar en fil med data och översätter provresultat till betyg och sedan skriver resultatet till en Excel-fil.

library(openxlsx)
library(readxl)
översätt_provresultat <- function(sökväg){
    data <- read_excel(sökväg) %>% ## Skulle det vara en Excel-fil kan 
        mutate(betyg = case_when(
        provresultat >= 95 ~ "A",
        provresultat >= 85 ~ "B",
        provresultat >= 75 ~ "C",
        provresultat >= 65 ~ "D",
        provresultat >= 55 ~ "E",
        provresultat < 55 ~ "F",
    ))
    write.xlsx(data, paste0("provresultat/klass-", unique(data$klass), "-provresultat.xlsx"))
}

sökvägar <- paste0("data/", list.files("data"))

map(sökvägar, översätt_provresultat)

Nu har vi sparat flera timmar av tråkigt arbete och kan istället ta en kaffe med kollegorna!