Skip to content

Experimentablauf: Bedingungen, Überspringen, Screen-outs und Ausbalancierung

Teilnehmende Between-Subjects-Bedingungen zuweisen, per Regel Seiten überspringen oder Teilnehmende ausschließen, die Seitenreihenfolge per lateinischem Quadrat ausbalancieren und jede Zuweisung exportieren.

Neu in v2.12.0

Potato 2.12 bringt fünf Einstellungen für das Design eines Experiments mit. Jede besteht aus wenigen Zeilen YAML, und alles, was Teilnehmenden zugewiesen oder gezeigt wurde, wird aufgezeichnet, sodass die CSV- und TSV-Exporte es in participants.csv schreiben können.

EinstellungFunktion
conditionsWeist jede teilnehmende Person einer Zelle eines Between-Subjects-Designs zu
show_when auf einer PhasenseiteÜberspringt die Seite, es sei denn, eine Regel trifft zu
exit_when auf einer PhasenseiteBeendet die Studie für die teilnehmende Person, wie es ein Screener tut
phases.counterbalanceOrdnet eine Gruppe von Seiten pro teilnehmender Person an, zufällig oder per lateinischem Quadrat
randomize_questions auf einer UmfrageseiteOrdnet die Fragen dieser Seite pro teilnehmender Person an

Diese Einstellungen wirken auf die Phasenseiten, die unter Mehrphasige Workflows beschrieben sind: consent, prestudy, instructions, training, annotation und poststudy, dazu die Laufzeitseiten, die eine jsPsych-Timeline, einen Kopfhörertest oder eine externe Aufgabe ausführen.

Bedingungen

yaml
conditions:
  factors:
    feedback: [none, immediate]
    font: [serif, sans]
  assignment: balanced        # balanced | random | round_robin
  balance_on: assigned        # assigned | completed
  max_per_cell: 40            # optional

Zwei Faktoren mit je zwei Stufen ergeben vier Zellen. Eine teilnehmende Person wird einer Zelle zugewiesen, sobald der Server sie zum ersten Mal sieht, und behält diese nach einem Neuladen der Seite oder einem Serverneustart.

SchlüsselStandardwertBedeutung
factorserforderlichFaktorname, zugeordnet zu einer Liste von mindestens zwei Stufen
assignmentbalancedbalanced wählt die Zelle mit den wenigsten Teilnehmenden und löst Gleichstände pro teilnehmender Person zufällig auf. random zieht eine Zelle, mit einem Seed pro teilnehmender Person. round_robin durchläuft die Zellen in der Reihenfolge des Eintreffens
balance_onassignedcompleted zählt nur Teilnehmende, die das Ende erreicht haben, ohne ausgeschlossen worden zu sein, sodass ein Abbruch durch die nächste eintreffende Person ersetzt wird
max_per_cellkeinerEine volle Zelle wird übersprungen. Sind alle Zellen voll, wird die am wenigsten gefüllte verwendet und eine Warnung protokolliert
cellsvollständiges faktorielles DesignEine explizite Liste von Zellen, eine Teilmenge des faktoriellen Designs, jeweils mit optionalem weight

Gewichtete Zellen geben einer Bedingung einen größeren Anteil der Teilnehmenden:

yaml
conditions:
  factors:
    prime: [none, positive, negative]
  cells:
    - {prime: none, weight: 2}
    - {prime: positive}
    - {prime: negative}

Setzen Sie Stufennamen in Anführungszeichen, die YAML als Boolesche Werte liest ("yes", "no", "on", "off"). Validator und Server melden einen nicht in Anführungszeichen gesetzten Namen beide als Fehler.

Bedingungen in Regeln prüfen

Regeln sprechen einen Faktor als condition.<factor> an, in show_when von Seiten, in exit_when von Seiten und in display_logic von Fragen. Der Wert, mit dem ein Faktor verglichen wird, muss eine seiner Stufen sein, weil ein Tippfehler die Seite oder Frage sonst vor allen verbergen würde. Der Validator meldet einen Wert, der keine Stufe ist.

yaml
- name: feedback_rating
  annotation_type: likert
  description: How useful was the feedback?
  size: 5
  display_logic:
    show_when:
      - {schema: condition.feedback, operator: equals, value: immediate}

Eine Frage, die durch ihre Bedingung ausgeblendet ist, ist nicht erforderlich, weder auf der Seite noch auf dem Server.

Unterschiedliche Items für jede Zelle

Um jeder Zelle eigene Items zu geben, benennen Sie Batch-Gruppen nach den Stufen eines Faktors. So weist ein Listendesign mit lateinischem Quadrat jeder teilnehmenden Person eine Liste zu:

yaml
conditions:
  factors:
    list: [list_a, list_b]
assignment_strategy: batch
batch_assignment:
  auto_assign_annotators: true
  group_by_condition: list
  groups:
    - {name: list_a, data_file: data/list_a.jsonl}
    - {name: list_b, data_file: data/list_b.jsonl}

Item-IDs müssen über alle Datendateien hinweg eindeutig sein, auch über die Dateien verschiedener Gruppen. Der Server startet nicht, wenn zwei Listen eine ID teilen. Ein Stimulus, der in beiden Listen vorkommt, braucht daher in jeder eine eigene ID, etwa h1_a und h1_b.

Eine jsPsych-Timeline erhält die Bedingungen der teilnehmenden Person als potato.conditions, und ihre Trial-Daten bekommen eine Spalte condition_<factor> pro Faktor. Siehe Laufzeitphasen.

Formulierung pro Bedingung

{condition.<factor>} wird überall auf einer Seite, im Item-Text, in der Formulierung von Fragen oder in Optionsbeschriftungen, durch die Stufe ersetzt, die die teilnehmende Person in diesem Faktor hat. Ein Endorsement-Experiment oder eine faktorielle Vignette variiert ihren Text auf diese Weise:

yaml
conditions:
  factors:
    endorser: ["The city council", "A neighbourhood association"]
json
{"id": "p1", "text": "{condition.endorser} proposes turning the car park into a park."}

Die Ersetzung wird HTML-escaped. Ein Platzhalter für einen Faktor, in dem die teilnehmende Person keine Stufe hat, bleibt unverändert auf der Seite stehen, sodass ein Tippfehler beim Testen auffällt. Ein Element mit data-condition-only="factor=level" wird für alle außerhalb dieser Stufe entfernt. Auf diese Weise zeigt ein Listenexperiment die sensible Aussage nur der Treatment-Gruppe.

Exporte schreiben den Item-Text so, wie er in der Datendatei steht, mit dem Platzhalter. Span-Offsets zählen die Zeichen des ausgefüllten Texts, so wie die teilnehmende Person ihn gesehen hat. Ein Span nach einem Platzhalter passt daher nicht zum exportierten Text. Verschieben Sie ihn entweder um den Längenunterschied zwischen dem Platzhalter und der Stufe der teilnehmenden Person (deren Bedingungen stehen im Export), oder halten Sie Platzhalter aus Text heraus, der mit Spans annotiert wird.

Seiten mit show_when überspringen

yaml
phases:
  order: [screener, smoking_followup, general, annotation]
  screener:
    type: prestudy
    file: surveys/screener.json
  smoking_followup:
    type: prestudy
    file: surveys/smoking.json
    show_when:
      - {schema: smoker, operator: equals, value: "Yes"}
  general:
    type: prestudy
    file: surveys/general.json

Die Grammatik ist dieselbe, die bedingte Fragen auf Fragenebene verwenden: eine Liste von Bedingungen mit schema, operator und value, verknüpft mit logic: all (Standard) oder logic: any, mit denselben 19 Operatoren und verschachtelten Gruppen all, any und not. Eine Regel kann jede Frage prüfen, die auf einer früheren Seite gestellt wurde, in jeder Phase, sowie jedes condition.<factor>.

Die Regel wird geprüft, wenn die teilnehmende Person die Seite davor verlässt. Eine ausgeblendete Seite wird in beide Richtungen übergangen: Next überspringt sie, und Previous landet nicht auf ihr. Jedes Überspringen wird aufgezeichnet.

Der Server verweigert den Start mit einer Regel, die eine Frage nennt, die keine Seite stellt, oder eine, die auf derselben oder einer späteren Seite gestellt wird, da diese Frage immer unbeantwortet wäre. Die Annotationsphase selbst lässt sich nicht überspringen.

Ausschluss mit exit_when

yaml
phases:
  screener:
    type: prestudy
    file: surveys/screener.json
    exit_when:
      show_when:
        - {schema: age, operator: lt, value: 18}
      message: This study is for adults only. Thank you for your time.

Die Regel wird geprüft, wenn die teilnehmende Person die Seite absendet, sodass sie Fragen auf dieser Seite prüfen kann. Trifft sie zu, gelangt die Person ans Ende der Studie:

  • Ohne Crowdsourcing-Anbieter sieht sie message.
  • Mit einem Anbieter (Prolific, SONA, CloudResearch Connect und die anderen) erhält sie das Screen-out-Ergebnis der Plattform und nie den Abschlusscode.

exit_when funktioniert auf Seiten vom Typ consent, prestudy, instructions und poststudy. Eine ausgeschlossene Person bleibt am Ende der Studie. Previous bringt sie nicht zurück, auch nicht mit allow_phase_back_navigation, und der Server speichert nichts mehr, was sie sendet. Antworten, die sie vor dem Ausschluss gegeben hat, bleiben in user_state.json, und der Ausschluss wird in participants.csv geschrieben, nicht in annotations.csv.

Ausbalancierte Seitenreihenfolge

yaml
phases:
  order: [intro, block_a, block_b, block_c, annotation]
  # ...block definitions...
  counterbalance:
    - pages: [block_a, block_b, block_c]
      method: latin_square        # or random

Die Seiten behalten die Plätze, die sie in order einnehmen, und jede teilnehmende Person erhält ihre eigene Anordnung davon.

  • random zieht eine Permutation mit einem Seed auf die teilnehmende Person, sodass sie nach einem Neuladen oder Neustart gleich bleibt.
  • latin_square nimmt Zeilen eines balancierten (Williams-)lateinischen Quadrats in der Reihenfolge des Eintreffens. Sind conditions konfiguriert, wird die Eintreffreihenfolge innerhalb jeder Zelle gezählt. So durchläuft jede Bedingung das ganze Quadrat, und die Seitenreihenfolge ist innerhalb jeder Bedingung ausbalanciert, statt mit ihr konfundiert zu sein. Bei einer ungeraden Anzahl von Seiten hat das Quadrat doppelt so viele Zeilen. Die Zähler werden beim Serverneustart aus den gespeicherten Zuständen neu aufgebaut.

Alle Seiten einer Gruppe müssen denselben Phasentyp haben. Seiten verschiedener Typen stehen in einer Studie nie nebeneinander und könnten daher nicht die Plätze tauschen.

Fragenreihenfolge auf einer Umfrageseite

yaml
phases:
  big_five:
    type: poststudy
    instrument: tipi
    randomize_questions:
      pin_last: [comments]     # or: randomize_questions: true

Jede teilnehmende Person sieht die Fragen der Seite in ihrer eigenen Reihenfolge, mit einem Seed auf Person und Seite, aufgezeichnet beim ersten Anzeigen der Seite. pin_first und pin_last halten benannte Fragen am Anfang oder Ende. Seiten, die mit layout.groups gestaltet sind, behalten ihre Reihenfolge. Die Reihenfolge der Optionen innerhalb einer Frage ist eine eigene Einstellung, randomize_order am Schema.

Der Ablaufdatensatz

user_state.json enthält für jede teilnehmende Person einen flow_record:

SchlüsselInhalt
conditions, condition_cell, condition_ordinalDie zugewiesene Zelle und die studienweite Eintreffnummer
cell_ordinalEintreffnummer innerhalb der Zelle, die bei konfigurierten Bedingungen die Zeile des lateinischen Quadrats bestimmt
latin_ordinalEintreffnummer für Zeilen des lateinischen Quadrats, wenn keine Bedingungen konfiguriert sind
page_ordersDie Reihenfolge jeder ausbalancierten Gruppe
question_ordersDie Fragenreihenfolge jeder randomisierten Seite
skipped_pagesSeiten, die durch show_when übergangen wurden
screened_outSeite und Zeitpunkt eines Ausschlusses
runtimesArt, Status, Versuche, Seitenaufrufe, Anzahl der Trials und Lauf-ID jeder Laufzeitseite
runtime_answersWas Laufzeitseiten aus ihren Läufen abgeleitet haben, etwa <page>_passed eines Kopfhörertests

Die CSV- und TSV-Exporte schreiben eine Zeile pro teilnehmender Person in participants.csv (oder .tsv). Mit einem Faktor feedback lautet die Kopfzeile:

text
user_id,condition_feedback,condition_ordinal,cell_ordinal,latin_ordinal,final_phase,screened_out,screened_out_page,skipped_pages,page_orders,question_orders,runtime_runs,runtime_answers

skipped_pages ist durch | getrennt, und die letzten vier Spalten enthalten JSON. Das MySQL-Speicher-Backend speichert den Ablaufdatensatz nicht, und ein Server, der es verwendet, protokolliert eine Warnung, wenn diese Funktionen konfiguriert sind.

Beispiel

examples/advanced/jspsych-stroop/ im Potato-Repository verwendet conditions, exit_when, eine jsPsych-Seite und randomize_questions. Starten Sie es aus dem Wurzelverzeichnis des Repositorys:

bash
python potato/flask_server.py start examples/advanced/jspsych-stroop/config.yaml -p 8000

Weiterführende Informationen

Implementierungsdetails finden Sie in der Quelldokumentation.