Skip to Tutorial Content

Mål og forberedelser

I denne delen skal vi jobbe videre med data i R. Vi skal også utføre regneoperasjoner, lære mer om klasser og målenivå. Videre skal vi lære å laste inn datasett og laste opp flere funksjoner (pakker). Vi skal også bli kjent med hvordan vi kan hente ut informasjon fra datasettet (som for eksempel skalaen på en variabel/vektor). Det blir også demonstrert hvordan du kan opprette én ny variabel i et datasett, samtidig som du lærer hvordan du kan velge variable fra et datasett, gi dem nye navn og lagre dem i et annet datasett. Til slutt skal du lære hvordan du visualiserer data.

Mål for arbeidsboken

I denne arbeidsboken skal du lære:

  • Å laste inn data og pakker.

  • Om pakken tidyverse.

  • Hvordan bruke pipe %>% og sette sammen funksjoner vha av denne.

  • Hvordan velge variable select() og endre navn med variable rename().

  • Å subsette data.

  • Om klasser og hvordan sjekke skalaen (svaralternativene) på en variabel vha koden levels().

  • Å utforske data vha følgende koder: summary(), str(), head() og tail().

  • Å lage tabeller vha table() og prop.table().

  • Hvordan filtrere ut data vha av filter().

  • Å lage tabeller med deskriptiv statistikk med stargazer().

Hente inn data

Når du skal gjennomføre en statistisk analyse så er som regel det første steget import og forberedelse av data. En styrke ved R er at det er mulig å importere mange ulike filformat, både fra en mappe på pcen din og fra en url på internett. Det er også mulig å ha flere datasett oppe i R samtidig. Dette dokumentet går gjennom import av .csv-filer, men vit at det finnes mange andre muligheter. Hvis du lurer på hvordan man skal laste inn en bestemt filtype og har glemt hvordan du gjør det så er dette veldig lett å finne svaret på internett.

I denne arbeidsboken skal vi jobbe med et datasett som er det man kaller en csv-fil. Datasettet er fra European Social Survey Round 9 (2018). European Social Survey er en spørreundersøkelse og datasettet du skal jobbe med i denne arbeidsboken inneholder svarene fra norske respondenter. Vi skal forenkle dette datasettet noe for oppgavene i denne arbeidsboken.

For å laste inn datasettet bruker vi koden read.csv(). Argumentet du putter i parantesen er enten et filnavn eller en URL. Mange datasett er fra internett og kan derfor lastes inn ved hjelp av en URL. Det ser slik ut:

ess <- read.csv("https://raw.githubusercontent.com/louisabo/Data-For-Teaching/main/utvalg_NO_ESS_2018.csv") 

I kodesnutten over så oppretter vi først et objekt som heter ess. Deretter kommer koden read.csv() og inne i parentesen følger enten en filbane som viser hvor på maskinen din csv-filen er lokalisert eller URL-en dersom du laster det inn direkte fra internett. Merk at du må ha anførselstegn rundt filbanen/URL-en.

Variabler i ESS

Vi skal jobbe med et utvalg av variablene i datasettet ess som vi skal plukke ut under. Datasettet ess består av 1406 observasjoner og 9 variable. Hver observasjonsenhet er en person i Norge. Utvalget er trukket vha sannsynlighetsutvelging og utvalget er derfor representativt for den norske befolkning. Dataene ble utgitt i 2018.

Datasettet består av følgende variabler:

  • nwspol: viser hvor mange minutter en respondent bruker på nyheter om dagen. Verdiene går fra 0-1109 minutter.

  • polintr: sier noe om hvor politisk interessert hver respondent er. Verdiene er på ordinalnivå med fire kategorier.

  • vote: denne variabelen oppgir om respondenten stemte ved forrige stortingsvalg.

  • yrbrn: sier hvilket årstall respondenten er født i.

  • trstlgl: sier hvorhvidt respondenter har tillit til det juridiske systemet i Norge (0 ingen tillit, 10 høy tillit). -trstplc: sier hvorhvidt respondenten har tillit til landents politikere (0 ingen tillit, 10 høy tillit).

  • trstprt: sier hvorhvidt respondenten har tillit til landets politiske partier.

  • trstep: sier hvorhvidt respondenter har tillit til Europaparlamentet.

Klasser og målenivå

R operer med seks grunnleggende typer data: numeric, integer, logical, complex og character. (I tillegg finnes det raw data og complex tall, men disse er for det meste ikke nødvendig å bruke, så vi går ikke inn på disse typene her.)

  • Numeric: tall som inneholder et desimal, men de kan også være heltall.
  • Integer: hele tall uten desimaler.
  • Logical: data som enten tar verdien TRUE eller FALSE, i tillegg er representerer NA missingverdier.
  • Character: data som representerer string-verdier.
  • Factor: spesiell type character string som har tilleggsegenskaper (som nivåer elle en rekkefølge).

Undersøke klasse

Vanligvis kan R differensiere mellom forskjellige klasser av data basert på egenskapene til dataene eller konteksten de er i. Det er allikevel viktig å huske på at R ikke kan lese tankene dine. Derfor er det viktig å sjekke at hvilke klasse R leser data som og om dette stemmer overens med hvilken klasse du tenker at dataene burde bli behandlet som. Dette er spesielt viktig å huske på hvis man vil vite en variabels målenivå, ettersom målenivået ikke nødvendigvis stemmer overens med klassen variabelen har i R.

For å undersøke hvilken klasse et objekt har kan man bruke class()-funksjonen. Outputen forteller deg hvilken klasse R leser dataene objektet inneholder som.

num <- 5.6
class(num)
## [1] "numeric"
char <- "tekst"
class(char)
## [1] "character"
logi <- TRUE 
class(logi)
## [1] "logical"

Alternativt kan man bruke en logisk test for å sjekke om et objekt er en bestemt klasse med is.[klasse]()-funksjonene. Denne funksjonen returnerer enten TRUE eller FALSE, som svar på den logiske testen.

is.numeric(num)
## [1] TRUE
is.numeric(char)
## [1] FALSE
is.character(char)
## [1] TRUE
is.logical(logi)
## [1] TRUE

Nominal

Når variabler er nominale så kan egenskapen deles i to eller flere gjensidig utelukkende kategorier. I ESS datasettet vårt er variabelen vote nominal: man har enten stemt, ikke stemt eller så er man ikke berettiget til å stemme.

Vi kan sjekke hvilken klasse variabelen har ved hjelp av class(). Denne koden tar samme argument som summary() hvor du skriver navnet på datasettet, dollartegn og variabel navn. Er du usikker på hvordan dette gjøres så gå tilbake til det vi gikk gjennom i første arbeidsbok.

Finn klassen på variabelen vote i datasettet datasett.
class(ess$vote)

Her får vi opp klassen “factor”. Klassen i R samsvarer altså med variabelens målenivå. Vi kan bruke levels() til å sjekke hvilke nivåer eller kategorier som er registrert. Koden tar samme argument som class(), altså levels(ess$variabel)

Bruk levels() til å finne kategoriene til variabelen vote. Datasettet heter fortsatt ess.
levels(ess$vote)

Her ser du at du får opp “skalaen” på variabelen, eller svar alternativene. Det betyr at respondenter har blitt kategorisert etter om de har stemt (“Yes”), ikke stemt (“No”) eller om de ikke har rett til å stemme pga alder eller statsborgerskapsstatus (“Not eligible to vote”).

Ordinalnivå

Når variabler er på ordinalnivå kan de deles i to eller flere gjensidig utelukkende kategorier som kan rangeres, men vi kan ikke si noe om avstanden mellom verdiene og en enhets økning har ikke samme betydning. I ESS datasettet vårt så er variabelen interest et eksempel på en variabel på ordinalnivå.

Bruk koden class() for å finne klassen til variabelen polintr (politisk interesse). Datasettet heter fortsatt ess.

class(ess$polintr)
Bruk koden levels() for å se hvilke kategorier variabelen har i R.
levels(ess$polintr)

Her ser du at vi har kategorier fra: “Hardly interested”, “Not at all interested”, “Quite interested” til “Very interested”. Vi kan ikke si hva avstanden mellom for eksempel “Quite interested” og “Very interested” er, men vi kan si at “Very interested” er ‘mer interesse’ for politikk enn “Not at all interested”.

Numerisk

Numeriske variabler kan rangeres, har samme avstand mellom alle verdier og en enhets økning betyr alltid det samme. Her er det altså snakk om variabler med faktiske tallverdier. I ESS datasettet vårt så er variabelen nwspol numerisk, som indikerer hvor mye tid en respondent bruker på nyheter.

Bruk koden class() for å finne klassen til variabelen nwspol (tid brukt på nyheter). Datasettet heter fortsatt ess.
class(ess$nwspol)

Her får vi klassen integer. Om en variabel er integer eller numeric betyr ofte i praksis det samme. Forskjellen er at integer-variabler er heltall og numeric-variabler kan ha desimaler.

Når du skal gjøre dine egne analyser så må du være obs og alltid sjekke at klassen på en variabel du skal bruke stemmer overens med målenivået. I mange datasett får kategoriske og ordinale variabler ofte tall istedenfor kategorinavn som verdier og lastes inn som klassen numeric. Dette gjør at kategoriske variabler kan fremstå som at de har et høyere målenivå enn de faktisk har i R. Derfor er det alltid viktig å også sjekke kodeboken for å se hvilket målenivå variabelen faktisk har. Det kommer ikke til å stå “denne variabelen har kategorisk målenivå” så dere må gjøre en selvstendig vurdering basert på hvilke verdier variabelen har.

Deskriptiv statistikk

Det er variabelens målenivå som avgjør hvilken deskriptiv statistikk som er fornuftig.

Kategoriske variabler

R har ingen innebygd funksjon for å finne modusverdien/typetall. Ved å søke på internett så finner du fort mange ulike funksjoner du kan bruke, men for å gjøre det enkelt bruker vi bare table(). Funksjonen table() gir oss en frekvenstabell, mens prop.table gjør om frekvenstabellen til andeler. ESS datasettet mangler data for noen observasjoner. Ved å ta med useNA = "always" i table() så får vi også denne informasjonen i tabellen:

# Her printer jeg en vanlig tabell som inkluderer NA
table(datasett$vote, useNA = "always")
## 
##                   No Not eligible to vote                  Yes 
##                  124                  125                 1156 
##                 <NA> 
##                    1
# Her printer jeg en tabell som er gjort om til andeler
prop.table(table(datasett$vote))
## 
##                   No Not eligible to vote                  Yes 
##           0.08825623           0.08896797           0.82277580
# Her printer jeg en tabell som er gjort om til andeler, men som inkluderer NA
prop.table(table(datasett$vote, useNA = "always"))
## 
##                   No Not eligible to vote                  Yes 
##         0.0881934566         0.0889046942         0.8221906117 
##                 <NA> 
##         0.0007112376

Funksjonen table() og prop.table() gir også en god oversikt over variablene som sådan. Legg merke til at når vi bruker prop.table() så er neste argument table() og deretter datasett$variebelnavn.

Legg merke til at du kan legge til gange 100 på slutten av parantesen så får du andelen i prosent.

prop.table(table(datasett$vote))*100
## 
##                   No Not eligible to vote                  Yes 
##             8.825623             8.896797            82.277580

Her ser vi at ca 82% av respondentene stemte ved forrige valg og at 8.9% av respondentene ikke har stemmerett, mens 8.8% av respondentene ikke stemte ved forrige valg.

Bruk table() for å få oversikt over fordelingen på variablen interest i datasettet datasett. Ikke legg til useNA argumentet.
table(datasett$interest)
Bruk prop.table() til å få en oversikt over variabelen interest i datasettet datasett. prop.table() gjør om frekvenstabellen fra table() til andeler.
prop.table(table(datasett$interest))
Gjør om frekvenstabellen med andeler til prosent.
prop.table(table(datasett$interest))*100
# Her må du gange med 100 på slutten av tabellen

Numeriske variabler

For å få oversikt over kontiuerlige variable kan du bruke funksjonen summary() som tidligere vist. Andre relevante er blant annet sd() som gir deg standardavviket til en variabel. Her er noen eksempler:

  • min() finner minimumsverdien (det laveste antall minutter brukt på nyheter). na.rm = TRUE forteller R at missing skal droppes i beregningen:
min(datasett$news, na.rm = TRUE)
## [1] 0
  • max() finner maksimumsverdien (det høyeste antall minutter brukt på nyheter). na.rm = TRUE forteller R at missing skal droppes i beregningen:
max(datasett$news, na.rm = TRUE)
## [1] 1109
  • mean() finner gjennomsnittlig antall minutter brukt på nyheter. na.rm = TRUE forteller R at missing skal droppes i beregningen:
mean(datasett$news, na.rm = TRUE)
## [1] 104.1006
  • median() finner median. na.rm = TRUE forteller R at missing skal droppes i beregningen:
median(datasett$news, na.rm = TRUE)
## [1] 60
  • sd() finner standardavviket. na.rm = TRUE forteller R at missing skal droppes i beregningen:
sd(datasett$news, na.rm = TRUE)
## [1] 155.5571
  • var finner varians. na.rm = TRUE forteller R at missing skal droppes i beregningen:
var(datasett$news, na.rm = TRUE)
## [1] 24198.01
  • quantile finner kvantilverdiene. na.rm = TRUE forteller R at missing skal droppes i beregningen:
quantile(datasett$news, na.rm = TRUE)
##   0%  25%  50%  75% 100% 
##    0   30   60  120 1109
  • summary finner forskjellig deskriptiv statistikk for en variabel:
summary(datasett$news)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##     0.0    30.0    60.0   104.1   120.0  1109.0      34

Legg merke til at hvert argument har tilleggsargumentet na.rm = TRUE, som fjerner manglende verdier dersom noen av observasjonene mangler informasjon på variabelen. Hvis en variabel har manglende verdier og man ber R om å finne gjennomsnittet på variabelen, så vil ikke R kunne regne gjennomsnittet på denne variabelen med mindre du spesifiserer at den skal ignorere observasjoner med manglende informasjon med dette argumentet. Les mer om manglende verdier/missing data og na.rm-argumentet i Arbeidsbok 4: Statistisk analyse.

Bruk mean() til å finne gjennomsnittet til variabelen age i datasettet datasett. Husk at du må legge til et argument som sier hvordan du skal håndtere missingverdier (NA).
mean(datasett$age, na.rm=TRUE)
# Husk at du må legge til datasett$variabel, etterfulgt av komma og deretter na.rm=TRUE
Bruk sd() til å finne standardavviket til variabelen age i datasettet datasett. Husk at du må legge til et argument som sier hvordan du skal håndtere missingverdier (NA).
sd(datasett$age, na.rm=TRUE)
# Husk at du må legge til datasett$variabel, etterfulgt av komma og deretter na.rm=TRUE

Base R og pakker

R-pakker er utvidelser til programmeringsspråket R. De inneholder kode, data, og dokumentasjon som gir oss tilgang til funksjoner som løser ulike problemer og gjør koding enklere. Første gang man skal bruke en pakke må man installere den med install.packages(). Etter at vi har installert pakken så må vi “hente den fra biblioteket” med library() for å fortelle R at vi ønsker å bruke pakken. Vi installerer bare pakken en gang, men vi må laste den inn fra biblioteket hver gang vi åpner R på nytt og ønsker å bruke pakken.

tidyverse

tidyverse er et sett med pakker som gjør databehandling mye enklere, som bl.a. inneholder pakkene dplyr og ggplot2:

  • dplyr inneholder mange funksjoner som er veldig nyttige når vi skal jobbe med data.
  • ggplot2 er en pakke vi bruker mye når vi skal visualisere data.

Når man starter et nytt script er det som regel nødvendig å hente tidyverse, ettersom de fleste regelmessig bruker veldig mange funksjoner fra denne gruppen med pakker.

# Installerer tidyverse
install.packages("tidyverse")

# Henter tidyverse fra bibliotekt
library(tidyverse)

Merk at pakkenavnet ikke står i anførselstegn når vi bruker library(). Anførselstegn rundt pakkenavnet er bare nødvendig når vi bruker install.packages().

tidyverse, dplyr og base R

For mange av operasjonen man kan gjøre med funksjonene som ligger i tidyverse, finnes det tilsvarende måter å gjøre det samme med det som kalles base R. Base R er den generiske programvaren som inneholder kodespråket til R. Hvilke funksjoner man bruker i scriptene sine er for det meste opp til egen preferanse, og mange bruker funksjoner fra både tidyverse og base R i samme script.

I arbeidsbøkene “Visualisering av data med ggplot” og “Visualisering av data med base R” viser vi hvordan man kan lage tilsvarende grafer med henholdvis ggplot og base R. En av de andre pakken man bruker mye fra tidyverse er dplyr. Tabellen under viser noen vanlige operasjoner og hvordan man kan gjøre det samme med dplyr og base R. For å lese mer om dette kan dere se på denne siden.

dplyr base R
filter(df, x) df[which(x), , drop = FALSE], subset()
mutate(df, z = x + y) df$z <- df$x + df$y, transform()
rename(df, y = x) names(df)[names(df) == "x"] <- "y"
select(df, x, y) df[c("x", "y")], subset()

Indeksering av data

For å få ut bestemte verdier i et datasett kan vi indeksere med klammeparanteser [ ]. I klammeparantesene spesifiserer vi posisjonen(e) til verdien(e) vi ønsker å få ut. Hvis objektet vi jobber med er en en-dimensjonal vektor trenger vi bare å spesifisere hvilken nummer verdien er i rekken. Dersom vi jobber med et datasett, må vi spesifisere kolonne og rad.

# Henter ut den andre verdien i den tredje kolonnen: 

ess[2,3]
## [1] "Yes"
# Får samme outputen som over med følgende kode: 
ess$vote[3]
## [1] "Yes"

Vi kan også hente ut verdier fra flere rader eller kolonner ved hjelp av klammeparanteser. Vi kan gjøre dette for sekvensere ved å spesifere disse som vektorer:

# Henter ut de verdiene for rader 5-10 for kolonner 1-3: 

ess[5:10, 1:3]

Eller vi for ikke-sekvensielle rader og kolonner, kan vi bruke c()-funksjonen:

# Henter ut de verdiene for rader 5, 10 og 12 for kolonner 1 og 3: 

ess[c(5,10,12), c(1,3)]

Det kan også hende at vi ønsker å hente ut enten alle radene for spesifikke kolonner eller alle kolonnene for spesifikke rader i et datasett.

# Henter ut alle radene for kolonner 1-3: 

ess[, 1:3]
# Henter ut alle kolonnene for rader 5, 7, 13, 21: 

ess[c(5, 7, 13, 21), ]

Dersom vi ønsker å utelukke spesifikke rader eller kolonner, kan vi gjøre dette ved å bruke samme framgangsmåte som vi har brukt så langt, men bare legge til negative fortegn.

# Henter ut alle radene bortsett fra 5-20 og alle kolonnene bortsett fra kolonner 2 og 4: 

ess[-5:-20, -c(2, 4)]

Logiske indekser

Vi kan også bruke indeksering til å velge ut data basert på ulike logiske tester. Vanlige logiske tester å bruke er bl.a. følgende:

# Lik eller større enn 1960
ess[datasett$yrbrn >= 1960] 

# Større enn 1960
ess[ess$yrbrn > 1960] 
  
# Lik eller mindre enn 1960 
ess[ess$yrbrn <= 1960] 

# Mindre enn 1960 
ess[ess$yrbrn < 1960] 

# Lik 1960
ess[ess$yrbrn == 1960] 

# Ulik 1960
ess[ess$yrbrn != 1960] 

Å indeksere ved hjelp av logiske tester er nyttig hvis vi bare vil ha med oss observasjoner som møter spesifikke kriterier, f.eks. at vi indekserer basert på minutter brukt på nyheter hver dag.

# Henter ut alle respondenter som bruker mer enn 60 minutter daglig på nyheter: 
ess[ess$nwspol > 60, ]

Vi kan også bruke logiske tester til å indeksere basert på verdien til en character string eller et factor level. Under vil vi hente ut alle respondenter som oppgir at de har stemt ved forrige valg.

# Henter ut alle respondenter som oppgir å ha stemt ved forrige valg ("Yes"): 
ess[ess$vote == "Yes", ]

For mer komplekse logiske tester, kan vi kombinere de logiske testene med Boolske uttrykk. Her kan vi bruke & (OG) for å si at vi vil hente verdier som møter kriterier. Hvis vi verdier bare må møte et av flere kriterier, kan vi bruke | (ELLER).

# Henter ut alle respondenter som oppgir å ha stemt ved forrige valg ("Yes") OG som bruker mer enn 60 minutter dalig på nyheter : 

ess[ess$vote == "Yes" & ess$nwspol > 60, ]
Hent ut alle respondenter som ENTEN oppgir å ha stemt (vote) ved forrige valg (“Yes”) ELLER som bruker mer enn 60 minutter dalig på nyheter (nwspol.
ess[ess$vote == "Yes" | ess$nwspol > 60, ]

Organisering av data

Vi har lastet inn datasettet vi skal jobbe med fra ESS. Nå skal vi forberede dataene. Ofte følger det med en kodebok når man laster ned data. Kodeboken inneholder informasjon om variablenes navn, hvilket målenivå de har og hva observasjonsenheten er. Kodeboken til ESS finner dere her. ESS inneholder mange landspesifikke variabler og kodeboken er derfor veldig lang.

Du trenger ikke å slå opp i kodeboken for å løse oppgavene i denne arbeidsboken, men når du skal kjøre dine egne analyser er det viktig å se nøye på kodeboken før du begynner å jobbe med dataene.

Større datasett som ESS inneholder ofte mange flere variabler enn de vi ønsker å bruke i våre analyser. Variablene kan også ha navn som er vanskelig å tolke og huske. For å finne ut hvilken informasjon variablene inneholder så kan vi slå opp i kodeboken. Vi har allerede valgt noen variabler fra datasettet som du skal jobbe med og slått opp hva variabelnavnene betyr, så du trenger ikke å åpne kodeboken for å løse oppgavene i denne arbeidsboken.

Nå skal vi fjerne de variablene vi ikke skal bruke og gi variablene navn som er lette å forstå og huske. For å gjøre dette skal vi benytte oss av funksjoner i pakken dplyr. Først bruker vi select() til å velge de variablene vi vil beholde og så bruker vi rename() til å endre navnene. Vi bruker en pipe %>% mellom funksjonene, som tar outputen til et utsagn og gjør det til inputen til det neste utsagnet. Pipen kan sees på som ordet “så”.

rename()-funksjonen

I neste kodebit ser du et eksempel hvordan man kan gi variabler navn som er lette å forstå og huske. Ved hjelp av rename-funksjonen skal vi endre på navnene til variablene nwspol, polintr, vote og yrbrn.

ess <- ess %>% 
rename(news = nwspol, # Endrer navn på nwspol til news
        interest = polintr)
Endre på navnet til variabelen yrbrn i datasettet ess til year_born med rename()-funksjonen.
ess <- ess %>% 
ess <- ess %>% rename(year_born = yrbrn) # Endrer navn på yrbrn til year_born

Subsetting av data

Å subsette betyr å bruke det som ligger inne i et datasett til å opprette et nytt et. Når vi skal subsette så kan vi bruke funksjoner i pakken dplyr. Med dplyr bruker vi %>%for å binde sammen ulike operasjoner vi vil utføre på et datasett. %>% kalles ofte for en pipe og når man bruker %>% kalles det piping. Det er en effektiv og ryddig måte å kode på.

select()-funksjonen

Den første funksjonen vi skal bruke er select(). Denne brukes til å velge hvilke variabler du vil ha med i det nye datasettet ditt. Her velger jeg å ta med variablene news, interest, vote, year_born fra ess i det nye datasettet datasett.

# Subsetter datasett med select()
datasett <- ess %>% select(news, interest, vote, year_born)
# Sjekker hvilke variabler som ligger i det nye datasettet med summary()-funksjonen
summary(datasett)
Bruk select() og %>% til å lage et datasett som heter datasett_subset. datasett_subset skal inneholde variablene interest og vote fra datasettet datasett.
datasett_subset <- datasett %>% select(interest, vote)
# Husk å skrive navnet på den nye datasettet før <-, og det gamle datasettet etterfulgt av en pipe (\%\>\%) før du skriver inn spesifiseringen av det nye datasettet vha select() etter.
# I select() må variablene være i riktig rekkefølge for å få riktig svar, altså (interest, valg).

filter()-funksjonen

Du kan også bruke filter()-funksjonen til å sette krav som enhetene i datasettet må møte for å bli tatt med i det nye datasettet. Under har jeg brukt funksjonen til å bare ta med respondenter som har stemt og som leser mer nyheter enn gjennomsnittet.

# Subsetter datasettet med filter()
datasett_filter <- datasett %>% filter(vote == "Yes", 
                       news > mean(news))
# Sjekker det nye datasettet med summary()-funksjonen
summary(datasett_filter)
##       news                      interest                   vote     year_born  
##  Min.   : NA   Hardly interested    :0   No                  :0   Min.   : NA  
##  1st Qu.: NA   Not at all interested:0   Not eligible to vote:0   1st Qu.: NA  
##  Median : NA   Quite interested     :0   Yes                 :0   Median : NA  
##  Mean   :NaN   Very interested      :0                            Mean   :NaN  
##  3rd Qu.: NA                                                      3rd Qu.: NA  
##  Max.   : NA                                                      Max.   : NA  
##       age     
##  Min.   : NA  
##  1st Qu.: NA  
##  Median : NA  
##  Mean   :NaN  
##  3rd Qu.: NA  
##  Max.   : NA

filter() brukes med spesifikke logiske symboler og tar minst to argumenter, et data-argument og et variabel-argument, eventuelt flere variabel-argument dersom du ønsker å filtrere ut observasjoner på flere variabler.

Oversikt over logiske operatorer:

Operator Betydning
== er lik
< mindre enn
> større enn
<= mindre eller lik
>= større eller lik
!= ikke lik
!x ikke x
| eller
& og

Et eksempel er at vi spør R om å filtrer ut respondenter som er født etter år 2000 med filter(>). Det som er viktig å huske på her er at vi må passe på at variabelene vi filtrer på er numeriske dersom vi oppgir f.eks tallverdier.

Et eksempel på hvordan bruke filter er som følger:

filter(datasett, year_born > 2000)

R vil her vise alle respondenter som er født etter år 2000. Vi kan for eksempel også filtrere ut alle som har svar at de stemte på følgende måte:

filter(datasett, vote == "Yes")

Koden følger argumentet data først som heter datasett og deretter variabelen vi ønsker å filtrere på. Vi kan også skrive koden på følgende måte:

datasett %>% 
filter(vote == "Yes")

Begge kodene gjør akkurat det samme. Jeg anbefaler alle til å jobbe med den nederste måten hvor man bruker %>% (eller en pipe som det heter). Koden gir en pipe inn i datasettet datasett og sier at inni dette datasettet så vil jeg filtrere ut alle respondenter som har stemt.

Bruk filter til å finne alle respondenter som er født i 1998 (year_born) i datasettet datasett.
datasett %>%
  filter(year_born == 1998)
# Husk å skrive navnet på datasettet også skriv `%>%` deretter bruker du filter(). Inni filter skriver du variabel og det du ønsker å filtrere ut.  

Ofte når vi bruker filter() vil vi telle observasjonene. I dette datasettet er det mange observasjoner. I R kan du bygge opp kode på følgende måte vha av %>% (eller piper).

datasett %>% 
  filter(year_born < 2000) %>% 
  count()

Når vi bruker count() etter filter vil R telle hvor mange observasjoner som blir filtrert ut på den variabelen du filtrer på.

Bruk filter til å finne alle respondenter som er født i 1970. Legg til count() for å telle hvor mange respondenter som er født i 1970.
datasett %>%
  filter(year_born == 1970) %>% 
  count()
# Husk å skrive navnet på datasettet også skriv `%>%` deretter bruker du filter(). Inni filter skriver du variabel og det du ønsker å filtrere ut. Husk at oppgaver spør etter ALLE repondenter som er født i 1970, da må du bruke to erlik-tegn. Deretter skriver du en `%>%` hvor legger til argumentet count().
Hvor mange av respondentene i datasettet bruker mer enn 40 minutter på nyheter daglig (news) i datasettet datasett?
datasett %>% 
  filter(news > 40) %>%
  count()
# Det som er vanskelig med denne oppgaven er å huske hvilken vei de logiske operatorene skal gå. Mer enn er > og mindre enn er <. Her er det lurt å videre også bare prøve seg frem, så sitter det til slutt. 

Subsetting med flere funksjoner samtidig

Subsetting kan også gjøres med flere funksjoner samtidig. Når du skal legge til en til funksjon legger du til en pipe og skriver funksjonen etter den. Det som er viktig å huske på her, er at R vil kjøre gjennom koden i den rekkefølgen du har skrevet den. Derfor er det viktig at du skriver funksjonene i riktig rekkefølge.

Her filtrerer vi først på respondenter som har stemt og som bruker mer tid på nyheter enn gjennomsnittet i datasettet datasett, før vi velger å bare ta med variablene news og year_born i det nye datasettet datasett_ny. Dersom vi hadde startet å velge news og year_born ville vi fått en feilmelding. Da ville ikke R kunne filtrere på vote, ettersom vi allerede ville ha fjernet denne variabelen fra datasettet.

# Subsetter datasettet med filter() og select()
datasett_ny <- datasett %>% filter(vote == "Yes", 
                       news > mean(news)) %>% 
                select(year_born, vote)

Lag et nytt datasett som heter datasett_ny. Bruk filter() kombinert med mean() for lage et datasett som bare inneholder observasjoner av respondenter som ikke har stemt (vote == “No”) som bruker mindre tid på nyheter enn gjennomsnittet (news. Til slutt skal du bruke select() til å velge variablene year_born og vote.

datasett_ny <- datasett %>% filter(vote == "No", 
                       news < mean(news)) %>% 
                       select(year_born, vote)
# Husk å skrive navnet på den nye datasettet før <-, og det gamle datasettet med spesifiseringen av det nye datasettet vha filter() og select() etter.
# Alle funksjonene og variablene må være i riktig rekkefølge for å få riktig svar.

Utforske data

Vi skal nå bli litt bedre kjent med dataene våre. Det er mange ulike måter å utforske datasett og variabler på. Vi har allerede sett på funksjonen summary(), men vi skal jobbe videre med str(), head() og tail().

Oversikt

For å få et deskriptivt sammendrag av et objekt kan vi bruke summary() eller str(). Begge disse kodene tar argumenter i form av et objekt (str(datasett)) eller et objekt og noe annet fra objektet (str(datasett$variabel)).

Bruk koden str() for å få en oversikt over datasettet vi jobber med. Datasettet heter fortsatt datasett.
str(datasett)

str() gjør at R printer litt informasjon om datasettet (antall observasjoner og variabler), sier hvilken klasse variablene har og viser noen av kategoriene til variablene.

Hvis man vil se de første eller siste radene i et datasett så kan man bruke henholdsvis head() og tail(). Disse tar samme argumenter som summary() og str().

Bruk koden head() til å se de første radene i datasettet.
head(datasett)
Bruk koden tail() til å se de siste radene i datasettet som heter datasett.
tail(datasett)

Som nevnt over kan alle disse funksjonene også brukes på enkeltvariabler. Da er argumentet f.eks tail(datanavn$variabelnavn).

Omkoding av variabler

Når vi omkoder variabler i et datasett, bør vi opprette en ny variabel. Dersom vi ikke gjør dette, erstatter vi informasjonen i den opprinnelige variabelen. Vi trenger informasjonen i den opprinnelige for å teste at omkodingen har fungert som vi ønsker. Det kan også skje at vi gjør en feil som vi ikke kan rette opp uten den opprinnelige variabelen (dette hender).

Først er det greit å få en oversikt over variabelene i datasettet og spesielt den vi ønske å kode om. Nyttige funksjoner å bruke til dette kan være summary(), head() og tail().

Bruk summary()-funksjonen for å få en bedre oversikt over datasettet datasett.
summary(datasett)

Matematisk omkoding

Først skal vi lære å kode om variablene ved å bruke matematiske omkoding. For å vise dette bruker vi variabelen year_born. Her kan vi lage en variabel som viser når respondentene ble født. Hvis respondentenes alder ble registrert i 2018, kan vi finne ut når de ble født ved å trekke alderen deres fra 2018

I neste kodebit legger vi til en ny variabel i datasettet. Dette gjøres ved å bruke opprette-objekt-pilen (<-). Deretter skriver du datasett etterfulgt av $ og hva du vil kalle den nye variabelen: datasett$variabel_navn. Vi skal kalle den nye variabelen age og legge den til i datasettet vårt som heter datasett.

Det er det som koden på venstre side av pilen betyr. Det jeg putter på høyreside av pilen er det variabelen består av. I R kan man utføre vanskelige regneoperasjoner med et par kodestrenger. Her skal vi trekke fra 2018 fra variabelen year_born (altså minus 2018 på hver rad i datasettet), slike at vi får alderen til alle respondentene.

Lag en ny variabel i datasettet datasett som heter age ved å trekke variabelen age fra 2018
datasett$age <- 2018-datasett$year_born
#  Husk å skrive navnet på den nye variabelen før <-, og så den matematiske omkodingen etter. 
# Matematisk omkoding 
2018 - datasett$year_born

I den forrige oppgaven får du beskjed om at omkodingen er blitt gjort riktig, men du ser dette ikke selv. For å sjekke dette på egenhånd kan vi bruke table()-funksjonen. Her sjekker vi om det stemmer at alder i 2018 (age) pluss året man ble født (year_born) er lik 2018 Dette er sant for alle 1374 respondenter, som indikeres ved at det står TRUE.

# Omkodingen fra forrige oppgave
datasett$age <- 2018 - datasett$year_born

# Sjekker med table() at omkodingen har blitt gjort riktig
table((datasett$age + datasett$year_born) == 2018)
## 
## TRUE 
## 1374

Vi kan også lage et plott med en linje som viser sammenhengen mellom variablene age og year_born.

# Plotter en linje med ggplot() og geom_smoot()
ggplot(datasett, aes(x = age, y = year_born)) + geom_smooth()
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'
## Warning: Removed 32 rows containing non-finite values (`stat_smooth()`).

Nå har vi opprettet en ny variabel i datasettet datasett som heter age. Vi skal lære mer om å opprette variable i senere arbeidsbøker.

Bruk koden summary() for å få en oversikt over den nye variabelen age.
summary(datasett$age)

Her får du igjen oversikt over den yngste respondenten og den eldste respondenten i antall år – altså alder og ikke basert på det året de ble født.

Husk at du kan bruke alle matematiske funksjoner når du lager variabler. Du kan dele (/), gange (*), plusse (+) og trekke fra (-).

Omkoding med ifelse()

Man kan også omkode variabler ved hjelp av funksjoner. En nyttig funksjon til omkoding er ifelse(). Med ifelse() så forteller du R hva du vil at de gamle verdiene i en variabel skal byttes ut med. Argumentene i funksjonen fungerer slik: ifelse(test, yes, no). Med andre ord, så lager man en test som verdier i variabelen enten oppfyller eller ikke. Verdiene som møter kravet til testen får en verdi (yes), og de som ikke møter kravet til testen får en annen verdi (no).

Her kan vi lage en variabel som skiller mellom respondentene som er 50 år eller eldre og de som er yngre enn 50 år. De som er 50 år og oppover skal få verdien 1 og de som er under 50 år skal få verdien 0.

# Omkoding med ifelse()
datasett$ny_age <- ifelse(datasett$age >= 50, 1, 0)

Her sjekker vi om vi har gjort omkodingen riktig med table(). Tabellen under er ganske uoversiktlig, men vi ser at alle under 50 år har fått verdien 0, og de 50 år og over har fått verdien 1.

# Sjekk av omkoding med table()
table(datasett$ny_age, datasett$age)
##    
##     15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
##   0 22 26 15 27 17 14 23 22 18 21 24 18 18 18 24 17 18 25 17 20 27 19 15 25 29
##   1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
##    
##     40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
##   0 20 21 23 15 24 20 34 30 32 25  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
##   1  0  0  0  0  0  0  0  0  0  0 25 19 23 30 31 23 24 26 21 23 18 23 22 15 20
##    
##     65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
##   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
##   1 27 21 13 18 15 13 23 15 16 23 15  9 10  6 10  7  7  1  1  2  1  6  2  1  1
##    
##     90
##   0  0
##   1  5

Bruk ifelse til å lage en ny variabel som heter omkodet_agei datasettet datasett, hvor alle som er 40 år og eldre får verdien 2 og alle som er under 40 år får verdien 1.

datasett$omkodet_age <- ifelse(datasett$age >= 40, 2, 1)
# Husk å skrive navnet på den nye variabelen før <-, og så omkodingen med ifelse() etter.  
# Husk at rekkfølgen i ifelse()-funksjonen er ifelse(logisk test, verdi hvis testen er sann, verdi hvis testen ikke er sann).
# Logisk test: 
ifelse(datasett$age >= 40, 2, 1)

I de forrige kodesnuttene har vi brukt verdiene fra variabelen i test-argumentet, men man kan også bruke andre funksjoner, f.eks. mean()-funksjonen. Her sier vi at vi vil at alle som er yngre enn gjennomsnittsalderen får verdien 0 og alle som er eldre enn gjennomsnittet får verdien 1.

# Omkoding med ifelse
datasett$mean_age <- ifelse(datasett$age < mean(datasett$age), 0, 1)

Bruk ifelse() til å legge til en ny variabel som heter median_age i datasettet datasett, hvor alle som er yngre enn median-alderen får verdien 0 og alle som er eldre får verdien 1.

datasett$median_age <- ifelse(datasett$age < median(datasett$age), 0, 1)
# Husk å skrive navnet på den nye variabelen før <-, og så omkodingen med ifelse() etter.  
# Husk at rekkfølgen i ifelse()-funksjonen er ifelse(logisk test, verdi hvis testen er sann, verdi hvis testen ikke er sann).
# Logisk test: 
ifelse(datasett$age < median(datasett$age), 0, 1)

Omkoding med ifelse() - dummyvariabel

Vi kan også bruke ifelse() til å kode om en variabel til en dummyvariabel. En dummyvariabel er en kategorisk variabel hvor alle enhetene får en av to mulige verdier. Som oftest bruker man verdiene 0 og 1 når man lager en dummyvariabel. Dummyvariabler indikerer at en bestemt ting stemmer eller ikke om en enhet, f.eks. om en respondent stemte (“Yes”) eller ikke ved stortingsvalget i 2017 (“No”).

Bruk ifelse() til å lage en ny variabel i datasettet datasett som heter dummy. Variabelen dummy skal ta veridien 1 om observasjonen har verdien “Yes” på variabelen voteog 0 ellers.

datasett$dummy <- ifelse(datasett$valg == "Yes", 1, 0)
# Husk å skrive navnet på den nye variabelen før <-, og så omkodingen med ifelse() etter.  
# Husk at rekkfølgen i ifelse()-funksjonen er ifelse(logisk test, verdi hvis testen er sann, verdi hvis testen ikke er sann).
# Husk å skrive "Stemt" i hermetegn. 
# logisk test: 
ifelse(datasett$valg == "Yes", 1, 0)

Tabell med deskriptiv statistikk

Det er mange ulike måter å lage tabeller til bruk i ulike former for skriftlig kommunikasjon. Denne seksjonen vil bare gjennomgå to funksjoner fra to pakker som kan brukes til dette, som et utgangspunkt for å lage tabeller. Her er det veldig mulig å finne flere måter å gjøre dette på, f.eks. gjennom å google seg frem.

stargazer()

For å lage en fin tabell med deskriptiv statistikk kan dere bruke funksjonen stargazer(). Denne funksjonen kommer vi også til å bruke senere i arbeidsbøkene når vi skal kjøre regresjonsanalyser (Arbeidsbok 5: Bivariat regresjonsanalyse og Arbeidsbok 6: Multivariat regresjonsanalyse).

Når vi bruker stargazer()-funksjonen, oppgir vi først hvilket objekt vi vil lage en tabell for og så hva slags format og informasjon vi vil at tabellen skal ha. Her kan man gjøre veldig mange tilpasninger (f.eks. endre på variabelnavnene) - for en fullstendig oversikt kjør koden ?stargazer eller søk etter stargazer i Help-fanen.

Dersom vi bruker stargazer()-funksjonen til å lage tabeller til en tekst, er det viktig at vi spesifiserer hva slags format vi ønsker at tabellen skal ha. Dette gjør vi i style-argumentet, som kan ta verdiene latex (default), html eller text. Skriver man i Latex eller Overleaf er det fint å bruke latex, ellers kan det være lurt å bruke html. Hvis man velger html som format, må man også spesifisere hvor man ønsker at tabellen skal lagres og hva filen skal hete.

Merk dere at når dere jobber i stargazer vil dere bare få output for variabler som er lagret som numeric.

# Eksempel på syntaks når man bare vil se output i Console
stargazer(objektnavn, type = "text")

# Eksempel på syntaks når man skal lagre en tabell i .html-format
stargazer(objektnavn, type = "html", out = "mappe/filnavn.html")
Bruk stargazer()-funksjonen til å lage en tabell med deskriptiv statistikk for datasettet datasett, hvor du viser output i “text”-format.
stargazer(datasett, type = "text")
Bruk stargazer()-funksjonen til å lage en tabell med deskriptiv statistikk for datasettet datasett, hvor du lagrer outputen med filnavn “data_tabell.html” i “.html”-format.
stargazer(datasett, type = "html", out = "data_tabell.html")

stargazer og objekt-typer

stargazer()-funksjonen tar bare data.frame-objekter. Datasett kan komme i forskjellige typer format, og de lastes ikke automatisk inn i R som data.frame-objekter. F.eks., når man laster in .dta-filer med haven::read_dta() lastes disse inn som tibble-objekter, dermed blir dette et problem hvis man ønsker å bruke stargazer()-funksjonen. Derfor må man først gjøre om datasett-objekter som ikke er data.frame-objekter med as.data.frame()-funksjonen, før man bruker stargazer()-funksjonen.

# Henter nødvendige pakker 
library(haven)
library(stargazer)

# Laster inn .dta-fil med read_dta()
df <- read_dta("datasett.dta") 

# Sjekker klassen med class()
class(df)

# Gjør om objektet til et data.frame-objekt
df <- as.data.frame(df)

# Lager tabell med deskriptiv statistikk 
stargazer(df, type = "text")

sumtable()

Et annet alternative er å bruke sumtable()-funksjonen fra vtable-pakken. Med denne funksjonen kan man enten lagre tabellen som en .html-fil eller bare se den i Viewer-fanen. Hvis man bruker sumtable()-funksjonen får man også med informasjon om variabler som ikke er numeric i tabellen.

Her spesifiserer du hvor du vil ha outputen med out-argumentet. Vi skal se på alternativene viewer (default) og htmlreturn. Dersom du velger htmlreturn, må du også velge hvor filen skal lagres og hva den skal hete med file-argumentet. Når du lagrer tabellen i .html-format, kan du åpne den i nettleser ved å klikke på filnavnet i Files-fanen og velge View in Web Browser. Deretter kan du kopiere eller lagre tabellen dit du ønsker. Alternativt, hvis du bare åpner tabellen i Viewer kan du eksportere den direkte derfra, ved å trykke på Export-knappen.

I likhet med stargazer()-funksjonen kan man også gjøre tilpasninger med sumtable(), men denne funksjonen er ikke like fleksibel som stargazer(). Søk etter sumtable i Help-fanen eller skriv ?sumtable for å få mer informasjon om tilpasningene man kan gjøre gjennom argumentene funksjonen tar.

Bruk sumtable()-funksjonen til å lage en tabell med deskriptiv statistikk for datasettet datasett, uten å spesifisere noen av argumentene.
sumtable(datasett)
Bruk sumtable()-funksjonen til å lage en tabell med deskriptiv statistikk for datasettet datasett, hvor du lagrer outputen med filnavn “data_tabell_kategorisk.html” i “htmlreturn”-format. MERK: Her vil outputen være hmtl-kode, men hvis du kjører samme kode med et datasett i RStudio vil du også kunne åpne tabellen som beskrevet over.
sumtable(datasett, out = "htmlreturn", file = "data_tabell_kategorisk.html")

Arbeidsbok 2: Data i R

Eli Sofie Baltzersen, Louisa Boulaziz, Bjørn Høyland, Eric Nilsen, Lise Rødland

29/01/2024