library(foreign)library(readxl)library(RISEkbmRasch) # devtools::install_github("pgmj/RISEkbmRasch")library(grateful) # devtools::install_github("Pakillo/grateful")library(ggrepel)library(car)library(kableExtra)library(readxl)library(tidyverse)library(eRm)library(mirt)library(psych)library(ggplot2)library(psychotree)library(matrixStats)library(reshape)library(knitr)library(cowplot)library(formattable) library(glue)library(hexbin)library(skimr)### some commands exist in multiple packages, here we define preferred ones that are frequently usedselect <- dplyr::selectcount <- dplyr::countrecode <- car::recoderename <- dplyr::rename# file paths will need to have "../" added at the beginning to be able to render document# get itemlabelsitemlabels <-read_excel("../data/Itemlabels.xlsx") %>%filter(str_detect(itemnr, pattern ="mp")) %>%select(!Dimension)spssDatafil <-"../data/2023-04-26 Prevent OSA-enkat.sav"# read SurveyMonkey datadf <-read.spss(spssDatafil, to.data.frame =TRUE) %>%select(starts_with("q0007"),q0001,q0002,q0003,q0004) %>%rename(Kön = q0002, Ålder = q0001,Bransch = q0003,Hemarbete = q0004)# SPSS format provides itemlabels too, we can save them in a dataframespssLabels <- df %>%attr('variable.labels') %>%as.data.frame()dif.kön <- df$Köndif.ålder <- df$Ålderdif.bransch <- df$Branschdif.hemarbete <- df$Hemarbetedf <- df %>%select(starts_with("q0007"))names(df) <- itemlabels$itemnr
4.1 Items
Code
itemlabels %>%kbl_rise(width =60)
itemnr
item
mp1
Jag har de resurser som behövs för att kunna utföra mina arbetsuppgifter.
mp2
Jag kan prioritera i vilken ordning mina arbetsuppgifter ska utföras.
mp3
Jag har tillräckligt med befogenheter för att kunna utföra mina arbetsuppgifter.
mp4
Jag kan påverka beslut som rör mina arbetsuppgifter.
RIdemographics(dif.ålder,"Ålder") # kanske även fixa en figur?
Ålder
n
Percent
18-29
22
3.8
30-39
103
17.8
40-49
175
30.2
50-59
215
37.1
60+
64
11.1
Code
RIdemographics(dif.bransch,"Bransch")
Bransch
n
Percent
Kontorsarbete (oavsett bransch)
284
49.1
Industri
26
4.5
Hotell, restaurang, service
8
1.4
Handel
16
2.8
Skola, utbildning
67
11.6
Vård, omsorg
99
17.1
Byggverksamhet
7
1.2
Annat
71
12.3
Code
RIdemographics(dif.hemarbete,"Antal dagar med arbete hemifrån")
Antal dagar med arbete hemifrån
n
Percent
En dag
136
23.5
Två dagar
105
18.1
Tre dagar
35
6.0
Fyra dagar
10
1.7
Fem dagar
2
0.3
Jag arbetar aldrig eller sällan hemifrån
291
50.3
4.2.1 Svarsbortfall items
Vi filtrerar bort respondenter som har färre än två svar på frågorna i delskalan.
Code
# If you want to include participants with missing data, input the minimum number of items responses that a participant should have to be included in the analysis:min.responses <-2scale.items <- itemlabels$itemnr# Select the variables we will work with, and filter out respondents with a lot of missing datadf.omit.na <- df %>%filter(length(scale.items)-rowSums(is.na(.[scale.items])) >= min.responses)RImissing(df.omit.na,"mp")
Vi har extremt få saknade svar, och tar därför bort respondenter som inte har kompletta svar.
Vi har väldigt få svar i lägsta svarskategorierna, speciellt för item mp1 och mp3. Vi slår därför ihop de två lägsta svarskategorierna för mp1 och mp3.
RIitemfitPCM2(df.omit.na, samplesize =250, nsamples =32, cpu =8)
OutfitMSQ
InfitMSQ
OutfitZSTD
InfitZSTD
mp1
0.925
0.884
-0.698
-1.079
mp2
0.842
0.819
-1.683
-1.961
mp3
0.817
0.84
-1.88
-1.709
mp4
0.691
0.696
-3.581
-3.377
mp5
0.824
0.822
-2.019
-2.032
Code
RIpcmPCA(na.omit(df.omit.na))
PCA of Rasch model residuals
Eigenvalues
1.71
1.27
1.21
0.81
0.00
Code
RIresidcorr(df.omit.na, cutoff =0.2)
mp1
mp2
mp3
mp4
mp5
mp1
mp2
-0.17
mp3
-0.23
-0.21
mp4
-0.32
-0.35
0.12
mp5
-0.15
-0.1
-0.48
-0.23
Note:
Relative cut-off value (highlighted in red) is -0.012, which is 0.2 above the average correlation.
Code
RIloadLoc(df.omit.na)
Code
RIitemCats(df.omit.na, items ="all")
Code
# increase fig-height above as needed, if you have many itemsRItargeting(df.omit.na, xlim =c(-5,5))
Code
RIitemHierarchy(df.omit.na)
Det finns en residualkorrelation mellan mp3 och mp4 långt över det rekommenderade tröskelvärdet. Eftersom mp4 visar låg item fit exkluderas detta item från fortsatta analyser.
Det finns problem med oordnade svarskategorier. Vi slår samman de två lägsta svarskategorierna (T1 och T2 i targeting-figuren) för item 2 och de två näst lägsta (T2 och T3) för item 5.
Code
# create vector with eliminated itemsremoved_items <-c("mp4")df.omit.na$mp2<-recode(df.omit.na$mp2,"1=0;2=1;3=2;4=3;5=4",as.factor=FALSE)df.omit.na$mp5<-recode(df.omit.na$mp5,"2=1;3=2;4=3;5=4",as.factor=FALSE)# select all items except those removeddf2 <- df.omit.na %>%select(!any_of(removed_items))
4.3.1 Analysis of response categories
Code
RIitemCats(df2, items ="all")
4.4 Rasch-analys 2
itemnr
item
mp1
Jag har de resurser som behövs för att kunna utföra mina arbetsuppgifter.
mp2
Jag kan prioritera i vilken ordning mina arbetsuppgifter ska utföras.
mp3
Jag har tillräckligt med befogenheter för att kunna utföra mina arbetsuppgifter.
Relative cut-off value (highlighted in red) is -0.064, which is 0.2 above the average correlation.
Code
RIloadLoc(df2)
Code
# increase fig-height above as needed, if you have many itemsRItargeting(df2)
Code
RIitemHierarchy(df2)
4.4.1 Targeting
Code
# increase fig-height above as needed, if you have many itemsRItargeting(df2)
Det finns inte längre något problem med residualkorrelationer. Flera items (mp1, mp2 och mp5) har något låg ZSTD item, medan MSQ ser ok ut. Vi går vidare och undersöker DIF och reliabilitet.
4.5 DIF-analysis
En DIF-analys bör inte inkludera svarskategorier med för få svar. Därför har svarskategorier med färre än 50 svar antingen exkluderas eller slagits ihop med andra svarskategorier (se avsnittet om bakgrundsdata för exakt antal svar per ordinarie kategori). DIF-variablerna omkodades till att innehålla följande kategorier:
Kön: man, kvinna
Ålder: 30-39, 40-49, 50-59, 60+
Bransch: kontorsarbete, ej kontorsarbete
Hemarbete: aldrig eller sällan, en dag, minst två dagar
Koden nedan specificerar exakt hur omkodningen gick till.
Code
# Omkodning för köndif.kön <-recode(dif.kön,"'Annat'=NA;'Vill ej uppge'=NA")# Omkodning för ålderdif.ålder <-recode(dif.ålder,"'18-29'=NA")# Omkodning för branschdif.bransch <-recode(dif.bransch,"'Industri'='Ej kontorsarbete';'Hotell, restaurang, service'='Ej kontorsarbete';'Handel'='Ej kontorsarbete';'Skola, utbildning'='Ej kontorsarbete';'Vård, omsorg'='Ej kontorsarbete';'Byggverksamhet'='Ej kontorsarbete';'Annat'='Ej kontorsarbete'")#Omkodning för hemarbetedif.hemarbete <-recode(dif.hemarbete,"'Fem dagar'='Minst två dagar';'Fyra dagar'='Minst två dagar';'Tre dagar'='Minst två dagar';'Två dagar'='Minst två dagar'")
Inga problem i DIF-analysen baserat på kön, ålder, bransch eller hemarbete.
4.6 Reliability
Code
RItif(df2, lo =-5, hi =5)
Reliabiliteten kommer inte riktigt upp i önskad nivå, men eftersom det avsedda användningsområdet enbart är på gruppnivå kan detta vara tillräckligt nära.