均等に割り当てたい場合(カウンターバランス)

刺激の条件割り当てについて,カウンターバランスを取るため,参加者に任意の数字をIDとして割り当て,そのIDに基づいて刺激セットを選択することを実装してみます。まず,どの刺激がどの条件に割り当てられるかが異なる刺激セットをいくつか作成します。カウンターバランスのためには,セットを通して,各刺激が各条件に同じ頻度で割り当てられるようなセットを作成する必要があります。*今回から,変数宣言を少し変えました。  例えば,再認課題で学習刺激と再認テスト時の新奇刺激を設ける場合を考えてみます。刺激リストを半数ずつに分けて,それぞれをリストAとリストBとしてみます。そして,以下の2つの刺激セットを用意することにしました。

  1. セット1
  2. セット2

刺激セットは2種類なので,全参加者の半数をセット1,残り半数をセット2に割り当てればカウンターバランスを達成できます。まず,刺激をリストAとリストBを作成してみます。

//リストA
const listA = ['リストA'];

//リストB
const listB = ['リストB'];

続いて,セット1とセット2を作成してみます。後で場合分けを行うとして,とりあえず,学習刺激と新奇刺激に異なるリストが割り当てられるセット1とセット2を作ります。

//set1
const learningWords = listA;
const newWords = listB;

//set2
const learningWords = ListB;
const newWords = listA;

場合分け用の変数としてsetSelectorを作成し,setSelectorが0か1かでセットの割り当てを分けることにします。ここでは,switchsetSelectorの値によって異なるセットを読み込んでいます。もちろん,ifでも可能ですが,セットは数字で割り当てるので可読性の高いswitchを用いています。

const setSelector;

switch(setSelector)
{
	case 0:
			//set1
			const learningWords = listA;
			const newWords = listB;
			break;
	case 1:
			//set2
			const learningWords = ListB;
			const newWords = listA;
			break;
**}**

では,続いて,setSelectorの値を取得します。参加者IDとして数字を入力してもらい,そのIDによってセットの割り当てを変えましょう。参加者IDは実験プログラムの実行時にプロンプトを表示し,入力してもらいます。Inquisit webのスクリプトを参考に作成しました。参加者IDの入力を求める関数(getSubjectID())を作成し,その返り値(入力された値)をsubjectIDとして得ます。入力された値は数字でないと困るので,3桁の半角数字でない場合はエラーが表示されます。また,入力ミスを防ぐため,2回入力してもらっています。

//id入力関数の定義
function getSubjectID() {
    const intRegExp = /(^\\d{3,3}$)/;
    const promptMsg = "3桁のIDを入力してください";
    const confirmMsg = "確認のため,IDをもう一度,入力してください";
    const invalidMsg = "無効な値です。再度,入力してください。";
    const matchMsg = "IDが一致しません。再度,入力してください。";

    let snum = window.prompt(promptMsg, "");

    while (snum != null && intRegExp.test(snum) == false) {
        // if the input was invalid, prompt again 
        window.alert(invalidMsg);
        snum = window.prompt(promptMsg, "");
    }

    if (snum == null) {
        return null;
    }

    let sconfirm = window.prompt(confirmMsg, "");
    while (sconfirm != null && (sconfirm != snum || intRegExp.test(sconfirm) == false)) {
        if (intRegExp.test(sconfirm) == false) {
            window.alert(invalidMsg);
        }

        else if (sconfirm != snum) {
            window.alert(matchMsg);
            return null;
        }

        sconfirm = window.prompt(confirmMsg, "");
    }

    return sconfirm;
}

//id入力
const subjectID = getSubjectID();

参加者IDとして3桁の半角数字の値を得ることができたので,この値をもとにsetSelectorの値を決定します。参加者の半数ずつにセットを均等に振り分けるため,割り算の余りを利用します。今回は,参加者IDを連番でつけていくことにしました(001〜)。参加者はセットの倍数集めるとすれば,参加者IDの奇数・偶数は同じ割合になります。そこで,subjectIDが偶数か奇数かを判定し,判定にもとづいて割り当てるセットを変えます。偶数と奇数の判定は,値を2で割り続けた時に,余りが0になれば偶数,1になれば奇数です。余りは%で計算できます。以下のコードで実装できます。

//id入力関数の定義
function getSubjectID() {
    const intRegExp = /(^\\d{3,3}$)/;
    const promptMsg = "3桁のIDを入力してください";
    const confirmMsg = "確認のため,IDをもう一度,入力してください";
    const invalidMsg = "無効な値です。再度,入力してください。";
    const matchMsg = "IDが一致しません。再度,入力してください。";

    let snum = window.prompt(promptMsg, "");

    while (snum != null && intRegExp.test(snum) == false) {
        // if the input was invalid, prompt again 
        window.alert(invalidMsg);
        snum = window.prompt(promptMsg, "");
    }

    if (snum == null) {
        return null;
    }

    let sconfirm = window.prompt(confirmMsg, "");
    while (sconfirm != null && (sconfirm != snum || intRegExp.test(sconfirm) == false)) {
        if (intRegExp.test(sconfirm) == false) {
            window.alert(invalidMsg);
        }

        else if (sconfirm != snum) {
            window.alert(matchMsg);
            return null;
        }

        sconfirm = window.prompt(confirmMsg, "");
    }

    return sconfirm;
}

//id入力
const subjectID = getSubjectID();

//刺激
//リストA
const listA = ['リストA'];

//リストB
const listB = ['リストB'];

//余りを計算
const setSelector = subjectID % 2;

let learningWords = [];
let newWords = [];

//セットの割り当ての分岐
switch (setSelector) {
    case 0:
        //set1
        learningWords = listA;
        newWords = listB;
        break;
        
    case 1:
        //set2
        learningWords = listB;
        newWords = listA;
        break;
}

const showLearningWords = {
    type: 'html-keyboard-response',
    stimulus: learningWords,
    trial_duration: 5 * 1000,
    choices: jsPsych.NO_KEYS
};

const showNewWords = {
    type: 'html-keyboard-response',
    stimulus: newWords,
    trial_duration: 5 * 1000,
    choices: jsPsych.NO_KEYS
};

let timeline = [];

timeline.push(showLearningWords);
timeline.push(showNewWords);

jsPsych.init({
    timeline: timeline
    }
);

さて,では,セット数がもっと多い場合,例えば5セットある場合はどうしたらよいでしょうか?先ほど,余りを用いたことを思い出してください。ある値を5で割り続けた場合にでてくる余りのパターンを考えてみると,それは「0, 1, 2, 3, 4」の5通りになります。つまり,参加者ID÷セット数で生じる余りによってセットの割り当てを均等に分岐することができます(ただし,参加者数がセットの倍数かつ連番でIDを与えた場合のみです)。なお,パターンには0が含まれていることに気をつけてください。

ランダムにセットを割り当てたい場合

対面実験などの参加者にIDを指定できる実験では,上記の方法で刺激のカウンターバランスを取ることができます。では,IDを指定することが困難なオンライン実験ではどうでしょうか(IDを指定出来たとしても,途中で辞める参加者も多いため,連番を与えることが困難)。カウンターバランスについては諦める方が現実的かと思います。その代わりの方法として,以下の2つのいずれかの方法が利用できます。

  1. 刺激セットをいくつか用意しておき,参加者ごとにいずれかのセットをランダムに割り当てる
  2. 刺激プールからいくつかの刺激を参加者ごとにランダムにサンプリングして用いる