Kapitel 2 Grunder i R

2.1 Introduktion

R är ett så kallat open-source programmeringsspråk. Open-source betyder att programmet är gratis att ladda ner och använda, samt att vem som helst har möjlighet att skapa egna, skräddarsydda metoder eller analyser som enkelt kan delas med omvärlden. R har varit tillgängligt för vem som helst att ladda ner och använda under mer än 20 års tid vilket innebär att många har utvecklat och bidragit till språket.

R kännetecknas av sina paket med funktioner som vi kan använda för att genomföra operationer. Vi kan se på funktionerna som olika verktyg ämnade att lösa specifika problem, till exempel om vi vill slå in en spik i en bräda kan vi använda en hammare, och paketen som olika verktygslådor fokuserade på att genomföra en viss form utav arbete. Eftersom R är ett s.k. open-source program, kan vem som helst skapa funktioner och paket för allmänheten och ibland finns det ett behov av att ladda ner nya paket (köpa in nya verktygslådor) för att genomföra en viss sorts analys. När vi installerar R för första gången får vi tillgång till en stor mängd olika paket, men vi har möjligheten att utöka dessa väldigt enkelt.

Viktigt!
När vi programmerar i R, sparas objekt som vi skapar i datorns arbetsminne (RAM-minne). Arbetsminnet kan vi säga motsvarar ett korttidsminne, vilket innebär att vi har ett mindre utrymme att arbeta med och information endast är där temporärt. Under en
session
(från när vi startar R tills vi stänger ner det) kan vi spara objekt som kan användas senare men dessa objekt kommer rensas när vi stänger ner programmet. Nästa gång vi startar upp programmet kommer vi inte kunna se de objekt som vi skapat i en tidigare session. Om vi vill använda objekt mellan sessioner kan vi spara ner information till datorns hårddisk, eller dess långtidsminne, på några olika sätt.

Det finns flertalet gränssnitt som hjälper till att programmera i R, men vi rekommenderar att använda RStudio. Detta visuella gränssnitt medför att vi inte behöver programmera med en kommandotolk. För att installera R och RStudio kan du följa instruktionerna här. Detta underlag är skapad med R version 4.2.1 (2022-06-23 ucrt).

2.1.1 Starta RStudio

När vi startar RStudio för första gången, delas programmet in i tre olika fönster. Vi rekommenderar att alltid börja med att öppna eller skapa ett dokument där kod sparas (även kallad ett R Script), genom File -> New file -> R Script eller kortkommandot Ctrl/Command + Shift + N. När detta dokument öppnas, delas RStudio in i fyra olika fönster. Ett R Script har ändelsen .R men är i grunden en textfil och kan öppnas i alla enkla texthanterare, t.ex. Notepad, om vi vill redigera koden utanför R eller RStudio.

2.1.1.1 Kort genomgång av RStudio

När ett R Script skapats innehåller nu det övre vänstra fönstret denna fil. Här kan vi skriva kod som sedan sparas om vi sparar dokumentet. Det rekommenderas starkt att alltid skriva kod i ett dokument för att ha möjligheten att återanvända och redigera koden på ett lätt sätt genom att öppna filen.

Det nedre vänstra fönstret innehåller en konsol. Här visas all kod som vi kör och tillhörande utskrifter och vi kan också skriva kod direkt i konsollen. Skillnaden är att vi inte sparar denna kod någonstans och det är mycket svårare att återanvända och redigera kod i detta fönster.

I det nedre högra fönstret kan vi se filer från datorn, visualiseringar som skapas med kod, få en översikt av de paket som vi har tillgängliga, samt få hjälp om olika funktioner i deras dokumentation. Paket i R har inbyggda hjälpfiler som kan hjälpa oss att förstå vad en funktion kan göra, vad som krävs för att använda funktionen, och vad funktionen producerar för resultat.

Det övre högra fönstret innehåller en översikt av alla objekt som vi skapar under en session och som R har i korttidsminnet. Objekten som vi ser i RStudios Environment kan vi klicka på för att antingen få mer detaljer om objektet eller exempelvis öppna datamaterial.

Dessa fönster kommer vi återkomma till senare i underlaget.

2.2 Grundläggande programmering i R

R är ett kraftfullt språk som kan genomföra väldigt komplexa och avancerade beräkningar. Innan vi kommer dit måste vi första börja med grunderna i R och en utav de vanligaste användningsområdena för R är att använda språket som en vanlig miniräknare.

I detta underlag kommer kodexempel (ljus bakgrund) visas som du kan kopiera till din egna dator. En knapp finns överst i det högra hörnet som kopierar allt innehåll i kodblocket. Från exemplena visas också utskrifter (mörk bakgrund) från koden som vi i RStudio ser i konsollen.

# Exempelkod som kan kopieras med en knapp i det övra högra hörnet.
## [1] "Utskrift från koder."

På vissa ställen i underlaget kommer ett interaktivt kodfönster visas där du kan testa att köra kod utan att ha tillgång till R och RStudio. Vi rekommenderar dig att sakta börja med att bekanta dig med RStudio och dess gränssnitt men om du vill testa kod direkt kan denna applikation användas.

2.2.1 Enkel kodning

Till att börja med kan vi använda matematiska operatorer såsom +, -, *, och /.

## Addition
2 + 3
## [1] 5
## Subtraktion
5 - 2
## [1] 3
## Multiplikation
4 * 5
## [1] 20
## Division
20 / 4
## [1] 5

Kommentarer i koden

I ovanstående kodexempel ser vi också något speciellt. Om du kopierar all text från ett block, kommer R endast köra den andra raden. En rad som börjar med # kommer R läsa av som en kommentar och inte R-kod som ska köras. Detta medför att vi kan kommentera kod som vi skriver vilket har många fördelar.

Dels kan vi i anslutning till specifika bitar kod själva beskriva vad koden gör och vad för resultat som vi förväntar oss att få. Det är väldigt lätt att man i ett stort R Script tappar bort sig själv, eller när man öppnar scriptet vid nästa session har glömt bort vad det är koden gör för något. Med kommentarer kan vi lättare komma ihåg vad de olika delarna gör, men framförallt också ge scriptet till någon annan som med kommentarerna kan följa vad det är som händer. Försök att få in en rutin att kommentera kod som du skriver redan från början!

2.2.2 Objekt och dess typer

I tidigare exempel kommer svaret på beräkningarna endast skrivas ut i konsollen, men om vi hade varit intresserade av att spara ner informationen behöver vi säga till R att göra det. Vi kan spara resultat av en operation till ett objekt med hjälp av <- eller =. När vi vill tilldela ett värde till ett objekt är det praxis att använda <- och vi kan skriva detta som en kombination av symbole, < och -. Vi kan läsa det som ‘’ett värde tilldelas till ett objekt i pilens riktning’’.

Vi kan döpa objekt relativt fritt men vi måste förhålla oss till ett par begränsningar:

  • ett objektnamn kan inte börja med en siffa, 9tal <- 9
  • ett objektnamn kan inte innehålla mellanslag, ett tal <- 2

Istället kan vi använda siffror och andra symboler inuti namnet, tal9, och använda symboler likt _ istället för mellanslag, ett_tal.

Det sistnämnda bör vi dock undvika och istället använda ett system kallad camelCase. Detta sätt att namnge objekt medför att vi tar bort alla mellanslag, slår ihop orden, och använder stor bokstav för att urskilja enskilda delar, ettTal.

## Summan av 2 + 3 tilldelas till ett objekt, döpt till a
a <- 2 + 3

## Vi kan använda en högerriktad pil, men detta är inte praxis
2 + 3 -> a

Vi kan nu använda a i senare delar av vår kod och R kommer veta att objektet innehåller summan av 2 + 3.

2.2.2.1 Typer

Det förekommer olika typer av objekt. En fördel med R är att vi i majoriteten av fallen inte behöver säga till R vilken typ ett objekt är, R kan läsa av kontexten relativt bra. Till exempel kommer objektet a ur exemplet ovan vara numeriskt (mer specifikt typen numeric). Vi kan kontrollera detta genom funktionen class().

class(a)
## [1] "numeric"

Utöver numeriska typer finns även:

  • textsträng (character): "hej", "Anna",
  • logisk (logical): TRUE eller FALSE,

samt två specialfall av siffertyper:

  • heltal (integer), ett specialfall av numeriskt när det bara förekommer heltal: 2L där L anger till R att objektet ska vara av typen integer,
  • komplex (complex) innehållande komplexa tal

Vanligtvis räcker det med att använda numeric, character och logical-typer.

## Siffror anges bara som de är
valfrittNummer <- 3

## För att man ska ange text måste de omfattas av " " för att R ska läsa de som text
valfriText <- "Hello world!"

## Om något är sant 
test <- TRUE

Med hjälp av dessa objekt kan vi använda dess värden senare.

# a är summan av 2 + 3, och valfrittNummer har värdet 3
a + valfrittNummer
## [1] 8
Viktigt!
Lägg märke till att om vi genomför någon matematisk beräkning på ett sparat objekt, till exempel
a + 3
så kommer objektet a fortfarande ha samma värde som när vi skapade det. Vi ser enbart resultatet av beräkningen i konsollen och måste tilldela värdet på nytt om vi vill spara det. R uppdaterar inte ett objekt såvida vi inte ''skriver över'' det.

I praktiken använder sig R utav ytterligare ett specialfall för textsträngar, Factor. Ett Factorobjekt är en blandning av en siffra och text i och med att värdena som R använder sig av i lagring och bearbetning av objektet är siffror, men dessa siffror representerar text. Detta är ett exempel på kodning av data, där det finns en nyckel någonstans sparad som beskriver att ett värde egentligen har en annan verklig betydelse.

2.2.3 Datastrukturer

Vi kan också ange flera värden på lite olika sätt i R. Dessa kan innehålla information av samma typ, men vissa strukturer tillåter en blandning av typer med vissa begränsningar. Datastrukturer är som namnet antyder ett sätt för oss att strukturera information för att lättare kunna läsa och använda det.

2.2.3.1 Vektorer

Låt oss säga att vi har en massa kläder som ligger kaotiskt utspritt i ett rum. För att strukturera dessa kan vi exempelvis ta alla sockar och lägga dem i en låda. Lådan innehåller därmed en grupp av liknande saker, som i R motsvarar en vektor.

En vektor måste innehålla värden av samma typ, siffror, text, eller logiska värden. För att skapa en vektor använder vi funktionen c(), där varje element som vi vill lägga till i vektorn separeras med ett kommatecken.

## En vektor med numeriska värden
A <- c(3, 5, 3, 7)

B <- c(1, 3, 2, 4)

## En vektor med textstränger
ord <- c("Apelsin", "Banan", "Citron")

## Skriver ut respektive vektor
A
## [1] 3 5 3 7
B
## [1] 1 3 2 4
ord
## [1] "Apelsin" "Banan"   "Citron"

Vektor A och B har fyra element och vektor ord har tre element, alla av samma typ. Om vi vill titta specifikt på ett element kan vi använda indexering. En vektor har bara en dimension vilket innebär att indexfunktionen [] endast behöver ett värde.

Viktigt!
R börjar räkna från 1 när det kommer till index. Detta skiljer sig från andra programmeringsspråk som oftast börjar på 0.
# Plockar ut det fjärde elementet ur vektorn A
A[4]
## [1] 7
# Plockar ut det andra elementet ur vektorn ord
ord[2]
## [1] "Banan"

2.2.3.2 Matriser

Låt oss anta att vi har två vektorer med lika många element. Vi kan slå ihop dessa till en matris genom matrix(). En matris måste också innehålla värden av samma typ, vi kan alltså inte kombinera en numerisk vektor med en textvektor.

## En matris med värdena från vektor A och B där vi anger att vi har 2 kolumner
matris <- matrix(c(A,B), ncol = 2)

## Skriver ut matrisen
matris
##      [,1] [,2]
## [1,]    3    1
## [2,]    5    3
## [3,]    3    2
## [4,]    7    4

Vi ser nu i marginalerna (raderna och kolumnerna) att R använder två värden i indexet för detta objekt och det är för att en matris har två dimensioner. Vi kan med hjälp av detta index både plocka ut enskilda element eller enskilda rader/kolumner där ordningen på indexvärdet spelar roll då R använder sig utav [rad,kolumn].

## Plockar ut den andra kolumnen ur matris
matris[,2]
## [1] 1 3 2 4
## Plockar ut elementet från den andra raden och första kolumnen
matris[2,1]
## [1] 5
## Plockar ut elementet från den första raden och andra kolumnen
matris[1,2]
## [1] 1

2.2.3.3 Lista

Att bara lägga alla strumpor i en låda, t-shirts i en annan låda, byxor i en tredje låda osv. skulle medföra att vi har lite mindre kaos i rummet, men lådorna riskerar bli ostrukturerade om de blir för många. Vi kan samla ihop dessa lådor i en byrålåda istället för att öka strukturen ytterligare.

Ett flexibelt sätt att organisera alla vektorer är en lista. Listans element kan vara av olika typer eller längd, och du kan till och med ha en lista inuti en lista. Följande exempel är en lista med fyra olika objekt.

lista <- list(A, B, ord, matris)

lista
## [[1]]
## [1] 3 5 3 7
## 
## [[2]]
## [1] 1 3 2 4
## 
## [[3]]
## [1] "Apelsin" "Banan"   "Citron" 
## 
## [[4]]
##      [,1] [,2]
## [1,]    3    1
## [2,]    5    3
## [3,]    3    2
## [4,]    7    4

För att plocka ut ett element från listan behöver vi använda ytterligare en form av indexering. Vi behöver först ta oss in i en utav lådorna för att indexera den som vanligt, och det gör vi genom [[element]].

## Plockar ut det fjärde elementet ur vektorn A, listans första element
lista[[1]][4]
## [1] 7
## Plockar ut elementet från den andra raden och första kolumnen i listans fjärde element
lista[[4]][2,1]
## [1] 5

2.2.3.4 Data frame

Ett specialfall av en lista är en data frame och denna struktur använder vi frekvent inom statistiken. En data frame innehåller vektorer av samma längd men de olika vektorerna kan vara av olika typ. Vi kan säga att det är en blanding av en matris och en lista. Vanligtvis döper vi de kolumner (vektorer) som vi lägger till när vi skapar en data frame (NAMN = OBJEKT), men om vi av någon anledning inte gör det kommer kolumnerna få standardnamn såsom X1 och X2.

## Skapar en data frame med hjälp av funktionen data.frame()
data.frame(Var1 = A, Var2 = B)
##   Var1 Var2
## 1    3    1
## 2    5    3
## 3    3    2
## 4    7    4

När vi samlar in data inom statistik brukar vi ställa upp informationen med samma struktur som en data frame, där varje rad är en observerad enhet och varje kolumn är en variabel som vi gör mätningar på. Varje enskilda cell blir då enhetens uppmätta värde på den angivna variabeln, till exempel halten kväveoxid i Vänern. Detta kallar vi ofta för rådata-format.

## Skapar data
student <- 
  data.frame(
    namn = c("Anna", "Oscar", "Jakob", "Noor"),
    längd = c(158, 164, 180, 174),
    utbildning = c("Biologi", "Biologi", "Matematik", "Statistik")
  )

## Skriver ut data
student
##    namn längd utbildning
## 1  Anna   158    Biologi
## 2 Oscar   164    Biologi
## 3 Jakob   180  Matematik
## 4  Noor   174  Statistik

Vi kan utifrån denna data frame till exempel läsa att den första studenten Anna är 158 cm lång och studerar Biologi.

Om vi är intresserade av en specifik variabel ur denna data frame kan vi återigen indexera med hjälp av [] men det vanligaste är att istället använda $.

## Tar ut variabeln utbildning ur data frame student
student$utbildning
## [1] "Biologi"   "Biologi"   "Matematik" "Statistik"
## Gör samma indexering med hjälp av []
student[,3]
## [1] "Biologi"   "Biologi"   "Matematik" "Statistik"
## Gör återigen samma men använder namnet på variabeln
student[, "utbildning"]
## [1] "Biologi"   "Biologi"   "Matematik" "Statistik"

2.3 Olika former av stöd

Det kommer bli väldigt jobbigt om vi alltid måste skapa data för hand eller beräkna summor som a + b + c + .... Användandet av en programvara ska underlätta de statistiska beräkningarna och i den andan följer här några kapitel om hur Rs olika funktioner kan hjälpa till.

2.3.1 Arbetsmappar

När vi arbetar med R kommer vi ofta vilja ladda in datamaterial, spara ner utskrifter eller diagram, eller på annat sätt interagera med hårddisken på datorn. För att underlätta detta kan vi ange en arbetsmapp (working directory). En arbetsmapp är ett sätt för oss att snabbt och enkelt ge information till R att den ska arbeta med information från en specifik del av datorns hårddisk. Till exempel kan vi ha filer med data inuti denna mapp som R enkelt kan importera, och om vi sparar vårt R Script, kommer det sparas i denna mapp om vi inte säger något annat.

För att hitta sökvägen till mappen på din dator som du vill ange som Rs arbetsmapp, kan du öppna upp mappen i ditt operativssystems filhanterare. Du kan följa lämplig instruktion för just ditt operativsystem:

Kopiera denna sökväg och använd sedan funktionen setwd() för att R ska spara mappen i arbetsminnet. Notera att alla \ måste bytas ut med antingen \\ eller / för att R ska kunna läsa av sökvägen korrekt. Exempelvis kan det se ut så här:

## Anger en arbetsmapp på datorn med alla filer som ska användas 
setwd("C:/Users/MIN ANVÄNDARE/MAPPENS NAMN")

2.3.2 Paket

När vi startar RStudio kommer vissa paket redan vara laddade, motsvarande att vi plockat fram verktygslådan till vår arbetsbänk, men vi kan ibland vara intresserade av funktioner vars paket inte blivit laddade. Om du inte har verktygslådan bredvid dig kommer det bli svårt att använda något av verktygen.

Vi kan ladda upp ett paket till arbetsminnet med hjälp av library() eller require(), där namnet på paketet anges inuti parenteserna.

## Laddar paketet dplyr och dess tillhörande funktioner
require(dplyr)

Om du har en ny installation av R på datorn måste du ibland installera paketen först, det vill säga ladda ner paketets information från internet. Som tur är finns det en funktion för detta också, nämligen install.packages(). Skillnaden här är att namnet på paketet måste anges inom citationstecken "PAKET" istället för bara namnet som vi gjorde i require(). Om du en gång redan installerat paketet till din version av R behöver du inte installera paketetet för varje ny session utan kan direkt ladda genom library() eller require().

## Om paketen inte finns på datorn måste de installeras. KÖRS ENDAST EN GÅNG!
install.packages("ggplot2")
install.packages("RColorBrewer")

## Laddar paketen innehållande de funktioner som vi vill använda
require(ggplot2)
require(RColorBrewer)

2.3.3 Funktion

Termen funktion har använts frekvent tidigare och kan behöva förtydligas. En funktion är en operation, oftast flera rader kod, som inte visas direkt i ett script. Vi kan använda redan inbyggda funktioner från olika paket eller skapa en egen funktion. Vi kommer i detta underlag fokusera på att använda redan skapade funktioner. För att använda en funktion behöver vi veta namnet på funktionen och eventuella argument som funktionen behöver. Argumentens värden anges med = till skillnad från “vanlig” kodning där <- anges för att tilldela värden.

funktion(argument1 = värde1, argument2 = värde2)

En funktion börjar med en ( och slutar men en ). Detta betyder att man kan skriva en funktion på både en eller flera rader för att exempelvis lättare kunna läsa av argumenten som användas. Notera att R dock måste ha någon form utav indikation att funktionen fortsätter, t.ex. ett , för att ange att flera argument tillkommer eller ett + för att koppla ihop flera funktioner, likt som kommer presenteras nedan för ggplot2-paketet.

## Skapar en vektor 

vektor <- 
  c(
    2,
    3,
    4,
    5,
    6
  )

Detta kodexempel är formaterat annorlunda än tidigare men R läser av den likväl. Vi använder att R automatiskt fortsätter läsa nästa rad om den inte anser att raden fått en avslutning.

  • <- behöver ett värde att tilldela men eftersom det inte anges något värde fortsätter R leta vid nästa rad.
  • Funktionen c får inget avslutande ) så R fortsätter leta vid nästa rad.
  • Varje , separerar element i vektorn, men eftersom det inte anges något ytterligare värde fortsätter R leta vid nästa rad.
  • Det är först när inget ytterligare element läggs till, inget , vid näst sista raden, och funktionen stängs med ) som R är nöjd och inte letar vidare på efterföljande rader.

2.3.4 Ladda in material

För att kunna arbeta med datamaterial som du samlat in från någon annanstans används någon av read.___()-funktionerna. Det vanligaste sättet att göra det är genom att skapa en kommaseparerad fil (csv) via exempelvis Excel och sedan importera den till R via read.csv2(). Se till att kolumn- och decimalseparatorn anges enligt det format som filen har med sep =, och dec =. Ett tips är att öppna .csv-filen i Notepad++ eller annan enkel ordbehandlare för att se vilka symboler som används.

## Laddar in datamaterial
bil <- read.csv2("data_om_bilar.csv", dec = ".")
elev <- read.csv2("data_om_elever.csv", dec = ".")

2.3.5 Hjälpdokumentation

Att alltid komma ihåg vad R kan göra, vilka funktioner som finns, vilka argument som de behöver med mera, är omöjligt. Som tur är finns många resurser att hjälpa oss, inte minst den interna dokumentationen.

Genom att använda ? och ett funktionsnamn letar R upp den tillhörande hjälpdokumentationen för funktionen som innehåller en detaljerad beskrivning av funktionens syfte, hur man använder den, vilka argument som finns och vad respektive styr, mer djupgående detaljer om funktionen och dess resultat, vad som funktionen skapar (dess resultat), ytterligare referenser, och allra sist exempel när funktionen används som man kan ta inspiration från.

?c

Det finns även mycket resurser på internet (detta underlag kan ses som en sådan resurs) som kan hjälpa till att förstå vad och hur man ska programmera.