Kapitel 58 Wide oder Long so lang wie breit
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(tidyr)
library(kableExtra)
##
## Attaching package: 'kableExtra'
## The following object is masked from 'package:dplyr':
##
## group_rows
Dies ist eine sehr schwierige Übung; das Umformen von Daten macht mich in R wahnsinnig. Tun Sie dies nicht, wenn Sie gestresst sind.
Zuerst simulieren wir ein paar Daten
library(kableExtra)
<-1:5
id<-c(rnorm(5,5,2))
pain_t1<-c(rnorm(5,5.2,2.2))
pain_t2<-c(rnorm(5,6,2))
pain_t3
<-cbind.data.frame(id, pain_t1, pain_t2, pain_t3)
df_pain_widekbl(df_pain_wide) %>% kable_styling()
id | pain_t1 | pain_t2 | pain_t3 |
---|---|---|---|
1 | 4.477547 | 0.6891036 | 5.502578 |
2 | 5.778489 | 4.1823753 | 3.960967 |
3 | 3.714936 | 7.5441658 | 1.806426 |
4 | 1.100044 | 4.0373206 | 2.632779 |
5 | 4.646760 | 6.1326351 | 4.034842 |
library(tidyr)
<-df_pain_wide %>%
df_pain_longpivot_longer(
cols= 2:4,
names_to = "timepoint",
names_prefix = "pain_t",
values_to="pain"
)
kbl(df_pain_long) %>% kable_styling()
id | timepoint | pain |
---|---|---|
1 | 1 | 4.4775467 |
1 | 2 | 0.6891036 |
1 | 3 | 5.5025783 |
2 | 1 | 5.7784891 |
2 | 2 | 4.1823753 |
2 | 3 | 3.9609670 |
3 | 1 | 3.7149358 |
3 | 2 | 7.5441658 |
3 | 3 | 1.8064256 |
4 | 1 | 1.1000442 |
4 | 2 | 4.0373206 |
4 | 3 | 2.6327794 |
5 | 1 | 4.6467597 |
5 | 2 | 6.1326351 |
5 | 3 | 4.0348420 |
Um zu verstehen, was der Code macht, schauen Sie sich an, was passiert, wenn wir kein names_prefix setzen:
<-df_pain_wide %>%
df_pain_longpivot_longer(
cols= 2:4,
names_to = "timepoint",
values_to="pain"
)kbl(df_pain_long) %>% kable_styling()
id | timepoint | pain |
---|---|---|
1 | pain_t1 | 4.4775467 |
1 | pain_t2 | 0.6891036 |
1 | pain_t3 | 5.5025783 |
2 | pain_t1 | 5.7784891 |
2 | pain_t2 | 4.1823753 |
2 | pain_t3 | 3.9609670 |
3 | pain_t1 | 3.7149358 |
3 | pain_t2 | 7.5441658 |
3 | pain_t3 | 1.8064256 |
4 | pain_t1 | 1.1000442 |
4 | pain_t2 | 4.0373206 |
4 | pain_t3 | 2.6327794 |
5 | pain_t1 | 4.6467597 |
5 | pain_t2 | 6.1326351 |
5 | pain_t3 | 4.0348420 |
rm(df_pain_wide) # for this exercise, we delete df_pain_wide, just to re-create it
# https://tidyr.tidyverse.org/reference/pivot_wider.html
<-df_pain_long %>%
df_pain_widepivot_wider(
names_from = timepoint,
values_from=pain,
)
kbl(df_pain_wide) %>% kable_styling()
id | pain_t1 | pain_t2 | pain_t3 |
---|---|---|---|
1 | 4.477547 | 0.6891036 | 5.502578 |
2 | 5.778489 | 4.1823753 | 3.960967 |
3 | 3.714936 | 7.5441658 | 1.806426 |
4 | 1.100044 | 4.0373206 | 2.632779 |
5 | 4.646760 | 6.1326351 | 4.034842 |
58.1 Jetzt erstellen wir ein etwas komplexeres Beispiel mit zwei Variablen:
<-1:20
id<-c(rnorm(20,5,0.8))
pain_t1<-c(rnorm(20,5.2,1))
pain_t2<-c(rnorm(20,6,1))
pain_t3<-rnorm(20,3,1.5)
depression_t1<-rnorm(20,2.3,1.2)
depression_t2<-rnorm(20,2,1)
depression_t3
<-cbind.data.frame(id, pain_t1, pain_t2, pain_t3, depression_t1,depression_t2, depression_t3)
df_widekbl(df_wide) %>% kable_styling()
id | pain_t1 | pain_t2 | pain_t3 | depression_t1 | depression_t2 | depression_t3 |
---|---|---|---|---|---|---|
1 | 5.656984 | 2.819316 | 5.815402 | 3.885715 | 2.0421460 | 1.5214934 |
2 | 6.165082 | 5.529996 | 7.583380 | 2.539429 | 2.0003762 | 2.5848875 |
3 | 5.531116 | 6.203559 | 4.263717 | 1.720150 | 3.7065487 | 2.5164596 |
4 | 5.871913 | 4.494053 | 5.098977 | 3.677762 | 3.0315677 | 0.4705033 |
5 | 4.130856 | 5.084113 | 5.002438 | 1.802936 | 1.1359716 | 0.5163920 |
6 | 5.698688 | 6.774785 | 5.631553 | 1.800300 | 3.5014509 | 4.0980196 |
7 | 4.103681 | 6.371349 | 7.105606 | 2.421270 | 2.2331449 | 3.9944306 |
8 | 5.061298 | 6.351247 | 4.317741 | 2.310692 | 2.0161379 | 3.3254441 |
9 | 5.497747 | 4.824040 | 6.524044 | 5.370380 | 2.5366711 | 1.4734719 |
10 | 4.564592 | 5.644271 | 5.227413 | 2.218900 | 1.4162920 | 2.1811705 |
11 | 3.352520 | 6.479761 | 6.433863 | 3.699441 | 0.7152843 | 1.8664987 |
12 | 5.539580 | 5.564063 | 5.544053 | 2.555122 | 3.9129574 | 2.3375691 |
13 | 6.307981 | 6.872753 | 6.468923 | 3.298944 | 2.0905369 | 1.9945405 |
14 | 4.775065 | 4.440590 | 6.859823 | 2.085893 | 1.8472488 | 2.6521203 |
15 | 4.927217 | 4.793689 | 6.320824 | 1.342637 | 2.3073442 | 0.7300040 |
16 | 7.297372 | 4.465633 | 7.419043 | 5.449281 | 3.4720211 | 2.8194853 |
17 | 4.240963 | 4.795546 | 6.239813 | 1.039829 | 1.6175661 | 1.0833755 |
18 | 4.599539 | 5.395504 | 6.049200 | 3.290007 | 0.0489657 | 2.0439870 |
19 | 5.612096 | 6.391864 | 5.371284 | 4.045980 | 3.7580677 | 2.1667151 |
20 | 5.599089 | 5.616377 | 7.023909 | 2.606809 | 5.4713226 | 2.8584734 |
58.2 Diese Daten sind im wide Format - Jetzt wollen wir sie in das long Format umwandeln.
- Bemerkung: bei der Zeile cols = 2:7, hätten wir auch folgendes schreiben können: cols = -id,
library(tidyr)
# https://tidyr.tidyverse.org/reference/pivot_longer.html
<-df_wide %>%
df_longpivot_longer(
cols = 2:7,
names_to = c(".value", "time"),
names_sep = '_')
kbl(df_long) %>% kable_styling()
id | time | pain | depression |
---|---|---|---|
1 | t1 | 5.656984 | 3.8857152 |
1 | t2 | 2.819316 | 2.0421460 |
1 | t3 | 5.815402 | 1.5214934 |
2 | t1 | 6.165082 | 2.5394288 |
2 | t2 | 5.529996 | 2.0003762 |
2 | t3 | 7.583380 | 2.5848875 |
3 | t1 | 5.531116 | 1.7201501 |
3 | t2 | 6.203559 | 3.7065487 |
3 | t3 | 4.263717 | 2.5164596 |
4 | t1 | 5.871913 | 3.6777623 |
4 | t2 | 4.494053 | 3.0315677 |
4 | t3 | 5.098977 | 0.4705033 |
5 | t1 | 4.130856 | 1.8029359 |
5 | t2 | 5.084113 | 1.1359716 |
5 | t3 | 5.002438 | 0.5163920 |
6 | t1 | 5.698688 | 1.8003003 |
6 | t2 | 6.774785 | 3.5014509 |
6 | t3 | 5.631553 | 4.0980196 |
7 | t1 | 4.103681 | 2.4212700 |
7 | t2 | 6.371349 | 2.2331449 |
7 | t3 | 7.105606 | 3.9944306 |
8 | t1 | 5.061298 | 2.3106923 |
8 | t2 | 6.351247 | 2.0161379 |
8 | t3 | 4.317741 | 3.3254441 |
9 | t1 | 5.497747 | 5.3703800 |
9 | t2 | 4.824040 | 2.5366711 |
9 | t3 | 6.524044 | 1.4734719 |
10 | t1 | 4.564592 | 2.2189000 |
10 | t2 | 5.644271 | 1.4162920 |
10 | t3 | 5.227413 | 2.1811705 |
11 | t1 | 3.352520 | 3.6994405 |
11 | t2 | 6.479761 | 0.7152843 |
11 | t3 | 6.433863 | 1.8664987 |
12 | t1 | 5.539580 | 2.5551217 |
12 | t2 | 5.564063 | 3.9129574 |
12 | t3 | 5.544053 | 2.3375691 |
13 | t1 | 6.307981 | 3.2989440 |
13 | t2 | 6.872753 | 2.0905369 |
13 | t3 | 6.468923 | 1.9945405 |
14 | t1 | 4.775065 | 2.0858934 |
14 | t2 | 4.440590 | 1.8472488 |
14 | t3 | 6.859823 | 2.6521203 |
15 | t1 | 4.927217 | 1.3426371 |
15 | t2 | 4.793689 | 2.3073442 |
15 | t3 | 6.320824 | 0.7300040 |
16 | t1 | 7.297372 | 5.4492815 |
16 | t2 | 4.465633 | 3.4720211 |
16 | t3 | 7.419043 | 2.8194853 |
17 | t1 | 4.240963 | 1.0398285 |
17 | t2 | 4.795546 | 1.6175661 |
17 | t3 | 6.239813 | 1.0833755 |
18 | t1 | 4.599539 | 3.2900068 |
18 | t2 | 5.395504 | 0.0489657 |
18 | t3 | 6.049200 | 2.0439870 |
19 | t1 | 5.612096 | 4.0459801 |
19 | t2 | 6.391864 | 3.7580677 |
19 | t3 | 5.371284 | 2.1667151 |
20 | t1 | 5.599089 | 2.6068093 |
20 | t2 | 5.616377 | 5.4713226 |
20 | t3 | 7.023909 | 2.8584734 |
58.3 Für diese Übung löschen wir df_wide, nur um es neu zu erstellen (von long wieder zu wide umzustellen).
rm(df_wide)
# https://tidyr.tidyverse.org/reference/pivot_wider.html
<-df_long %>%
df_widepivot_wider(
names_from = "time",
values_from=c("pain","depression"))
kbl(df_wide) %>% kable_styling()
id | pain_t1 | pain_t2 | pain_t3 | depression_t1 | depression_t2 | depression_t3 |
---|---|---|---|---|---|---|
1 | 5.656984 | 2.819316 | 5.815402 | 3.885715 | 2.0421460 | 1.5214934 |
2 | 6.165082 | 5.529996 | 7.583380 | 2.539429 | 2.0003762 | 2.5848875 |
3 | 5.531116 | 6.203559 | 4.263717 | 1.720150 | 3.7065487 | 2.5164596 |
4 | 5.871913 | 4.494053 | 5.098977 | 3.677762 | 3.0315677 | 0.4705033 |
5 | 4.130856 | 5.084113 | 5.002438 | 1.802936 | 1.1359716 | 0.5163920 |
6 | 5.698688 | 6.774785 | 5.631553 | 1.800300 | 3.5014509 | 4.0980196 |
7 | 4.103681 | 6.371349 | 7.105606 | 2.421270 | 2.2331449 | 3.9944306 |
8 | 5.061298 | 6.351247 | 4.317741 | 2.310692 | 2.0161379 | 3.3254441 |
9 | 5.497747 | 4.824040 | 6.524044 | 5.370380 | 2.5366711 | 1.4734719 |
10 | 4.564592 | 5.644271 | 5.227413 | 2.218900 | 1.4162920 | 2.1811705 |
11 | 3.352520 | 6.479761 | 6.433863 | 3.699441 | 0.7152843 | 1.8664987 |
12 | 5.539580 | 5.564063 | 5.544053 | 2.555122 | 3.9129574 | 2.3375691 |
13 | 6.307981 | 6.872753 | 6.468923 | 3.298944 | 2.0905369 | 1.9945405 |
14 | 4.775065 | 4.440590 | 6.859823 | 2.085893 | 1.8472488 | 2.6521203 |
15 | 4.927217 | 4.793689 | 6.320824 | 1.342637 | 2.3073442 | 0.7300040 |
16 | 7.297372 | 4.465633 | 7.419043 | 5.449281 | 3.4720211 | 2.8194853 |
17 | 4.240963 | 4.795546 | 6.239813 | 1.039829 | 1.6175661 | 1.0833755 |
18 | 4.599539 | 5.395504 | 6.049200 | 3.290007 | 0.0489657 | 2.0439870 |
19 | 5.612096 | 6.391864 | 5.371284 | 4.045980 | 3.7580677 | 2.1667151 |
20 | 5.599089 | 5.616377 | 7.023909 | 2.606809 | 5.4713226 | 2.8584734 |
58.4 Manchmal führen Umwege zum Ziel: Von Wide to Long to Long-Wide
Wir schauen uns ein Beispiel an, bei dem wir zwei Variablen haben, die wir als long darstellen können: Einerseits der Ort der Probleme, hier Knie und Hüfte, anderseits die drei Messgrössen (“Outcomes”) Gehtest, Sit to Stand Test, und der Hop Test. So sehen die Daten aus:
Die Daten sind schon zusammengefasst, das heisst, wir haben hier nicht die Werte einzelner Patient:innen, sondern schon zusammengefasste Werte (d.h. die prozentualen Veränderungen der Mittelwerte).Aber das Prinzip bleibt gleich bei Daten einzelner Patient:innen.
Wir könnten sagen, dass die Daten long-wide sind, da die Variable Gelenk als long formatiert ist (d.h. für jede Kategorie der Variable Gelenk eine Zeile), und die Variable Outcome ist hier als wide formatiert (d.h. es gibt keine Variable Outcome die für jede Kategorie eine Zeile hat, sondern bei der Variable perc_change ist jeweils das Outcome angehängt, also im wide Format).
<-rio::import("http://www.pt-wissen.ch/Statistik_BSc_Physiotherapie_Leukerbad/summary_walk_sit_hop.csv", encoding="UTF-8")
data_long_widekbl(data_long_wide, caption='Daten im long-wide Format') %>% kable_styling()
Gelenk | perc_change_Geh_Test | perc_change_Sit_to_Stand_Test | perc_change_Hop_Test |
---|---|---|---|
Hüfte | 8% | 17% | 6% |
Knie | 9% | 18% | 27% |
Nun werden wir zuerst die Daten komplett ins long Format transformieren. In diesem Fall könnte man sagen, dass danach die Daten im long-long Format sind, da beide Variablen Gelenk und Outcome als long formatiert sind.
<-data_long_wide %>%
data_long_longpivot_longer(
cols= starts_with("perc"),
names_to = "Outcome",
names_prefix = "perc_change_",
values_to="value"
) kbl(data_long_long, caption='Daten im long-long Format') %>% kable_styling()
Gelenk | Outcome | value |
---|---|---|
Hüfte | Geh_Test | 8% |
Hüfte | Sit_to_Stand_Test | 17% |
Hüfte | Hop_Test | 6% |
Knie | Geh_Test | 9% |
Knie | Sit_to_Stand_Test | 18% |
Knie | Hop_Test | 27% |
Doch wir möchten nun eine Tabelle, in der die beiden Gelenke Knie und Hüfte je eine Spalte besetzen. Deshalb transformieren wir die long-long Daten in ein wide-long format.
<-data_long_long %>%
data_wide_longpivot_wider(
names_from = Outcome,
values_from=value,
)kbl(data_wide_long, caption='Daten im wide-long Format') %>% kable_styling()
Gelenk | Geh_Test | Sit_to_Stand_Test | Hop_Test |
---|---|---|---|
Hüfte | 8% | 17% | 6% |
Knie | 9% | 18% | 27% |
Natürlich könnten wir es auch gerade umgekehrt darstellen.
<-data_long_long %>%
data_wide_long2pivot_wider(
names_from = Gelenk,
values_from=value,
)kbl(data_wide_long2, caption='Daten im wide-long Format') %>% kable_styling()
Outcome | Hüfte | Knie |
---|---|---|
Geh_Test | 8% | 9% |
Sit_to_Stand_Test | 17% | 18% |
Hop_Test | 6% | 27% |
58.5 Oh, ein Beispiel haben wir noch.
Wir haben drei Variablen mit den Antwortsoptionen für die STarTBack Risiko-Kategorien Low, Medium, High-Risk. Siehe hier.
set.seed(666)
=1:200
id=sample(c("Low-Risk", "Medium-Risk", "High-Risk"), size=200, replace=TRUE, prob=c(0.34, 0.42, 0.24))
Kategorie.t0=sample(c("Low-Risk", "Medium-Risk", "High-Risk", NA), size=200, replace=TRUE, prob=c(0.38, 0.39, 0.20,0.03))
Kategorie.t1=sample(c("Low-Risk", "Medium-Risk", "High-Risk", NA), size=200, replace=TRUE, prob=c(0.38, 0.37, 0.19,0.06))
Kategorie.t2
<-data.frame(id, Kategorie.t0, Kategorie.t1, Kategorie.t2)
data
head(data)
## id Kategorie.t0 Kategorie.t1 Kategorie.t2
## 1 1 High-Risk Medium-Risk <NA>
## 2 2 Medium-Risk Medium-Risk High-Risk
## 3 3 High-Risk Medium-Risk High-Risk
## 4 4 Medium-Risk Medium-Risk Low-Risk
## 5 5 Medium-Risk <NA> Medium-Risk
## 6 6 Low-Risk Low-Risk Low-Risk
Wir möchten nun eine Tabelle erstellen, um die relative Häufigkeit der Kategorien zu berechnen. Das können wir zum Beispiel tun, indem wir die Tabelle zuerst in ein long Format umwandeln.
By the way, natürlich könnten wir dies mit summarytools::freq(data$Kategorie.t0) etc sehr einfach tun. Doch manchman möchten wir die Tabelle mit den Zusammenfassungen noch für weitere Analysen benutzen, wie zum Beispiel die Berechnungen der Veränderungen oder für ggplot Graphiken.
Hier das Beispiel mit summarytools::freq.
::freq(data$Kategorie.t0) summarytools
## Frequencies
## data$Kategorie.t0
## Type: Character
##
## Freq % Valid % Valid Cum. % Total % Total Cum.
## ----------------- ------ --------- -------------- --------- --------------
## High-Risk 49 24.50 24.50 24.50 24.50
## Low-Risk 65 32.50 57.00 32.50 57.00
## Medium-Risk 86 43.00 100.00 43.00 100.00
## <NA> 0 0.00 100.00
## Total 200 100.00 100.00 100.00 100.00
Nun machen wir es aber auf die harte Tour:
<-data %>%
data_longpivot_longer(cols=-id,
names_pattern="(.+)\\.(.+)",
names_to=c(".value", "Zeitpunkt"))
head(data_long)
## # A tibble: 6 × 3
## id Zeitpunkt Kategorie
## <int> <chr> <chr>
## 1 1 t0 High-Risk
## 2 1 t1 Medium-Risk
## 3 1 t2 <NA>
## 4 2 t0 Medium-Risk
## 5 2 t1 Medium-Risk
## 6 2 t2 High-Risk
Nun können mit der dplyr::summarise Funktion sehr einfach die Prozente berechnen.
In der Variante 1 berechnen wir die Prozente unter Berücksichtigung der fehlenden Werte (d.h. 100 bezieht sich auf den kompletten Datensatz von 200, und wir berechnen die Prozente der Missing Values auch).
<-data_long %>%
summary_table_variante_1group_by(Zeitpunkt, Kategorie) %>%
summarise(n=n()) %>%
mutate(Prozente=round(n/sum(n)*100,1))
## `summarise()` has grouped output by 'Zeitpunkt'. You can override using the
## `.groups` argument.
kbl(summary_table_variante_1, caption="Absolute und relative Häufigkeit berechnet auf 200 Personen.") %>% kable_styling()
Zeitpunkt | Kategorie | n | Prozente |
---|---|---|---|
t0 | High-Risk | 49 | 24.5 |
t0 | Low-Risk | 65 | 32.5 |
t0 | Medium-Risk | 86 | 43.0 |
t1 | High-Risk | 45 | 22.5 |
t1 | Low-Risk | 77 | 38.5 |
t1 | Medium-Risk | 72 | 36.0 |
t1 | NA | 6 | 3.0 |
t2 | High-Risk | 40 | 20.0 |
t2 | Low-Risk | 75 | 37.5 |
t2 | Medium-Risk | 77 | 38.5 |
t2 | NA | 8 | 4.0 |
In der nächsten Variante berechnen wir die Prozente nur in Bezug auf die Personen, die keine Missing Values haben. Wir brauchen dazu wieder die length2 Funktion. Dank geht auch hier wieder an http://www.cookbook-r.com/Manipulating_data/Summarizing_data/. Damit wir in der Tabelle die Missing Values auch als Prozente sehen, müssen wir etwas tricksen. Die Prozente der Missing Values beziehen sich auf die 200 Personen. Die Prozente der nicht fehlenden Kategorien beziehen sich hier auf die Personen ohne Missing Values in der Variable Kategorie.
# New version of length which can handle NA's: if na.rm==T, don't count them
<- function (x, na.rm=FALSE) {
length2 if (na.rm) sum(!is.na(x))
else length(x)
}
<-data_long %>%
summary_table_variante_2group_by(Zeitpunkt, Kategorie) %>%
summarise(n=length2(Kategorie, na.rm=TRUE),
total_incl_missing=n(),
missing=sum(is.na(Kategorie))) %>%
mutate(Prozente=round(ifelse(is.na(Kategorie),missing/sum(total_incl_missing)*100, n/sum(n)*100),1)) %>%
mutate(n=ifelse(is.na(Kategorie), missing, n)) %>%
select(-missing,-total_incl_missing)
kbl(summary_table_variante_2, caption="Absolute und relative Häufigkeit berechnet auf Personen ohne Missing Values in der Variable Kategorie.") %>% kable_styling()
Zeitpunkt | Kategorie | n | Prozente |
---|---|---|---|
t0 | High-Risk | 49 | 24.5 |
t0 | Low-Risk | 65 | 32.5 |
t0 | Medium-Risk | 86 | 43.0 |
t1 | High-Risk | 45 | 23.2 |
t1 | Low-Risk | 77 | 39.7 |
t1 | Medium-Risk | 72 | 37.1 |
t1 | NA | 6 | 3.0 |
t2 | High-Risk | 40 | 20.8 |
t2 | Low-Risk | 75 | 39.1 |
t2 | Medium-Risk | 77 | 40.1 |
t2 | NA | 8 | 4.0 |
Das gleiche Ergebnis bekommen wir mit folgendem Code, ausser dass wir die Missing Values nicht ausgeben können.
<-data_long %>%
summary_table_variante_3filter(!is.na(Kategorie)) %>%
group_by(Zeitpunkt, Kategorie) %>%
summarise(n=n()) %>%
mutate(Prozente=round(n/sum(n)*100,1))
kbl(summary_table_variante_3, caption="Absolute und relative Häufigkeit berechnet auf 200 Personen.") %>% kable_styling()
Zeitpunkt | Kategorie | n | Prozente |
---|---|---|---|
t0 | High-Risk | 49 | 24.5 |
t0 | Low-Risk | 65 | 32.5 |
t0 | Medium-Risk | 86 | 43.0 |
t1 | High-Risk | 45 | 23.2 |
t1 | Low-Risk | 77 | 39.7 |
t1 | Medium-Risk | 72 | 37.1 |
t2 | High-Risk | 40 | 20.8 |
t2 | Low-Risk | 75 | 39.1 |
t2 | Medium-Risk | 77 | 40.1 |
58.6 Häufigkeitstabellen mit mehr als einer Variable
Wenn wir mehr als eine Variable haben, müssen wir nach der ersten long umwandlung noch ein zweites Mal pivot_longer ausführen.
<-rio::import("http://www.pt-wissen.ch/Statistik_BSc_Physiotherapie_Leukerbad/zufriedenheit.csv", encoding="UTF-8")
data
<-data%>%
data_longpivot_longer(cols=everything(),
names_pattern = "(.+)\\.(.+)",
names_to=c(".value", "Zeitpunkt"))
::datatable(data_long) DT
So wie die Daten jetzt sind, können wir noch nicht einfach eine Häufigkeitstabelle erstellen. Einfacher geht es, wenn wir noch einmal pivot_longer anwenden.
<-data_long %>%
data_long_longpivot_longer(cols=-Zeitpunkt,
names_to="Variable",
values_to="Zufriedenheit")
::datatable(data_long_long) DT
Jetzt können wir ganz einfach mit dplyr::sumarise eine Häufigkeitstabelle erstellen. Damit wir die Missing Values korrekt berücksichtigen, müssen wir die lehren Zellen mit NA ersetzen und wieder die length2 Funktion benutzen.
==""]<-NA
data_long_long[data_long_long
<- function (x, na.rm=FALSE) {
length2 if (na.rm) sum(!is.na(x))
else length(x)
}<-data_long_long %>%
summary_table_Zufriedenheitgroup_by(Zeitpunkt, Variable, Zufriedenheit) %>%
summarise(n=length2(Zufriedenheit, na.rm=TRUE),
total_incl_missing=n(),
missing=sum(is.na(Zufriedenheit))) %>%
mutate(Prozente=round(ifelse(is.na(Zufriedenheit),missing/sum(total_incl_missing)*100, n/sum(n)*100),1)) %>%
mutate(n=ifelse(is.na(Zufriedenheit), missing, n)) %>%
select(-missing,-total_incl_missing)
## `summarise()` has grouped output by 'Zeitpunkt', 'Variable'. You can override
## using the `.groups` argument.
::kbl(summary_table_Zufriedenheit) %>% kableExtra::kable_styling() kableExtra
Zeitpunkt | Variable | Zufriedenheit | n | Prozente |
---|---|---|---|---|
t1 | Zufrieden_mit.Therapie | In hohem Masse | 3 | 13.0 |
t1 | Zufrieden_mit.Therapie | Mässi | 2 | 8.7 |
t1 | Zufrieden_mit.Therapie | Sehr | 18 | 78.3 |
t1 | Zufrieden_mit.Zustand | Ja | 10 | 43.5 |
t1 | Zufrieden_mit.Zustand | Nein | 7 | 30.4 |
t1 | Zufrieden_mit.Zustand | Sehr | 6 | 26.1 |
t2 | Zufrieden_mit.Therapie | Mässi | 4 | 30.8 |
t2 | Zufrieden_mit.Therapie | Sehr | 9 | 69.2 |
t2 | Zufrieden_mit.Therapie | NA | 10 | 43.5 |
t2 | Zufrieden_mit.Zustand | In hohem Masse | 1 | 4.8 |
t2 | Zufrieden_mit.Zustand | Ja | 1 | 4.8 |
t2 | Zufrieden_mit.Zustand | Mässi | 6 | 28.6 |
t2 | Zufrieden_mit.Zustand | Nein | 4 | 19.0 |
t2 | Zufrieden_mit.Zustand | Sehr | 9 | 42.9 |
t2 | Zufrieden_mit.Zustand | NA | 2 | 8.7 |
t3 | Zufrieden_mit.Therapie | Mässi | 3 | 27.3 |
t3 | Zufrieden_mit.Therapie | Nein | 3 | 27.3 |
t3 | Zufrieden_mit.Therapie | Sehr | 5 | 45.5 |
t3 | Zufrieden_mit.Therapie | NA | 12 | 52.2 |
t3 | Zufrieden_mit.Zustand | Mässi | 2 | 18.2 |
t3 | Zufrieden_mit.Zustand | Nein | 2 | 18.2 |
t3 | Zufrieden_mit.Zustand | Sehr | 7 | 63.6 |
t3 | Zufrieden_mit.Zustand | NA | 12 | 52.2 |