I denne rapport gives eksempler på tabeloutput i R Studio.
Der vises følgende typer tabeller:
Tabellerne vises med både vægtet og uvægtet stikprøve.
Der er ikke gjort forsøg på at skrive loops, der kan udskrive flere tabeller på en gang.
I dette afsnit vises eksempler på frekvenstabeller.
I tabellerne vises kolonner for:
Der tilføjes tabeloverskrifter øverst.
Tabeller er udviklet ved at kombinere %>% (pipe) funktionen med forskellige andre pakker, der kan tilføje kolonnetotaler og figurtekster.
Her kommer først en uvægtet frekvenstabel:
# Uvægtet frekvenstabel:
tabel1 <- df %>% # %>% (pipe) er en speciel funktion, der kan binde flere funktioner sammen
group_by(Køn) %>% # Her væles Køn
summarise(Frekvens = n()) %>% # Tæller antal
mutate(Procent=percent(Frekvens/sum(Frekvens), accuracy=1)) %>% # mutate tilføjer en kolonne med procenter
adorn_totals(where = c("row"), fill = "100%") # Tilføjer kolonnetotaler
kbl(tabel1, # Her tilføjes figurtekst
caption = "Tabel 1: Deltagernes fordeling på køn.") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE, position = "left")
| Køn | Frekvens | Procent |
|---|---|---|
| Mand | 478 | 43% |
| Kvinde | 637 | 57% |
| Ønsker ikke at besvare | 1 | 0% |
| Total | 1116 | 100% |
Og her er en vægtet frekvenstabel, hvor der er anvendt den ikke-trimmede vægt (WEIGHTS).
Jeg har ikke kunnet finde en pakke, der kan lave denne type frekvenstabeller med vægtede data, så jeg har kodet løsningen selv. Der er tilføjet survey vægte ved at tælle op på Vægt variablen i stedet for antal rækker. Det fungerer fint.
tabel2 <- df %>% # %>% (pipe) er en speciel funktion, der kan binde flere funktioner sammen
group_by(Køn) %>% # Her væles Køn
summarise(Frekvens = round(sum(WEIGHTS),0)) %>% # Vægtene indlæses vha. sum. Har kontrolleret at det stemmer.
mutate(Procent=percent(Frekvens/sum(Frekvens), accuracy=1)) %>% # mutate tilføjer en kolonne med procenter
adorn_totals(where = c("row"), fill = "100%") # Tilføjer kolonnetotaler
kbl(tabel2,
caption = "Tabel 2: Deltagernes fordeling på køn - vægtet") %>% # Tilføjer tabeloverskrift
kable_styling(bootstrap_options = "striped", full_width = FALSE, position = "left") # Definerer størrelse, tilføjer striber
| Køn | Frekvens | Procent |
|---|---|---|
| Mand | 546 | 49% |
| Kvinde | 569 | 51% |
| Ønsker ikke at besvare | 1 | 0% |
| Total | 1116 | 100% |
I dette afsnit gives eksempler på krydstabeller.
Jeg har brugt tableby pakken, som giver nogle rigtigt flotte tabeller. Pakken har en funktion, hvor man kan tilføje vægte, hvis det ønskes.
Her en uvægtet krydstabel
colnames(df)[colnames(df) == "Q_7"] <- "Bank"
tabel3 <- tableby(Region ~ Bank, data=df, test=FALSE)
kbl(summary(tabel3, text=TRUE),
caption = "Tabel 3: I hvilken bank har du dit primære kredit kort? - krydset med region.") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE, position = "float_left")
| Region Hovedstaden (N=364) | Region Midtjylland (N=253) | Region Nordjylland (N=93) | Region Sjælland (N=165) | Region Syddanmark (N=241) | Total (N=1116) | |
|---|---|---|---|---|---|---|
| Bank | ||||||
|
113 (31.0%) | 38 (15.0%) | 14 (15.1%) | 44 (26.7%) | 66 (27.4%) | 275 (24.6%) |
|
30 (8.2%) | 27 (10.7%) | 5 (5.4%) | 15 (9.1%) | 9 (3.7%) | 86 (7.7%) |
|
9 (2.5%) | 18 (7.1%) | 3 (3.2%) | 7 (4.2%) | 31 (12.9%) | 68 (6.1%) |
|
23 (6.3%) | 11 (4.3%) | 4 (4.3%) | 9 (5.5%) | 7 (2.9%) | 54 (4.8%) |
|
8 (2.2%) | 9 (3.6%) | 22 (23.7%) | 2 (1.2%) | 9 (3.7%) | 50 (4.5%) |
|
27 (7.4%) | 13 (5.1%) | 0 (0.0%) | 6 (3.6%) | 14 (5.8%) | 60 (5.4%) |
|
6 (1.6%) | 3 (1.2%) | 11 (11.8%) | 0 (0.0%) | 0 (0.0%) | 20 (1.8%) |
|
5 (1.4%) | 9 (3.6%) | 14 (15.1%) | 1 (0.6%) | 2 (0.8%) | 31 (2.8%) |
|
66 (18.1%) | 49 (19.4%) | 5 (5.4%) | 50 (30.3%) | 35 (14.5%) | 205 (18.4%) |
|
76 (20.9%) | 75 (29.6%) | 15 (16.1%) | 30 (18.2%) | 66 (27.4%) | 262 (23.5%) |
|
1 (0.3%) | 1 (0.4%) | 0 (0.0%) | 1 (0.6%) | 2 (0.8%) | 5 (0.4%) |
Og her er samme tabel, hvor den trimmede vægt er slået til:
tabel4 <- tableby(Region ~ Bank, data=df, weights = WEIGHTS.TRIM, test=FALSE)
kbl(summary(tabel4, text=TRUE),
caption = "Tabel 4: I hvilken bank har du dit primære kredit kort? - krydset med region - vægtet.") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE, position = "float_left")
| Region Hovedstaden (N=348) | Region Midtjylland (N=246) | Region Nordjylland (N=111) | Region Sjælland (N=147) | Region Syddanmark (N=264) | Total (N=1116) | |
|---|---|---|---|---|---|---|
| Bank | ||||||
|
87 (25.1%) | 32 (13.0%) | 20 (18.0%) | 34 (22.8%) | 67 (25.5%) | 240 (21.5%) |
|
35 (10.1%) | 25 (10.2%) | 8 (7.2%) | 15 (10.2%) | 9 (3.3%) | 92 (8.2%) |
|
7 (2.1%) | 16 (6.6%) | 2 (2.1%) | 5 (3.5%) | 30 (11.4%) | 61 (5.5%) |
|
24 (7.0%) | 9 (3.5%) | 3 (3.0%) | 6 (3.8%) | 7 (2.8%) | 49 (4.4%) |
|
8 (2.4%) | 7 (3.0%) | 26 (23.1%) | 1 (1.0%) | 13 (4.8%) | 55 (5.0%) |
|
27 (7.7%) | 11 (4.5%) | 0 (0.0%) | 7 (4.7%) | 15 (5.8%) | 60 (5.4%) |
|
6 (1.7%) | 5 (1.9%) | 11 (10.0%) | 0 (0.0%) | 0 (0.0%) | 22 (1.9%) |
|
9 (2.5%) | 13 (5.4%) | 20 (17.7%) | 1 (0.4%) | 2 (0.8%) | 44 (4.0%) |
|
62 (17.8%) | 50 (20.2%) | 5 (4.7%) | 43 (29.2%) | 40 (15.1%) | 200 (17.9%) |
|
81 (23.4%) | 77 (31.5%) | 16 (14.1%) | 35 (23.6%) | 79 (29.8%) | 288 (25.8%) |
|
1 (0.2%) | 1 (0.3%) | 0 (0.0%) | 1 (0.8%) | 2 (0.8%) | 5 (0.4%) |
Som det ses, har vægtningen ganske stor indflydelse på resultaterne!
Rent kosmetisk er et lidt irriterende, at der bliver tilføjet em bindestreg foran hver rækkelabel, men det er desværre en begrænsning i tableby pakken, når man bruger kbl til at tilføje tabeloverskrift. Man kan få en pænere formaterring ved at slette den nederste kbl kode og i stedet vise tabelle via funktionen summary(tabel4).
tabel4 <- tableby(Region ~ Bank, data=df, weights = WEIGHTS.TRIM, test=FALSE)
summary(tabel4)
| Region Hovedstaden (N=348) | Region Midtjylland (N=246) | Region Nordjylland (N=111) | Region Sjælland (N=147) | Region Syddanmark (N=264) | Total (N=1116) | |
|---|---|---|---|---|---|---|
| Bank | ||||||
| Danske Bank | 87 (25.1%) | 32 (13.0%) | 20 (18.0%) | 34 (22.8%) | 67 (25.5%) | 240 (21.5%) |
| Jyske Bank | 35 (10.1%) | 25 (10.2%) | 8 (7.2%) | 15 (10.2%) | 9 (3.3%) | 92 (8.2%) |
| Sydbank | 7 (2.1%) | 16 (6.6%) | 2 (2.1%) | 5 (3.5%) | 30 (11.4%) | 61 (5.5%) |
| Nykredit Bank | 24 (7.0%) | 9 (3.5%) | 3 (3.0%) | 6 (3.8%) | 7 (2.8%) | 49 (4.4%) |
| Spar Nord Bank | 8 (2.4%) | 7 (3.0%) | 26 (23.1%) | 1 (1.0%) | 13 (4.8%) | 55 (5.0%) |
| Arbejdernes Landsbank | 27 (7.7%) | 11 (4.5%) | 0 (0.0%) | 7 (4.7%) | 15 (5.8%) | 60 (5.4%) |
| Ringkjøbing Landbobank | 6 (1.7%) | 5 (1.9%) | 11 (10.0%) | 0 (0.0%) | 0 (0.0%) | 22 (1.9%) |
| Sparekassen Danmark | 9 (2.5%) | 13 (5.4%) | 20 (17.7%) | 1 (0.4%) | 2 (0.8%) | 44 (4.0%) |
| Nordea | 62 (17.8%) | 50 (20.2%) | 5 (4.7%) | 43 (29.2%) | 40 (15.1%) | 200 (17.9%) |
| Anden bank | 81 (23.4%) | 77 (31.5%) | 16 (14.1%) | 35 (23.6%) | 79 (29.8%) | 288 (25.8%) |
| Ved ikke | 1 (0.2%) | 1 (0.3%) | 0 (0.0%) | 1 (0.8%) | 2 (0.8%) | 5 (0.4%) |
Multiple response tabeller er lidt vanskeligere at producere. Man kan dog både kode dem selv fra bunden eller bruge pakken expss.
Jeg har valgt at bruge expss, da det er lettest. Expss understøtter desværre ikke procent format, så tallene står som procenter uden procenttegn i tabellerne. Til gengæld kan man bruge vejevariable.
Inden man laver multiple response tabeller, kan det være en fordel at gemme de relevante variable i et nyt dataframe og give kolonnerne passende overskrifter.
df8 <- df %>%
rename("Visa Dankort" = "Q_8_1",
"Dankort" = "Q_8_2",
"Visakort" = "Q_8_3",
"Mastercard" = "Q_8_4",
"Mastercard Dankort" = "Q_8_5",
"Andet" = "Q_8_6",
"Har ikke et betalingskort" = "Q_8_7",
"Ved ikke" = "Q_8_8")
# Gem subset af data (Q_8)
df_Q8 <- df8[ , c("Visa Dankort", "Dankort", "Visakort", "Mastercard", "Mastercard Dankort",
"Andet", "Har ikke et betalingskort", "Ved ikke",
"Køn", "Alder", "Region", "WEIGHTS", "WEIGHTS.TRIM")]
Obs! En ulempe ved expss er, at man er nødt til manuelt at definere kolonneoverskrifter, fordi der indsættes teksten “rownames” i den første kolonne. Det betyder, at man evt. kan springe første step i ovenstående over.
Her er eksempler på en vægtet frekvenstabel med brug af WEIGHTS.TRIM:
tabel5 <- cross_cpct(df_Q8, mdset("Visa Dankort" %to% "Ved ikke"), list(total()), weight = WEIGHTS.TRIM)
kbl(tabel5, caption = "Tabel 5: Hvilke betalingskort har du gennem din bank? - vægtet.",
col.names = c("Betalingskort:", "Total pct. af resp."), digits=2) %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE, position = "center")
| Betalingskort: | Total pct. af resp. |
|---|---|
| Visa Dankort | 86.04 |
| Dankort | 4.94 |
| Visakort | 7.03 |
| Mastercard | 46.57 |
| Mastercard Dankort | 6.47 |
| Andet | 1.39 |
| Har ikke et betalingskort | 0.39 |
| Ved ikke | 0.12 |
| #Total cases | 1116.00 |
Tallene viser pct. at det totale antal respondenter (1.116).
Alternativt kan man vise tallene som pct. at det total antal afgivne svar (1.719):
tabel6 <- cross_cpct_responses(df_Q8, mdset("Visa Dankort" %to% "Ved ikke"), list(total()), weight = WEIGHTS.TRIM)
kbl(tabel6, caption = "Tabel 6: Hvilke betalingskort har du gennem din bank? - vægtet.",
col.names = c("Betalingskort:", "Total pct. af svar"), digits=2) %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE, position = "center")
| Betalingskort: | Total pct. af svar |
|---|---|
| Visa Dankort | 56.25 |
| Dankort | 3.23 |
| Visakort | 4.60 |
| Mastercard | 30.45 |
| Mastercard Dankort | 4.23 |
| Andet | 0.91 |
| Har ikke et betalingskort | 0.25 |
| Ved ikke | 0.08 |
| #Total responses | 1719.00 |
Og sådan kunne en ** vægtet krydstabel** se ud:
tabel7 <- cross_cpct(df_Q8, mdset("Visa Dankort" %to% "Ved ikke"), list(total(), Alder), weight = WEIGHTS.TRIM)
kbl(tabel7, caption = "Tabel 7: Hvilke betalingskort har du gennem din bank? - krydset med alder - vægtet.",
col.names = c("Betalingskort:", "Total pct. af resp.", "Under 30 år", "30-39 år",
"40-49 år", "50-59 år", "60-69 år", "70+ år", "Ønsker ikke at oplyse"), digits=2) %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE, position = "float_left")
| Betalingskort: | Total pct. af resp. | Under 30 år | 30-39 år | 40-49 år | 50-59 år | 60-69 år | 70+ år | Ønsker ikke at oplyse |
|---|---|---|---|---|---|---|---|---|
| Visa Dankort | 86.04 | 86.96 | 81.06 | 83.18 | 87.04 | 85.87 | 89.64 | 100 |
| Dankort | 4.94 | 4.35 | 7.66 | 5.65 | 4.05 | 4.13 | 4.46 | NA |
| Visakort | 7.03 | 8.70 | 9.61 | 7.71 | 7.18 | 6.36 | 5.21 | NA |
| Mastercard | 46.57 | 43.48 | 51.28 | 42.80 | 41.68 | 47.82 | 50.35 | NA |
| Mastercard Dankort | 6.47 | 8.70 | 3.97 | 5.50 | 6.46 | 6.87 | 7.65 | NA |
| Andet | 1.39 | NA | NA | 2.07 | 2.49 | 0.85 | 1.56 | NA |
| Har ikke et betalingskort | 0.39 | NA | NA | 1.15 | 0.66 | NA | 0.27 | NA |
| Ved ikke | 0.12 | NA | NA | NA | NA | 0.33 | 0.23 | NA |
| #Total cases | 1116.00 | 23.00 | 53.00 | 108.00 | 191.00 | 309.00 | 431.00 | 1 |
Bemærk i øvrigt, at det de uvejede samplestørrelser, der står nederst i tabellen!
Her til sidst et alternativt layout for en multipel frekvenstabel, med kolonner for både pct. af resp. og svar:
tabel8 <- data.frame(Frekvens = round(colSums(df_Q8[1:8]*df_Q8$WEIGHTS.TRIM),0),
Pct.af.Svar = percent(round((colSums(df_Q8[1:8]*df_Q8$WEIGHTS.TRIM)/sum(df_Q8[1:8])),2)),
Pct.af.Resp = percent(round((colSums(df_Q8[1:8]*df_Q8$WEIGHTS.TRIM)/nrow(df_Q8[1:8])),2)))
kbl(tabel8, caption = "Tabel 8: Hvilke betalingskort har du gennem din bank? - vægtet.") %>%
kable_styling(bootstrap_options = "striped", full_width = FALSE, position = "center")
| Frekvens | Pct.af.Svar | Pct.af.Resp | |
|---|---|---|---|
| Visa Dankort | 960 | 56% | 86% |
| Dankort | 55 | 3% | 5% |
| Visakort | 79 | 5% | 7% |
| Mastercard | 520 | 30% | 47% |
| Mastercard Dankort | 72 | 4% | 6% |
| Andet | 15 | 1% | 1% |
| Har ikke et betalingskort | 4 | 0% | 0% |
| Ved ikke | 1 | 0% | 0% |
I denne rapport er vist eksempler på, hvordan man kan lave tabeller.
Det letteste er nok at lave det hele i expss, da det ikke kræver helt så meget kodning. Fordelen er også, at man får det samme visuelle output.
Personligt kan jeg dog bedst lide, at der står procenter med procenttegn i tabellerne, og det kan expss ikke.