Kapitel 8. Besondere Variablentypen

Inhaltsverzeichnis

Compute
Group
DictFileVar
DecisionVar
IntRandom (Zufallszahlen)
Blockzähler
TextElement
Array
TextArray
VarArray
RestrictVar

Compute

Compute Variablen werden mit einem Namen NAME angelegt und enthalten entweder direkt einen Zahlenwert oder ein Berechnungsschema BERECHNUNG mit anderen Variablen, dessen Ergebnis jeweils im Moment des Zugriffs ermittelt wird. Sie können wie folgt angelegt, in vielerlei Hinsicht verwendet und auf Wunsch auch optional mit dem Attribut export in den Datenexport einbezogen werden.

compute VARNAME = BERECHNUNG;
[export;]
    

Bei BERECHNUNG handelt es sich im einfachsten Fall um einen einfachen Zahlenwert, der mit dem ActionBefehl set(VARNAME = VALUE); beliebig verändert werden kann. Im folgenden Beispiel soll nur beim ersten Betreten einer Frage eine Initialisierungslogik ausgeführt werden:

compute initNotwendig = 1;

TextQ intro;
text = "Los geht's!";
continueActionBlock="
  if(initNotwendig eq 1){
    set(initNotwendig = 0);
    // do some init stuff
  };
";
    

Compute Variablen können aber auch verwendet werden, etwa um die Werte der vier numerischen Eingabefelder einer NumQ mit dem Namen »punkte« zu addieren. Das folgende Beispiel ist zwar überflüssig, da man die Summe auch direkt unter dem Namen der NumQ punkte ansprechen kann, verdeutlicht aber das Prinzip.

compute summe = punkte.1 + punkte.2 + punkte.3 + punkte.4;
    

Die Variable summe enthält beim Zugriff zu jedem Zeitpunkt das jeweils aktuelle Ergebnis der Berechnung.

Als Rechenoperatoren sind +, -, *, /, % (modulo) und Klammerausdrücke möglich. Korrekte Punkt vor Strich Rechnung wird eingehalten.

Group

Eine Group wird mit einem Namen NAME, sowie einer leicht modifizierten Labelliste angelegt und stellt einen Bezug zwischen LABELCODEs, TEXTen und BEDINGUNGen her. Die Bedingungen definieren zu jeder Zeit eines Interviews, welche Labelcodes in der Group gerade vorhanden sind. Dieses Verhalten kann an diversen Stellen eingesetzt werden, z.B. für die konditionale Übernahme von Texten in den Fragetext oder für Restriktionen, die sich nicht einfach per Labelwert-Bezug zu anderen Fragen herstellen lassen. Das optionale Attribut export steuert, ob die Group beim Datenexport berücksichtigt werden soll.

group NAME;
labels=
LABELCODE "TEXT" (BEDINGUNG)
LABELCODE "TEXT" (BEDINGUNG)
...
;
[export;]
    

Ein Beispiel: Es werden Geschlecht und Alter des Befragten abgefragt, und je nachdem, was dieser geantwortet hat, soll ein bestimmter Text (der sich nicht direkt den Fragen nach Alter und Geschlecht entnehmen lässt) in den Text der TextQ meldung eingebaut werden. Die mit @insert eingeblendete Group hilft bei der Realisierung.

  SingleQ geschlecht;
  labels=
  1 "Männlich"
  2 "Weiblich"
  ;
      
  SingleQ alter;
  labels=
  1 "18-39 Jahre"
  2 "40-59 Jahre"
  ;
  
  group anrede;
  labels=
  1 "Mein Herr, Sie sind 18-39 Jahre alt."  (geschlecht eq 1 and alter eq 1)
  2 "Mein Herr, Sie sind 40-59 Jahre alt."  (geschlecht eq 1 and alter eq 2)
  3 "Meine Dame, Sie sind 18-39 Jahre alt." (geschlecht eq 2 and alter eq 1)
  4 "Meine Dame, Sie sind 40-59 Jahre alt." (geschlecht eq 2 and alter eq 2)
  ;
  
  TextQ meldung;
  text="@insert(anrede)";
    

Das Element der Group, dessen Bedingung erfüllt ist, wird als Text in den Fragetext übernommen.

Im Fall des Textersatz' werden alle zutreffenden Labels als Komma-separierte Liste ausgegeben. Das Trennzeichen und der letzte Trenner können frei festgelegt werden:

      insert="SEP","CON";
    
Group myGroup;
  labels=
  1 "1" (1 in abc)
  2 "2" (2 in abc)
  3 "3" (3 in abc)
;
insert=" | ", " und ";
// @insert(myGroup) sähe dann möglicherweise so aus: "1 | 2 und 3"
    

In diesen Beispiel ist der Sinn der Labelwerte noch nicht zu erkennen. Groups können auch als Vorlage für Restriktionen dienen. Beispielsweise sollen Automodelle nur dann abgefragt werden, wenn die Marke insgesamt bekannt ist (dies lässt sich zwar auch mit Labelfiltern lösen, aber es ist ja auch nur ein Beispiel):

  MultiQ marken;
  text="Welche dieser Automarken kennen Sie?";
  labels=
  1 "Audi"
  2 "BMW"
  3 "Mercedes"
  ;
  
  group restr;
  labels=
  1 "Audi"     (marken eq 1)
  2 "Audi"     (marken eq 1)
  3 "Audi"     (marken eq 1)
  4 "BMW"      (marken eq 2)
  5 "BMW"      (marken eq 2)
  6 "BMW"      (marken eq 2)
  7 "Mercedes" (marken eq 3)
  8 "Mercedes" (marken eq 3)
  9 "Mercedes" (marken eq 3)
  ;
  
  MultiQ modelle;
  text="Welche dieser Automodelle kennen Sie?";
  labels=
  1 "Audi A4"
  2 "Audi A6"
  3 "Audi A8"
  4 "BMW 3er"
  5 "BMW 5er"
  6 "BMW 7er"
  7 "Mercedes C-Klasse"
  8 "Mercedes E-Klasse"
  9 "Mercedes S-Klasse"
  ;
  restrict=restr;
    

Gruppen können neben den Bedingungen, die ihre Werte bestimmen, auch ein else-Label erhalten. Auf diese Weise ließe sich eine Voreinstellung für eine Gruppe festlegen, die durch bestimmte Bedingungen aufgehoben wird.

Group myGroup;
  labels=
  1 "1" (1 in abc)
  2 "2" (2 in abc)
  3 "3" (3 in abc)
  9 "9" else
;
    

Obwohl die group-Daten sich eindeutig von anderen Variablen herleiten lassen, werden sie im Datensatz abgelegt. Der Grund dafür ist, dass die Daten einer group sich auch aus Variablen definieren können, deren Zustand im Nachhinein nicht unbedingt immer nachvollziehbar ist, wie z.B. Zufallszahlen, Zeiten oder Quotenstände.

DictFileVar

Die DictFileVar implementiert einen Dictionary-Mechanismus, der einem Schlüssel einen Wert zuordnet. Beispielsweise ist eine Unterteilung Deutschlands in Regionen (z.B. Nord, Süd, Ost und West) denkbar. Die Befragten sollen ihre Postleitzahl eingeben und werden darüber einer der vier Regionen-Gruppen zugeordnet. Man hantiert dabei mit der langen Liste aller deutschen Postleitzahlen, die in vier Gruppen unterteilt werden soll. Dass ließe sich mit einer Group umsetzen, wäre allerdings umständlich und verbrauchte Software-Ressourcen. Hier ist die DictFileVar das Mittel der Wahl.

Die Syntax ist:

      DictFileVar name=("Datei", Schlüsselvariable);
    

In der Datei stehen zeilenweise untereinander die Schlüssel und daneben die ihnen zugeordneten Werte. Die Schlüsselvariable enthält den Schlüsselwert (in unserem Beispiel also die Postleitzahl). Im folgenden Beispiel enthält die Datei »plz.txt« nur drei Zeilen mit zwei Postleitzahlen aus Hamburg und einer aus Berlin:

10247 3
20257 1
22359 1
    

Die Postleitzahl wird in einer NumQ namens »plz« abgefragt, daher hat die Schlüsselvariable den Namen »plz.1«. Die DictFileVar sähe also so aus:

DictFileVar region=("plz.txt", plz.1);
    

Wenn Befragte nun als Postleitzahl »10247« eingeben, wird dieser Schlüssel-Wert in der Datei gesucht und die DictFileVar bekommt den ihr zugeordneten Wert 3 (für »Ost«). Die DictFileVar kann nun wiederum für Filter, Quoten usw. verwendet werden.

Sowohl beim Schlüssel als auch beim zugeordneten Wert kann es sich auch um Text handeln (anstelle von Zahlen). Der zugeordnete Wert kann auch direkt für Textersatz verwendet werden.

Zu beachten ist: Um ständige Dateizugriffe zu vermeiden, wird der Inhalt der DictFileVar nur einmal ermittelt, und zwar zum Zeitpunkt des ersten Zugriffs auf die Datei. Voraussetzung für die Verwendung der DictFileVar ist daher, dass sich die Zuordnungen nicht während der Interviewzeit verändern. Zudem haben auch Änderungen an der Schlüsselvariablen (beispielsweise durch ein Zurückgehen und Ändern während des Interviews) keinen Einfluss, nachdem der Wert einmal ermittelt wurde.

DecisionVar

Mit einer DecisionVar ist es möglich, den Faktor, ob eine Bedingung erfüllt ist oder nicht, in Berechnungen mit einzubeziehen.

Syntax:

  DecisionVar name = (Bedingung);
    

Wenn die Bedigung erfüllt ist, hat die DecisionVar den Wert 1 ansonsten 0.

IntRandom (Zufallszahlen)

Mit IntRandom lassen sich ganzzahlige Zufallszahlen erzeugen. Die Syntax ist:

  IntRandom name=von bis;
    

Für eine Zufallszahl zwischen 1 und 10 wäre das beispielsweise

IntRandomVar meineZufallszahl = 1 10;
    

Zu beachten ist, dass die Zufallszahl einmal bei Interviewstart ermittelt wird und dann während des gesamten Interviews konstant bleibt (genau wie alle anderen Zufalls-Elemente wie z.B. randomisierte Blöcke auch).

Blockzähler

Wenn ein Block von Fragen durchlaufen wird, kann es notwendig sein, zu ermitteln, an welcher Position in diesem Block sich das Interview gerade befindet. Beispielsweise können Fragen in einem randomisierten Block stehen, und abhängig davon, ob eine Frage die erste oder eine andere Position in diesem Block hat, kann der Fragetext anders sein. Hierzu gibt es pro Block je eine Variable, die diese Information liefert. Die Variable wird automatisch generiert und trägt den Namen count_+Blockname. Wenn der Block also »block1« hieße, würde die Blockzähl-Variable count_block1 heißen. Beim Durchgehen des Blocks enthält die Variable als Wert die Position des Blocks, an dem sich das Interview gerade befindet.

Beispiel:

Gegeben seien zwei Frage, q1 und q2. Diese erscheinen randomisiert im Block »block1«:

block block1=(q1 q2); random;
    

Je nachdem, ob eine Frage als erstes oder zweites kommt, soll der Fragetext anders sein. Beispielhaft für q1: Der Fragetext wird mittels Textersatz und einer group erzeugt.

group qtext_q1;
labels=
1 "Fragetext q1 Erstvorlage" (count_block1 eq 1)
2 "Fragetext q2 Zweitvorlage" (count_block1 eq 2)
;

SingleQ q1;
text="@insert(qtext_q1)";
...
    

TextElement

TextElement stellt eine einfache Textvariable dar. Sie kann lediglich mit einem Namen angelegt und in ActionBlöcken mittels setText(TEXTVAR, "’TEXT"’) und appendText(TEXTVAR, "’TEXT"’) neu belegt oder um einen weiteren Text verlängert werden.

TextElement meinTextElement;

ActionBlock ab = {
setText(meinTextElement, "Das ist ein");
appendText(meinTextElement, " Beispiel.");
};
    

Mit der Anweisung saved kann eine Variable auch über Abbruch und Wiederaufnahme erhalten bleiben,

TextElement te = "ein Text" saved; // angelegt + gespeichert (Abbr/Wiederaufnahme)
    

Array

Ein besonderer Variablentyp ist das Array. Ein Array speichert eine Anzahl #WERTE von Fließkommazahlen, die sich per Index ansprechen lassen. Es kann von außen betrachtet auch als einzelne, atomare Variable angesprochen werden. Der Wert des Arrays entspricht dann der Summe seiner einzelnen Elemente. Mit dem optionalen Attribut export wird das Array beim Datenexport berücksichtigt.

      Array VARNAME[#WERTE];
    
      
// Beispiel:
Array zehnFelder[10];
[export;]
    

Ein neu angelegtes Array wird entsprechend der Einstellung ArrayInitMode initialisiert, siehe „Skriptparameter“. Das Array zehnFelder hat demnach 10 Felder mit entsprechenden Werten, die mit eckigen Klammern angesprochen werden können. Der Index beginnt bei 1.

zehnFelder[1]
...
zehnFelder[10]
    

Arrays können z.B. in for-Schleifen mit Werten belegt werden, etwa um die Werte einer Gruppe (hier auswahl) auf ein Array zu übertragen (nur sinnvoll, wenn das Array mit _missing-Werten initialisiert wurde):

compute max = 10;
array arr[max];
  for( zaehler=1 to max ) {
    if( zaehler in auswahl ) {
      set( arr[zaehler] = zaehler );
    };
  };
    

Alternativ kann das Array auch mit dem Action-Befehl set gefüllt werden, s. „Actionbefehle“.

TextArray

Analog zu Array gibt es auch einen Variablentyp TextArray, der anstelle von mehreren Werten mehrere Texte enthält. Es gibt zwei Möglichkeiten TextArrays zu initialisieren:

// Direkte Initialisierung mit Texten
TextArray marken = {"Audi" "BMW" "Mercedes"};

// Indirekte Initialisierung mit den Labels einer Frage
MultiQ q_marken;
labels=
1 "Audi"
2 "BMW"
3 "Mercedes"
;
TextArray marken = q_marken;
    

Wie auch bei normalen Arrays lassen sich die einzelnen Texte mit eckigen Klammern ansprechen und der Index beginnt bei 1.

VarArray

Ein dritter Array-Typ neben Array für Zahlen und TextArray für Texte steht mit VarArray für Variablen zur Verfügung. Einem VarArray können wir die Variablen direkt über ihre Namen übergeben und dann auf die Werte über den Index zugreifen.

      vararray NAME = (VAR1 VAR2 ...);
    

RestrictVar

Die RestrictVar kann als Schablone für den restrict Befehl verwendet werden, um Labellisten automatisch zu filtern. Das folgende Beispiel zeigt die Verwendung mit SingleQs, um der Reihe nach die Plätze 1 bis 3 auf die Label zu verteilen.

RestrictVar NAME = TEMPLATE;
    
singleq msq1;
text="1. Platz";
labels=
1 "a"
2 "b"
3 "c"
4 "d"
5 "e"
;

RestrictVar rsv = (not(msq1));

singleq msq2;
text="2. Platz";
labels copy msq1;
restrict=(not(msq1));
// restrict=rsv;  // Alternative Schreibweise mit RestrictVar

singleq msq3;
text="3. Platz";
labels copy msq1;
restrict=(not(msq1 or msq2));