Testafdelingen hos Forbrugerrådet Tænk har ønsket at få udviklet en løsning, der kan erstatte Q Research Software pakken, og som fremadrettet kan bruges til databehandling og analyse i forbindelse med Testafdelingens analysearbejde.
I denne rapport præsenteres en foreløbig løsning for databehandling, herunder datarens og vægtning.
Forbrugerrådet Tænks panel har en meget skæv aldersfordeling, hvor de unge er stærkt underrepræsenteret og de ældre (60+) er stærkt overrepreæsenteret. Det betyder, at man skal være meget varmsom med, hvordan, og ikke mindst OM, man skal vægte data!!
R drives i høj grad af pakker som er udviklet ved siden af basisprogrammet. Som det første indlæses derfor pakker, som kræves for at gennemføre databehandlingen.
library(survey)
library(scales)
library(ggplot2)
if("dplyr" %in% (.packages())){
detach("package:dplyr", unload=TRUE)
detach("package:plyr", unload=TRUE)
}
library(plyr)
library(dplyr)
Jeg vil anbefale at importere data i SPSS format, da det bevarer labels, så de kan indlæses i tabeller og figurer.
Som alternativ kan man importere data i Excel eller CSV format, Her er det mest hensigtsmæssigt at kategoriske variable importeres som tekstværdier i stedet for numeriske værdier, men desværre kan Enalyzer ikke eksportere data i det format.
Bemærk i øvrigt, at variable bestående af talværdier altid importeres i “double format”, dvs. som flydende talværdier, uanset om der er tale om heltal eller decimaltal. Det betyder, at der ofte vises decimaler for heltal i resultater. Man kan evt. konvertere til heltal, men det ligger ud over formålet med denne indledende præsentation.
SPSS data importeres ved at kalde funktion “read_sav”, der peger på det bibliotek, hvor datafilen er gemt. Scriptet der vises nedenfor skal derfor rettes til, så det passer med filnavn og bibliotek, hvor SPSS filen er gemt.
# SPSS datafilens placering angives:
df.raw <- foreign::read.spss("C:/Rfiles/Forbrugerpanel-september-2023v4.sav",
to.data.frame = T)
Bemærk at SPSS filen gemmes i en dataframet “df.raw”.
Dataframes udgør sammen med vektorer og matricer grundpillerne i R, når man kalder funktioner.
Her vises nogle eksempler på, hvordan man kan få et overblik over datafilens struktur, inden den videre bearbejdning.
Man kan kalde funktionen “View” vha. syntaxen “View(df)”, hvor df er navnet på det dataframe, man ønsker at åbne. Så åbnes et faneblad, hvor man kan se alle rækker og kolonner som hvis man havde åbnet datasættet i SPSS, Excel eller lignende program. Jeg viser det ikke her, da det vil optage for meget plads!
Ved at kalde “glimpse” funktionen vises information om variable i datasættet herunder type og indhold:
glimpse(df.raw)
## Rows: 1,116
## Columns: 44
## $ respid <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, …
## $ Q_2 <fct> Kvinde, Kvinde, Kvinde, Mand, Kvinde, Kvinde, Kvinde, Kvinde, K…
## $ Q_3 <fct> 30-39 år, 50-59 år, 60-69 år, 60-69 år, 50-59 år, 60-69 år, 60-…
## $ Q_4 <fct> Region Hovedstaden, Region Hovedstaden, Region Hovedstaden, Reg…
## $ Q_5 <fct> "Lang videregående uddannelse (eksempelvis master, kandidat, ci…
## $ Q_6 <fct> Ja, Nej, Nej, Nej, Nej, Nej, Nej, Nej, Nej, Ja, Nej, Ja, Nej, N…
## $ Q_7 <fct> Jyske Bank, Jyske Bank, Danske Bank, Sydbank, Nordea, Anden ban…
## $ Q_8_1 <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, …
## $ Q_8_2 <dbl> 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ Q_8_3 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ Q_8_4 <dbl> 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, …
## $ Q_8_5 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, …
## $ Q_8_6 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ Q_8_7 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ Q_8_8 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ Q_9 <fct> Dankort, Visa/Dankort, Visa/Dankort, Visa/Dankort, Visa/Dankort…
## $ Q_10 <fct> Ja, Nej, Nej, Nej, Nej, Nej, Nej, Nej, Ja, Nej, Nej, Ja, Nej, N…
## $ Q_11 <fct> Nej, Ved ikke, Ja, Ved ikke, Ved ikke, Ved ikke, Ved ikke, Ved …
## $ Q_12 <fct> Meget vigtigt, Hverken eller, Slet ikke vigtigt, Mindre vigtigt…
## $ Q_13 <fct> "Jeg vil aktivt skulle vælge om det er Dankort-delen eller Visa…
## $ Q_15 <fct> Enig, Helt enig, Hverken enig eller uenig, Hverken enig eller u…
## $ Q_16_1 <dbl> 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, …
## $ Q_16_2 <dbl> 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, …
## $ Q_16_3 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, …
## $ Q_16_4 <dbl> 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, …
## $ Q_16_5 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, …
## $ Q_16_6 <dbl> 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, …
## $ Q_16_7 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ Q_18 <fct> Hverken enig eller uenig, Helt enig, Hverken enig eller uenig, …
## $ Q_19 <fct> Enig, Helt enig, Uenig, Hverken enig eller uenig, Enig, Enig, U…
## $ Q_21 <fct> Nej, Nej, Nej, Nej, Nej, Nej, Nej, Nej, Nej, Nej, Nej, Nej, Nej…
## $ Q_23_1 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ Q_23_2 <dbl> 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, …
## $ Q_23_3 <dbl> 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, …
## $ Q_23_4 <dbl> 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, …
## $ Q_23_5 <dbl> 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ Q_23_6 <dbl> 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, …
## $ Q_23_7 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ Q_24_1 <dbl> 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, …
## $ Q_24_2 <dbl> 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, …
## $ Q_24_3 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ Q_24_4 <dbl> 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, …
## $ Q_24_5 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, …
## $ Q_24_6 <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …
Den importerede datafil består af 1.116 rækker (data samples) og 54 variables (kolonner).
Man kan se mere information om labelstrukturen i en variabel ved at kalde funktionen “str”. Her er vist information om Q_2 (Køn)
str(df.raw$Q_2) # angiv variabel efter dollartegnet
## Factor w/ 4 levels "Mand","Kvinde",..: 2 2 2 1 2 2 2 2 2 2 ...
Som det ses ligger der informationer gemt om spørgsmålstekst, numeriske værdier og labels.
Det er altid en god idé at kontrollere sit datasæt for tomme celler (missing values), da det kan give udfordringer, når man laver beregninger, tabeller og figurer.
Nogle gange kan missing values skyldes surveyrelaterede forhold som spørgsmålsbetingelser, men andre gange kan der være tale om indlæsningsfejl. Med data, der kommer fra et surveyværktøj som Enalyzer, vil missing values dog typisk skyldes spørgsmålsbetingelser.
Mulighederne for fejl er større i datakilder som fx Excelark, hvor data kan være indtastet manuelt.
Men for øvelsens skyld, tager vi lige et kig på det indlæste datasæt.
Her er vist eksempel på en funktion, der kontrollerer datasættet for missing values og viser en udskrift for hver variabel.
sapply(df.raw, function(x) sum(is.na(x)))
## respid Q_2 Q_3 Q_4 Q_5 Q_6 Q_7 Q_8_1 Q_8_2 Q_8_3 Q_8_4
## 0 0 0 0 0 0 0 0 0 0 0
## Q_8_5 Q_8_6 Q_8_7 Q_8_8 Q_9 Q_10 Q_11 Q_12 Q_13 Q_15 Q_16_1
## 0 0 0 0 5 0 0 0 0 0 0
## Q_16_2 Q_16_3 Q_16_4 Q_16_5 Q_16_6 Q_16_7 Q_18 Q_19 Q_21 Q_23_1 Q_23_2
## 0 0 0 0 0 0 0 0 0 0 0
## Q_23_3 Q_23_4 Q_23_5 Q_23_6 Q_23_7 Q_24_1 Q_24_2 Q_24_3 Q_24_4 Q_24_5 Q_24_6
## 0 0 0 0 0 0 0 0 0 0 0
Det skarpe blik vil straks opdage, at der 5 missing values i Q_9, som har noget at gøre med kreditkort. De 5 manglende svar skyldes dog en svarbetingelse fra Q_8, hvorfor alt er som det skal være :-)
Det kan være problematisk at arbejde med “vil ikke oplyse” eller “Andet” kategorier i de demografiske baggrundsspørgsmål, der bruges som vejevariable. Der er kun 2 respondenter, som har valgt en af disse kategorier, men det kan give problemer med vejningen
Her er vist, hvordan man kan gemme de 2 slettede observationer i et separat datasæt, så de kan merges tilbage på det vejede datasæt.
# De 2 observationer med problematisk svar i køn og alder gemmes i ny dataframe:
df.raw.reserve <- df.raw[df.raw$Q_2 == "Andet" | df.raw$Q_2 == "Ønsker ikke at besvare" | df.raw$Q_3 == "Ønsker ikke at oplyse",]
# Gemmer kun rækker uden disse svarmuligheder:
df.raw <- df.raw[df.raw$Q_2 != "Andet" & df.raw$Q_2 != "Ønsker ikke at besvare" & df.raw$Q_3 != "Ønsker ikke at oplyse",]
Det er også en god idé at slette ubrugte svarmuligehder i de demografiske variable, der indgår i vejningen.
# Slet ubrugte svarmuligheder i køn og alder
df.raw$Q_2 <- droplevels(df.raw$Q_2)
df.raw$Q_3 <- droplevels(df.raw$Q_3)
Så er vi klar til at veje data efter kontrol og rens af data! Der blev i alt fjernet 2 observationer, så nettostikprøven er på 1.114 observationer.
Det rensede datasæt gemmes i et nyt dataframe “df”
# Gemmer i ny dataframe:
df <- df.raw
Som vi talte om på mødet 19/2 vægtes data på randfordelinger, også kaldet “raking”. Dvs. at de respektive fordelinger for køn, alder og region vejes på plads, men ikke fx køn og alder sammen eller i forhold til geografi. Dertil er datagrundlaget for spinkelt grundet, at der er en skævhed i aldersfodelingen i surveydesignet, da der er for få unge og for mange ældre i Forbrugerpanelet.
I det følgende vises, hvordan data vejes ved brug af “survey” pakken. Bemærk at der ikke tages højde for skævhed i sampling m.v. her. Der er alene tale om post-stratificeringsvejning.
Der dannes 2 vægte, en “basis” vægt uden grænser for laveste og højeste værdi, og en vægt, hvor den nedre og øvre grænse sættes til hhv. 0.3 og 3.
Bemærk at vejefordelingerne fra Danmarks Statistik skal indtastes manuelt i scriptet! Jeg har rundet værdierne af til nærmeste hele tal. “.49” betyder fx. 49%. Vil man have det mere præcist kan man sætte flere decimaler på.
Det kan sikkert godt automatiseres, men da man ikke vil have behov for at opdatere værdierne mere en måske 1 gang årligt, er det nok ikke umagen værd i forhold til tidsforbruget.
Her kommer først det script der definerer vejefaktorer og den første vægt uden begrænsing. Vægten gemmes i en vektor “data.svy.rake”
data.svy.unweighted <- svydesign(ids=~1, data=df)
gender.dist <- data.frame(Q_2=c("Mand","Kvinde"),
Freq=nrow(df)*c(.49, .51)) # Udgangspunkt i fordelinger fra Danmarks Statistik
age.dist <- data.frame(Q_3=c("Under 30 år","30-39 år","40-49 år","50-59 år","60-69 år","70 år eller derover"),
Freq=nrow(df)*c(.19, .16, .15, .17, .14, .19)) # Udgangspunkt i fordelinger fra Danmarks Statistik
geo.dist <- data.frame(Q_4=c("Region Hovedstaden","Region Midtjylland","Region Nordjylland","Region Sjælland","Region Syddanmark"),
Freq=nrow(df)*c(.32, .23, .10, .14, .21)) # Udgangspunkt i fordelinger fra Danmarks Statistik
data.svy.rake <- rake(design = data.svy.unweighted,sample.margins <- list(~Q_2, ~Q_3, ~Q_4),population.margins <- list(gender.dist, age.dist, geo.dist))
Og her dannes den “trimmede” vægt. Man kan sætte intervallerne manuelt ved at justere på værdierne i funktionen.
data.svy.rake.trim <- trimWeights(data.svy.rake, lower=.3, upper=3, strict=TRUE)
De to nye vejevariable merges på datsættet vha. disse scripts.
df$WEIGHTS <- weights(data.svy.rake)
df$WEIGHTS.TRIM <- weights(data.svy.rake.trim)
De 2 gemte observationer som blev fjernet inden vejningen kan nu merges tilbage på det vægtede datasæt med vægten “1” for begge vægte.
Koden herunder viser, hvordan det gøres:
# De 2 besvarelser tildeles vægten "1" i begge vejevariable:
df.raw.reserve$WEIGHTS <- c(1,1)
df.raw.reserve$WEIGHTS.TRIM <- c(1,1)
# De 2 besvarlser merges tilbage i datasættet:
df <- rbind(df, df.raw.reserve)
Nu har vi 2 vægte, der kan bruges, når vi går i gang med at udforske datasættet for indsigter.
Inden vi går videre omdøbes variabelnavne på de 3 demografiske variable, der indgik i vejningen, så det er nemmere at aflæse figurer og tabeller.
Man kan også ændre navne på andre variable her ved at opdatere scriptet herunder:
#Ændre kolonnenavne
colnames(df)[colnames(df) == "Q_2"] <- "Køn"
colnames(df)[colnames(df) == "Q_3"] <- "Alder"
colnames(df)[colnames(df) == "Q_4"] <- "Region"
# osv.
Vi ændrer også variabeltypen til kategorisk (factor) for Respid variablen, da det ikke giver mening, at den er numerisk.
# Konverterer respid til en factor:
df.raw$respid <- as.factor(df.raw$respid)
Lad os nu se lidt nærmere på, hvordan vægtene fordeler sig for “basis” vægten WEIGHTS:
summary(df$WEIGHTS)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.3253 0.4626 0.6001 1.0000 0.9979 13.6386
Middelvbærdien er 1, så vejningen er konvergeret korrekt. Til gengæld er der nogle meget ekstreme vægte på helt op til 13.63 og ned til 0.33! Specielt det første er ret skidt.
Det næste man bør kigge på er “weighting efficiency”, hvilket groft sagt siger noget om, hvor meget vejningen har af betydning for datamaterialets styrke. Weighting efficienct udregnes vha. en formel, jeg ikke skal komme nærmere ind på her (den fremgår af scriptet!), og returnerer en værdi mellem 0 og 1. Jo tættere på 1 jo bedre. Normalt sættes en grænse på 0.8, hvilket svarer til at vejningen reducerer samplestørrelsen med 20 pct. Er det tilfældet, bør man justere sin vejning.
Lad os i det følgende kigge lidt nærmere på “den ubegrænsede”basis” vægten. Jeg har omregnet til en 0-100 procentskala for overskuelighedens skyld.
a <- sum(df$WEIGHTS)^2
b <- 1000*sum(df$WEIGHTS^2)
c <- a/b
c_pct <- percent(c, accuracy = .01)
print(paste0("Weighting efficiency: ", c_pct, ", Vær obs hvis markant under 80%!"))
## [1] "Weighting efficiency: 37.04%, Vær obs hvis markant under 80%!"
Som det ses er weighting efficiency helt nede på knap 37.04 pct.! Det er ikke godt, og jeg vil ikke anbefale at bruge denne vægt i de videre analyser!
Men hvad kan det skyldes?
Her er vist et histogram for vejefaktorerne, hvor aldersgrupperne er fremhævet med farver.
p1 <- ggplot(data=df, aes(x=WEIGHTS))
p2 <- p1 + geom_histogram(binwidth = 0.2, aes(fill=Alder), colour="Black") +
ggtitle("WEIGHTS - fordelt på aldersgrupper") +
theme(plot.title = element_text(colour="Black", size = 15,hjust = 0.5))
p3 <- p2 + xlab("Vejefaktor") + ylab("Antal") +
theme(axis.title.x = element_text(colour = "Black", size=15),
axis.title.y = element_text(colour = "Black", size=15),
legend.position = c(1,1),
legend.justification = c(1,1))
p3
Som det ses ligger der en stor klump af vægte mellem 0 og 1 for især de 60-69 årige. Der er også en række outliers i den øvre del af skalaen for de 18-29 årige.
Ideelt se burde vægtene have været normalfordelt med middelværdien 1 i stedet for denne højreskæve fordeling. Det er hovedforklaringen på, hvorfor vejningen reducerer datamaterialets styrke så markant.
Men hvad med den anden “trimmede” vejevariabel WEIGHTS.TRIM?
Nedenfor ses vejefordelingen:
summary(df$WEIGHTS.TRIM)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.4885 0.6258 0.7633 1.0000 1.1611 3.0000
Det ser meget bedre ud, idet vægtene ligger i intervallet 0.49 til 3.
Weighting efficiency er også acceptabel:
a1 <- sum(df$WEIGHTS.TRIM)^2
b1 <- 1000*sum(df$WEIGHTS.TRIM^2)
c1 <- a1/b1
c1_pct <- percent(c1, accuracy = .01)
print(paste0("Weighting efficiency: ", c1_pct,", Vær obs hvis markant under 80%!"))
## [1] "Weighting efficiency: 78.56%, Vær obs hvis markant under 80%!"
Selvom resultatet ligger under idealgrænsen på 80% er det ok. Havde den ligget under 70% ville man være nødt til at overveje at ændre vejningen.
Som det fremgår af denne grafik, er fordelingen af vægtene stadig højreskæv, men ikke i samme grad som for “basis” vægten.
q1 <- ggplot(data=df, aes(x=WEIGHTS.TRIM))
q2 <- q1 + geom_histogram(binwidth = 0.05, aes(fill=Alder), colour="Black") +
ggtitle("WEIGHTS.TRIM - fordelt på aldersgrupper") +
theme(plot.title = element_text(colour="Black", size = 15,hjust = 0.5))
q3 <- q2 + xlab("Vejefaktor") + ylab("Antal") +
theme(axis.title.x = element_text(colour = "Black", size=15),
axis.title.y = element_text(colour = "Black", size=15),
legend.position = c(1,1),
legend.justification = c(1,1))
q3
Jeg vil derfor anbefale at anvende den trimmede vægt i de videre analyser.
Her til sidst, vil jeg vise, hvordan vejningen påvirker resultaterne med udgangspunkt i aldersvariablen.
Først vises fordelingen på de 6 aldersgrupper uvægtet:
ggplot(df, aes(x = reorder(Alder, desc(Alder)))) +
geom_bar(color="green", fill=rgb(87,219,124, maxColorValue = 255), width=0.5) +
coord_flip(ylim=c(0,500)) +
labs(x="Alder", y="Antal") +
labs(title = "Spm.3: Hvad er din alder?", subtitle = "Uvægtet")
Og her vægtet med “basis” vægten:
ggplot(df, aes(x = reorder(Alder, desc(Alder)))) +
geom_bar(aes(weight=WEIGHTS), color="green", fill=rgb(87,219,124, maxColorValue = 255), width=0.5) +
coord_flip(ylim=c(0,500)) +
labs(x="Alder", y="antal") +
labs(title = "Spm.3: Hvad er din alder?", subtitle = "Vægtet - basis")
Og endelig med den “trimmede” vægt:
ggplot(df, aes(x = reorder(Alder, desc(Alder)))) +
geom_bar(aes(weight=WEIGHTS.TRIM), color="green", fill=rgb(87,219,124, maxColorValue = 255), width=0.5) +
coord_flip(ylim=c(0,500)) +
labs(x="Alder", y="Antal") +
labs(title = "Spm.3: Hvad er din alder?", subtitle = "Vægtet - trimmed")
Som det ses er den trimmede vægt et kompromis. Aldersfordelingen vægtes ikke helt på plads, men datamaterialets styrke bevares.
Men med så skæv en aldersfordeling ville jeg nok kigge nærmere ind i, hvor meget vejningen egentlig betyder for resultaterne. Hvis det kun rykker nogle få procent i den ene eller anden retning, ville jeg helt droppe at vægte data.
Denne rapport har vist eksempler på, hvor data kan importeres, kontrolleres, renses og vægtes. Jeg har gemt en Rapport-skabelon, I kan tage udgangspunkt i, samt en script-fil, hvor al kode er gemt med kommentarer.
Læringskurven i R er ret stejl, så for at få en grundlæggende forståelse for, hvordan R fungerer, vil jeg anbefale at tage et grundkursus. Jeg har selv taget kurset R Programming A-Z™: R For Data Science With Real Exercises! som udbydes på onlinelæringsplatformen Udemy. Det er ofte på tilbud til en overkommelig pris. Det tog mig knap 11 timer at gennemføre.
Selvom det er smart at importere data direkte fra en SPSS fil og bevare metadata om labels, er der også ulemper. Bl.a. kan man ikke manuelt ændre overskriften i forklaringstekster i figurer. F.eks. kan man ikke ændre “Q_3” til “Alder”. Det er lidt bøvlet. Man kan dog komme uden om det ved at omdøbe kolonneoverskrifterne (variabelnavne) til noget mere forståeligt end Q_2 m.v.
En løsning kunne være at anvende “Foreign” pakken, når man importerer SPSS data, så Metadata ikke ryger med over. Desværre er denne pakke mere “følsom” overfor bl.a. åbne tekstfelter, e-mailadresser o.lign. hvorfor data skal renses inden import.
Som nævnt er CSV og Excel ikke rigtigt en mulighed, da Enalyzer ikke kan eksportere i det format, vi har brug for. Men måske I kunne sende dem en mail med ønsker til fremtidige eksportformater.
Jeg vil kigge videre på at udvikle nogle standardtabeller og -figurer, der fungerer med vejevariable.