Sesjon 6: Beskrivende statistikk
R-workshop 30. og 31. august, OsloMet
Det første jeg gjør når jeg har et nytt datasett, er å utforske dataene med beskrivende statistikk. Da er hovedfokuset at R-kodingen skal gå fort og jeg skal få oversikt. Base-R har mange praktiske funksjoner for dette.
Når jeg skal presentere resultatene mine – også de beskrivende – bruker jeg mer tid og flere pakker; inkludert piper fra tidyverse.
Nå skal vi:
- lage beskrivende statistikk: tall og figurer i base-R
- ta vårt første dykk i dplyr (pakke i tidyverse)
- lage fine tabeller
Pakker vi bruker:
dplyr
(evt.tidyverse
)stargazer
kableExtra
Beskrivende statistikk
Vi begynner med å sjekke ut dataene.
View(df)
dim(df); names(df)
De første seks observasjonene.
head(df)
Univariate fordelinger
Funksjoner fra base-R er perfekte for kjapp utforskning av dataene, men ganske kjapt vil tidyverse gi stordriftsfordeler.
Kategoriske variabler
Frekvenstabell Absolutt fordeling
table(df$Parti)
Relativ fordeling
prop.table(table(df$Parti))
I prosent
prop.table(table(df$Parti)) * 100
Rund av til uten desimaler.
round(prop.table(table(df$Parti)) * 100)
Lagre resultatet
<- prop.table(table(df$Parti)) * 100 tabell1
Søylediagram
barplot(tabell1)
Din tur!
Bruk litt tid på å leke med denne.
- legg en tittel og aksenavn på grafikken med:
main=
,xlab=
,ylab=
. - kan du sortere søylene fra lav til høy? Da sorterer du verdiene i
tabellen med
order
+ indeksering. - endre fargene på søylene med tilleggsargumentet
col=
Sjekk fargenavnene her: http://www.stat.columbia.edu/~tzheng/files/Rcolor.pdf - sjekk ut
horiz = TRUE
oglas = 2
. Hva kan du gjøre?
Kakediagram
pie(tabell1)
Kontinuerlige variabler
Numeriske beskrivelser
Når variablene er kontinuerlige, kan vi bruke kvartiler, gjennomsnitt…
Her ser jeg på respondentenes innvandrerskepsis.
summary(df$Skepsis)
stargazer
gir deg et automatisk sammendrag av datasett
med kontinuerlige variabler. Default utupt er i latex, så presiser at du
vil ha “text”.
library(stargazer)
##
## Please cite as:
## Hlavac, Marek (2022). stargazer: Well-Formatted Regression and Summary Statistics Tables.
## R package version 5.2.3. https://CRAN.R-project.org/package=stargazer
stargazer(df[,c("Skepsis", "KultSkepsis")],
type = "text")
Grafisk utforskning
hist(df$Skepsis)
Bivariate sammenhenger
To kagetoriske variabler
table(df$Innvandrer, df$Prekaritet)
Lagre resultatet
<- table(df[,c("Innvandrer", "Prekaritet")]) krysstabell
Legg til marginalfordelingen
addmargins(krysstabell)
Relativ fordeling Vil du ha andeler i stedet?
prop.table(krysstabell)
Regn ut fordelingen kolonnevis
prop.table(krysstabell, margin = 1)
Søylediagram Nå blir søylene lagt oppå hverandre.
barplot(krysstabell)
… ved siden av
barplot(krysstabell,
beside = TRUE,
names.arg = c("Prekaer", "Ikke-prekaer"))
Bytte sammenlikning? Da kan du transposere tabellen
krysstabellt(krysstabell)
barplot(t(krysstabell),
beside = TRUE)
### To kontinuerlige variabler
Numeriske beskrivelser
Pearsons R Bruk cor()
for bivariate
korrelasjoner. NA håndteres med å fortelle hvilke observasjoner vi
ønsker å bruke.
cor(df$Skepsis,
$KultSkepsis,
dfuse = "pairwise.complete.obs")
Signifikansteste korrelasjonen
cor.test(df$Skepsis,
$KultSkepsis) df
Korrelasjonsmatrise
cor(df[,c("Skepsis", "KultSkepsis", "Inntekt", "Utdanning")],
use = "pairwise.complete.obs")
Grafisk framstilling
plot(df$Skepsis,
$KultSkepsis) df
plot(df[,c("Skepsis", "KultSkepsis", "Inntekt", "Utdanning")])
Hva er tidyverse/dplyr?
Til nå har vi jobbet i base-R. Det er den eldste og mest stabile
dialekten i R. Det er fullt mulig å gjøre de fleste operasjoner i
base-R, men de siste årene har en ny dialekt oppstått basert på
tidyverse
. Tidy-universet består av et sett med R-pakker
som alle følger omtrent samme språklige prinsipper. Denne dialekten har
flere fordeler:
datarydding: Som navnet indikerer, er pakken spesielt godt egnet for å rydde i data.
dplyr
er en pakke som bygger på tidyverse. Den har gjort mye av datatilretteleggingen svært rask. R har tradisjonelt vært lite tilpasset til store datasett, hvor alle funksjoner som krever å gå gjennom lange variabler har vært svært trege. I tillegg gjør pakken det mulig å kommunisere med databaser (SQL).intuitiv: I tillegg til et eget vokabular (et sett med funksjoner), bygger pakken også på en annen type syntaks. Mange opplever at denne syntaksen ligger nærmere slik vi tenker og bygger opp en argumentasjon. Dermed kan kodene virke mer intuitive.
Det er en fordel å ha grunnleggende kunnskaper i begge dialekter. Dermed kan du jobbe deg rundt ethvert problem.
Før du bruker funksjoner fra tidyverse, må du hente pakken (eller en av pakkene som baserer seg på denne) ut av biblioteket og inn i arbeidsminnet ditt. Funksjonene og syntaksen befinner seg i pakken.
Vi skal basere oss på dplyr
-pakken som er en del av
tidy-universet. Vi begynner med å hente opp pakken fra biblioteket. Om
du ikke har installert den allerede, må du gjøre det først.
# install.packages("dplyr")
library(dplyr)
R følger opp med å informere oss om hvilke pakker som maskeres fra
arbeidsområdet vårt. For eksempel inneholder dplyr funksjonen
intersect()
som har en navnebror i base-R. Om vi bruker
funksjonsnavnet, er det dplyr sin funksjon vi nå vil få servert.
Eksempeldataene Her skal vi bruke en versjon av norske ESS (2014). Vi begynner med å laste in dataene og gi dem et navn vi liker.
library(laerdegR)
data(kap5)
<- kap5 df
Syntaks: Piper eller parenteser?
I base-R: parentes
I base-R kommuniserer du ved først å oppgi funksjonen du ønsker å bruke, så objektnavnet i parentes, samt argumenter/tilleggsargument separert med komma.
Her regner jeg gjennomsnittet til variabelen om innvandrerskepsis
blant ESS respondentene. Tilleggsargumentet na.rm = TRUE
adresserer problemet med at noen respondenter ikke har svart.
mean(df$Skepsis, na.rm = T)
For å gjøre koden mer lesbar, vil vi ofte skifte linje etter hvert komma.
mean(df$Skepsis,
na.rm = T)
I tidyverse: piper
I tidyverse bruker vi “piper” for å binde ulike argumenter sammen. Det gjør vi med “%>%” (prosent, større-enn, prosent). Vi kan bruke funksjoner fra base-R eller fra tidyverse sammen med pipene.
Vi oppgir objektet først, så funksjonen. Alle argumenter som ikke oppgir objektet, må oppist på “gammelt vis”. Vi indikerer hvor objektet skulle ha vært med “.”.
$Skepsis %>% mean(., na.rm = T) df
Med piper, er det ekstra ryddig å skifte linje for lesbarhet.
$Skepsis %>%
dfmean(., na.rm = T)
Flere operasjoner på samme objekt
Vi kan alltid bygge opp en sekvens koder. Dette skal foregå kronologist (første operasjon først). Vi kan gjøre det på tre måter:
- én operasjon av gangen. Vi kan gjøre hver operasjon for seg og lagre dem i egne objekter.
<- is.na(df$Skepsis)
er.na <- sum(er.na)
ant.na ant.na
Vi har ant.na
hull i variabelen.
- to operasjoner av gangen
- base-R: Vi kan legge parenteser i pareneteser. Den siste kommer først. Aller sist kommer objektet.
sum(is.na(df$Skepsis))
- tidyverse: Vi kan lage en pipe: Objektet først, så første operasjon, så operasjonen vi vil gjøre på resultatet av denne operasjonen.
$Skepsis %>%
dfis.na(.) %>%
sum()
Det finnes ingen regler for hva som er best. Du bestemmer!
Frekvenstabell
Kontinuerlig variabel
Funksjonen summarize
lar deg samle ulik statistikk for
en eller flere variabler i datasettet. Du begynner med å presisere
datasettet, så pipe, så summarize-funksjonen. Den vil da forstå at
variablene/objektene du refererer til finnes i datasettet
df
.
%>%
df summarize(gjennomsnitt = mean(Skepsis, na.rm = TRUE),
median = median(Skepsis, na.rm = TRUE))
Du kan også lage kvantiler:
%>%
df summarize("skepsis" = quantile(Skepsis, na.rm = TRUE),
"kulturell skepsis" = quantile(KultSkepsis, na.rm = TRUE)) %>%
t()
Her flipper jeg også tabellen (transposerer) med
t()
.
Kategorisk variabel
Vi kan telle gruppemedlemmer med tidyverse. Da grupperer vi dataene
etter en kategori med group_by()
, så ber vi om et
sammendrag summarize()
og presiserer at vi ønsker antallet
i hver gruppe n()
.
%>%
df group_by(Parti) %>%
summarize(n())
Vi kan bygge opp tabellen med flere sammendragstyper og runde av til to desimaler.
%>%
df summarize(antall = table(Parti),
andel = prop.table(antall),
prosent = prop.table(antall)*100) %>%
round(.,2)
Lagre tabellen
<- df %>%
frekvenstabell summarize(antall = table(Parti),
andel = prop.table(antall),
prosent = prop.table(antall)*100) %>%
round(.,2) %>%
#Skal du ha partinavnene, må du jobbe litt...
cbind(parti = unique(df$Parti[!is.na(df$Parti)]),
.)
Trivariat frekvenstabell
Bivariat tabell
%>%
df group_by(Prekaritet) %>%
summarize(skepsis = mean(Skepsis, na.rm = T),
kulturell_skepsis = mean(KultSkepsis, na.rm = T))
Trivariat tabell
%>%
df group_by(Innvandrer, Prekaritet) %>%
summarize(skepsis = mean(Skepsis, na.rm = T),
kulturell_skepsis = mean(KultSkepsis, na.rm = T))
## `summarise()` has grouped output by 'Innvandrer'. You can override using the
## `.groups` argument.
<- df %>%
trivariat group_by(Innvandrer, Prekaritet) %>%
summarize("Innvandrerskepsis" = mean(Skepsis, na.rm = T),
"Kulturell innvandrerskepsis" = mean(KultSkepsis, na.rm = T))
## `summarise()` has grouped output by 'Innvandrer'. You can override using the
## `.groups` argument.
Eksporter tabellen din
Du kan eksportere tabellen på flere måter:
Excel: Dette er et datasett, så du kan eksportere med
write.table()
og importere i Excel, for eksempel.LaTeX: Skriv tabellen ut med latex-kode ved hjelp av de samme tabellfunksjonene. Her er ofte
stargazer
-pakken fin (mer om det senere).HTML/Word: Du kan bruke tabellfunksjoner i R for å printe tabellen som html. Da kan du “copy-paste” til Word. Her er
knitr
ogkableExtra
gode pakker (mer om disse senere også).
**Eksporter tabellen med html* Vi kan eksportere tabellen som html og importere den inn i word. I prosessen kan vi legge til ny informasjon.
kableExtra
-pakkken (sammen med knitr
) har
fine funksjoner for dette. kbl()
er kjernefunksjonen. Den
krever en tabellel.
Jeg henter pakken inn fra biblioteket.
library(kableExtra)
?kbl
Her lager jeg en enkel tabell. Utputtet befinner seg i “Viwer” nederst til høyre.
kbl(x = trivariat)
Hvilke tilleggsargumenter finnes?
?kbl
Legg til tittel, for eksempel.
kbl(x = trivariat,
caption = "Sammenhengen mellom økonomisk usikkerhet og innvandringsskepsis.")
Nå kan jeg eksportere tabellen. Det gjør jeg med en ny funksjon:
save_kable()
. Da må jeg presisere filnavnet.
kbl(x = trivariat,
caption = "Sammenhengen mellom økonomisk usikkerhet og innvandringsskepsis.") %>%
save_kable("tabell.html")
Utskriften befinner seg i mappen hvor arbeidsretningen din er satt. Husker du ikke hvor? La oss sjekke?
getwd() #Min arbeidsretning ("get working directory")
Jeg kan til og med spørre R om hvilke filer som befinner seg der.
list.files()
Er filen min i listen?
any(list.files() == "tabell.html")
Åpne fila i nettlesern din og kopier/lim den inn i Word. Voilá!
Din tur
Fortsett med tabellen hvor du kontrollerer for
Innvandrer
ogPrekaritet
, men hvor du også presiserer hvor mange observasjoner du har i hver kategori. Dette gjør du isummarize
, med funksjonenn()
(uten noen andre argumenter).Lag en trivariat tabell hvor du kontrollerer for
Inntekt
istedet for innvandring.- blir den lang? Du kan bruke
print(n = 20)
i enden av kabelen din for å printe 20 observasjoner (osv.). - filtrer ut “NA” i prekaritet. Da bruker du
filter(!is.na(Prekaritet))
i kabelen før du grupperer.
- blir den lang? Du kan bruke
lag en html-tabell av resultatet med
kbl()
frakableExtra
.pimp tabellen med info fra hjelpesidene:
digits =
align =
Mitt forsøk på trivariat tabell
Fungerer ikke funksjonen din som den skal?
Når du henter ut en pakke fra biblioteket, vil du av og til få beskjed om at enkelte funksjoner overskygger (eller er “maskert”) funksjoner som allerede befant seg i arbeidsområdet ditt. Årsaken er at du av og til vil oppleve konflikter mellom ulike pakker. Derfor er det lurt å være bevisst på hvilke pakker du bruker til enhver tid og hvor funksjonene dinne hører hjemme. Ikke last inn et drøss med pakker uten å vite hvilke funksjoner du skal bruke.
Eksempelvis, har enkelte pakker definert ulike funksjoner med likt
navn. Ett eksempel er select()
som både befinner seg i
MASS
-pakken og i dplyr
-pakken. Om du ikke fikk
med deg denne beskjeden da du hentet ut den nye pakken, og kodene dine
ikke oppfører seg som de skal, bør du undersøke om dette er problemet.
En måte å gjøre dette på er å bruke hjelpesidene. Finner du at den samme
funksjonen befinner seg i to åpne pakker? Da har du to valg:
- spesifiser hvor funksjonen din kommer fra. Du kan alltid fortelle R at du ønsker å bruke en spesifikk funksjon fra en spesifikk pakke. Da trenger du faktisk ikke å laste inn hele biblioteket. Dette gjør du med to kolon.
Her forteller jeg R at jeg ønsker å bruke
select()
-funksjonen fra dplyr
.
:: select() dplyr
- du kan fjerne den ene pakken. Dette kan du gjøre ved å klikke deg
fram i RStudio eller med syntaks. Du kan enten klikke på fanen
“Packages” i vinduet nederst til høyre. Her finner du en liste over alle
pakkene i biblioteket ditt, med pakkene som er lastet inn i R huket av.
Huk vekk pakken du ikke ønsker. Eventuelt kan du bruke
detach( )
.
Her laster jeg først inn dplyr
, så fjerner jeg den
igjen.
library(dplyr)
detach("package:dplyr", unload = TRUE)