Randomisation

Übung Forschungsmethodik II | SS 2024

Autor
TU Chemnitz

C. Maiwald

Professur Forschungsmethoden und Analyseverfahren in der Biomechanik

Datum

11. April 2024

Ausgangssituation

Die für uns relevanten Randomisationsarten greifen wir mit steigender Komplexiät in den folgenden Abschnitten und Übungsaufgaben auf. Wir orientieren uns dabei jeweils an fiktiven Studienszenarien.

An diese Randomisationslisten wird immer die Anforderung gestellt, dass sie (a) eine zufällige Zuteilung der Personen zu den Untersuchungsbedingungen enthält und (b) reproduzierbar sein muss.

Als letzte Aufgabe werden wir eine der Listen als Textdatei (PDF) exportieren, so dass eine Bearbeitung (bzw. Abarbeitung) bzw. ein Versand per E-Mail erleichtert wird und keine Manipulationen mehr möglich sind.

Einfache Randomisation

Ausgangspunkt ist das bereits öfter zitierte Beispiel der DiGA vs. PT Studie. Probanden sollen in zwei Behandlungsarme randomisiert werden, Stratifikationsmerkmale sind in diesem Fall nicht vorhanden. Wir gehen von einem monozentrischen Design aus, d. h. ein Studienzentrum rekrutiert alle Probanden, es benötigt daher auch nur eine Liste. Als Fallzahl sind 60 Personen pro Behandlungsarm vorgesehen.

Aufgabe
  1. Erzeuge eine Randomisationsliste, welche die insgesamt 120 Probanden zufällig auf beide Behandlungsarme verteilt.

  2. Erzeuge eine restriktivere Liste, welche die Probanden im Verhältnis 1:1 auf beide Studienarme verteilt.

  3. Prüfe das Zuteilungsverhältnis und gib eine geeignete Häufigkeitstabelle aus.

# Ohne Fallzahlvorgabe pro Arm
set.seed(1)
ZZ <- runif(120)
RL.einfach <- data.frame(Proband = seq(1:120), Behandlung=ifelse(ZZ > 0.5, "DiGA", "PT"))

table(RL.einfach$Behandlung)

DiGA   PT 
  57   63 
# Mit Fallzahlvorgabe pro Arm

set.seed(1)
BEHANDLUNG <- character()
DIGA <- sample(1:120, size=60)
for(i in 1:120){
  BEHANDLUNG[i] <- ifelse(is.element(i, DIGA), "DiGA", "PT" )
}
RL.einfach.fallzahl <- data.frame(Proband = seq(1:120), Behandlung=BEHANDLUNG)

table(RL.einfach.fallzahl$Behandlung)

DiGA   PT 
  60   60 

Block-Randomisation

Auch hier greifen wir auf das DiGA vs. PT Beispiel zurück. Für die Zuordnung zu den Behandlungsarmen soll sichergestellt werden, dass nach der Hälfte der insgesamt einzuschließenden Probanden (n=30 pro Arm) die beiden Behandlungsarme bereits mit exakt gleich vielen Patienten “gefüllt” sind. Dasselbe soll auch am Ende der Rekrutierung bei n=60 pro Arm erfüllt sein. Eine Stratifizierung ist hier nicht vorgesehen.

Aufgabe
  1. Erzeuge die Randomisationslisten einer solchen Block-Randomisation.
# Im ersten Block werden 30 Probanden pro Arm randomisiert, also 60 insgesamt. Wir erzeugen zunächst die 30 zufälligen Probanden, welche die DiGA erhalten, danach füllen wir die übrigen mit PT auf.

BEHANDLUNG <- character()
DIGA <- sample(1:60, size=30)

set.seed(1) # Seed für ersten Block

for(i in 1:60){
  BEHANDLUNG[i] <- ifelse(is.element(i, DIGA), "DiGA", "PT" )
}


RL.block1 <- data.frame(PROBAND = seq(1:60), Behandlung = BEHANDLUNG)
table(RL.block1$Behandlung)

DiGA   PT 
  30   30 
set.seed(2) # Seed für zweiten Block
BEHANDLUNG2 <- character()
DIGA2 <- sample(1:60, size=30)
for(i in 1:60){
  BEHANDLUNG2[i] <- ifelse(is.element(i, DIGA2), "DiGA", "PT" )
}

RL.block2 <- data.frame(PROBAND = seq(1:60), Behandlung = BEHANDLUNG2)
table(RL.block2$Behandlung)

DiGA   PT 
  30   30 

Stratifizierte Randomisation

Wir greifen das DiGA vs. PT Beispiel erneut auf. Anstelle einer einfachen oder blockweisen Randomisation soll nun nach zwei Kriterien stratifiziert werden:

  1. Geschlecht: M, W
  2. Rekrutierungszentrum: RZ.1, RZ.2, RZ.3

Dabei belassen wir die Gesamtfallzahl wieder bei n=60 pro Behandlungsarm.

Tipp

Da wir nun in zwei Geschlechtern und drei Zentren getrennt randomisieren (unabhängig von eventuell weiteren Vorgaben zum Proporz der Strata, siehe unten), resultiert das in separaten Randomisationslisten für jede Ausprägungskombination der involvierten Stratifikationsmerkmale.

Wir spielen dies anhand zweier Szenarien durch:

  1. Liberaler Fall: wir lassen zu, dass theoretisch ein Rekrutierungszentrum alle Patienten einschleust. Obendrein gibt es keine Vorgabe zum Geschlechterverhältnis, d. h. im Zweifel entsteht hier eine große Dysbalance (z. B. deutlich mehr Männer als Frauen in der Studie)

  2. Restriktiver Fall: wir fordern ein, dass jedes Rekrutierungszentrum genau ein Drittel aller Probanden beisteuern und obendrein Männer und Frauen im Verhältnis von 1:1 in den Probandenzahlen vorkommen müssen (restriktiver Fall)

Aufgabe
  1. Erzeuge Randomisationslisten für die jeweiligen Kombinationen der Strata.

  2. Gib die Häufigkeitstabellen der Zuordnung zu den Behandlungsarmen für die jeweiligen Strata aus.

# 2 Geschlechter x 3 Zentren ergibt 6 getrennte Listen.

GESCHLECHT <- c("M", "W")
ZENTRUM <- c("RZ.1", "RZ.2", "RZ.3")


## Liberaler Fall
set.seed(10)
for(i in 1:2){
  for(j in 1:3){
    LISTE <- paste0(ZENTRUM[j],".",GESCHLECHT[i])
    ZZ <- runif(120)
    BEHANDLUNG <- ifelse(ZZ > 0.5, "DiGA", "PT")
    assign(LISTE, data.frame(PROBAND=seq(1:120), Behandlung=BEHANDLUNG))
  }
}

table(RZ.1.W$Behandlung)

DiGA   PT 
  55   65 
table(RZ.1.M$Behandlung)

DiGA   PT 
  54   66 
table(RZ.2.W$Behandlung)

DiGA   PT 
  67   53 
table(RZ.2.M$Behandlung)

DiGA   PT 
  64   56 
table(RZ.3.W$Behandlung)

DiGA   PT 
  67   53 
table(RZ.3.M$Behandlung)

DiGA   PT 
  65   55 
## Restriktiver Fall
## Wir geben pro Kombination der Strata sowohl Fallzahl als auch Geschlechterproporz vor. D. h. pro Liste (2x3=6 Listen) werden 20 Probanden eingeschleust, exakt 10 DiGA und 10 PT. Das Vorgehen ähnelt damit jenem der Block-Randomisation, nur wiederholen wir das pro Liste.

LISTE <- c("RZ.1.M", "RZ.1.W", "RZ.2.M", "RZ.2.W", "RZ.3.M", "RZ.3.W")

for(n in 1:length(LISTE)){
  set.seed(n)
  BEHANDLUNG <- character()
  DIGA <- sample(1:20, size=10)
  for(i in 1:20){
    BEHANDLUNG[i] <- ifelse(is.element(i, DIGA), "DiGA", "PT" )
  }
  assign(LISTE[n], data.frame(PROBAND=seq(1:20), Behandlung=BEHANDLUNG))
}

table(RZ.1.W$Behandlung)

DiGA   PT 
  10   10 
table(RZ.1.M$Behandlung)

DiGA   PT 
  10   10 
table(RZ.2.W$Behandlung)

DiGA   PT 
  10   10 
table(RZ.2.M$Behandlung)

DiGA   PT 
  10   10 
table(RZ.3.W$Behandlung)

DiGA   PT 
  10   10 
table(RZ.3.M$Behandlung)

DiGA   PT 
  10   10 

Intra-individuelle Randomisation von Versuchsbedingungen

Als Studienbeispiel nutzen wir eine biomechanische Laboruntersuchung, in welcher die Wirkung eines aktiven Arm-Hand-Exoskeletts für Greiftätigkeiten auf die Muskelaktivität des Unterarms untersucht werden soll. Das Exoskelett kann in drei Modi arbeiten: off (ohne aktive Unterstützung, äquivalent zu einer Bedingung ohne Exoskelett), min (minimale aktive Unterstützung des Exoskeletts) und max (maximale aktive Unterstützung des Exoskeletts). Alle Probanden werden in allen drei Modi des Exoskeletts untersucht, wobei die Reihenfolge der Modi pro Proband randomisiert werden muss. Als Fallzahl ist n=30 vorgesehen.

Aufgabe
  1. Erzeuge eine Randomisationsliste für diese Studie, so dass der Versuchsleiter für alle 30 Probanden eine randomisierte Reihenfolge der Versuchsbedingungen (off, min, max) zur Verfügung hat. Es soll darüber hinaus sichergestellt sein, dass die Modi über alle 30 Probanden hinweg jeweils gleich häufig vorkommen.

  2. Erzeuge eine Häufigkeitstabelle, aus der hervorgeht, dass die jeweiligen Bedingungen an erster, zweiter oder dritter Stelle auch wirklich gleich häufig vorkommen.1

# Zufallsmodus: Problematisch, da nicht sichergestellt ist, dass alle Permutationen gleich häufig vorkommen

# Reihenfolge der Bedingungen als "Sampling ohne Zurücklegen"
BED <- c("off", "min", "max")
RL.intra <- data.frame(Proband=seq(1:30), B1=NA, B2=NA, B3=NA)

set.seed(20)
for(i in 1:30){
  S <- sample(BED, size=3, replace = FALSE)
  RL.intra[i,2:4] <- S
  
}


RL.intra.long <- stack(RL.intra, select = c(B1, B2, B3))
table(RL.intra.long$value, RL.intra.long$ind)
     
      B1 B2 B3
  max  5 11 14
  min 10  9 11
  off 15 10  5
# Damit stellt man allerdings nicht sicher, dass die Kombinationen ausbalanciert sind. D. h. es kann zu einem ungewollten Überhang von bestimmten Bedingungen an einer der drei Versuchspositionen kommen.

# Daher besser: mögliche Permutationen der Bedingungen vorher festlegen, dann zufällig verfielfältigen
library(combinat)

Attache Paket: 'combinat'
Das folgende Objekt ist maskiert 'package:utils':

    combn
## Insgesamt 6 Permutationen der drei Bedingungen möglich:
PERMUT <- permn(BED)
print(PERMUT)
[[1]]
[1] "off" "min" "max"

[[2]]
[1] "off" "max" "min"

[[3]]
[1] "max" "off" "min"

[[4]]
[1] "max" "min" "off"

[[5]]
[1] "min" "max" "off"

[[6]]
[1] "min" "off" "max"
S <- character()
set.seed(20)
for(i in 1:5){
  I <- sample(1:6, 6)
  FOLGE <- unlist(PERMUT[I])
  S <- c(S, FOLGE)
}

RL.intra <- data.frame(Proband = seq(1:30), matrix(S, nrow=30, byrow = TRUE))
colnames(RL.intra) <- c("Proband", "B1", "B2", "B3")

table(RL.intra$B1)

max min off 
 10  10  10 
table(RL.intra$B2)

max min off 
 10  10  10 
table(RL.intra$B3)

max min off 
 10  10  10 

Ausgabe / Export der Randomisationsliste

Für die viele (auch studentische) Anwendungsfälle ist eine Ausgabe der Randomisationsliste als Textdatei bzw. PDF ausreichend, welche dann im Fall von PDF auch nicht mehr nachträglich manipulierbar ist und im Labor in Form eines Ausdrucks auf Papier direkt verwendet werden kann. In wenigen Ausnahmen (z. B. für Umsetzung der Randomisation in webbasierter Software in klinischen Studien) ist eine Ausgabe in einem Tabellenformat (z. B. Excel) vorteilhafter.

Aufgabe

Gib die Liste der intraindividuellen Randomisation sowohl als Textdatei im PDF-Format als auch in Form einer Excel-Tabelle aus.

library(gridExtra)
# Damit wird die Tabelle zu einem Textobjekt im PDF. A4 Größe in Zoll angeben!
pdf("Randomisation_intraindividuell_PDF.pdf", width=8.27, height=11.69)
grid.table(RL.intra, rows=NULL)
dev.off()
png 
  2 
library(writexl)
write_xlsx(RL.intra, "Randomisation_intraindividuell_Excel.xlsx")

Fußnoten

  1. Hinweis: Das geht natürlich nur, wenn die Anzahl der Veruschsbedingungen und die Anzahl der Probanden in einem geeigneten Vielfachen zueinander stehen. Dies ist in unserem Fall aber gegeben.↩︎