jsPsychとQualtricsでやらかした話:データが不完全な状態に

jsPsychとQualtricsでやらかした話:データが不完全な状態に

jsPsychとQualtricsで調査実験をしたのですが、jsPsychの個々人のデータに欠損が生じるという問題が発生しました。なぜ問題が発生したのかや、解決策をまとめます。

psyJS Advent Calendar 2021の14日目の記事です。

問題の起きた実験の概要

jsPsychで実験の流れ
ことの発端は、この記事にあるように、参加者の姓・名を利用した自尊心IATを実施しようとしたのがきっかけでした。jsPsych上で参加者の名前をフォームで入力させ、後の自尊心IATでその姓・名をそれぞれ刺激として提示する、といった感じです(上の記事に既に対処法は記載しています)。

var name_trial= {
  type: 'survey-text',
  preamble:'<p>次に行う実験でどうしても必要なため記入をお願いしております。</p>'+' <p>ここで収集した名前については、次の課題でのみ使用し、分析には使用致しません。</p>'+'<p>プライバシー保護には十分配慮致します。</p>',
  questions: [
        {prompt: '名字(姓)を入力してください(例:田中 太郎さんなら:田中)', name: 'name_up', required:'True'},
      ],
  button_label: '次へ',
  on_finish: function(data){
    //上で質問した名前を取得
    nameup = jsPsych.data.get().last(1).values()[0].response.name_up;
    
    //addPropertiesに姓・名を保存
    jsPsych.data.addProperties({name01: nameup});
  }
};

いろいろな実装方法がありますが、筆者は、入力してもらった姓名を”jsPsych.data.addProperties”を用い、jsPsychのデータに姓・名だけが保存される列を作成し、保存していました。

jsPsych

jsPsychで作成した実験をQualtricsに埋め込んで実行する方法・Rによるデータ読み込み

jsPsychで作成した実験を、Qualtricsに埋め込んで実行する方法の紹介…
kscscr.com

そうしてjsPsychで実装した実験を、Qualtrics上に埋め込んで、実施しました。

やらかしたこと:データが完全に記録されない

そうしてQualtricsで実験が終了し、さあ分析しよう!といった段階で、jsPsych部分のデータが上手く処理できないことに気づきます(スーッと血の気が引く)。

Qualtricsデータ
Qualtricsからダウンロードしたcsv(簡略化しています)

上の画像は、Qualticsでの調査と、QualtricsにjsPsychの実験を埋め込んだときのデータ例(わかりやすさのために簡略化しています)です。

QualtricsでjsPsychのデータを取得すると、個々の質問への回答と同じように、csvの1つセルの中に、個人の実験のデータがJSON形式で入ります。csvの中にJSONが入るという特殊な入れ子型になっています。通常は、Rでこのcsvを読み込み、質問紙部分とjsPsychを分離し、データの整形を行います。

jsPsychのデータ部分をRで処理しようとしたところ、データが完全に記録されていないため、処理できないという問題が発生しました。

jsPsych データ
例:IDが1の人のjsPsychのデータ

csvのセルの中にある一つのJSONデータ(上の画像は一人目)を見てみると、データが不完全な終わり方をしており、うまく記録できていないことがわかります。正常に記録できている人も少なからず存在しますが、ほとんどの人のデータが不完全な終わり方をしていました。

やらかしの原因:データ量の肥大化

jsPsych データ
addPropertiesでなぜデータが増える理由

データが完全に記録されなかった理由は、addPropertiesを使用し、データが肥大化してしまったことが原因。おそらくQualtricsのデータの一つのセルに記録できるデータサイズは、50KB程度なのですが(漢字2.5万文字、半角英数5万文字)、それを超えてしまったのが原因のようです。

今回の自尊心IATでは、参加者の名前をaddPropertiesで列に保存し、後から呼び出すという形にしていました。そのため、列数や試行数が増えると、データサイズはどんどん大きくなっていきます。

例えば「上坂」という文字列を保存した場合を考えます。文字としては4バイトですが、JSON形式だと「”name01″:”上坂”」として保存されるので15バイトになります。これが200試行分毎回保存されるので、姓を保存するだけで、3KBに。これに加え、名やあだ名(「ゆかり」など)を保存すると10~15KB程度通常のデータサイズから逸脱することになります(注:実在の人物とは関係ありません)。

微々たるデータ量ですが、これによってQualtricsのセルの容量を突破してしまい、溢れ出た部分は記録されないという問題が発生してしまいました。

解決策:データのスリム化

その1:ignoreで列を消す

var datajs = jsPsych.data.get().ignore('name01').json();

実験プログラムの仕様を変更しない場合、一番簡単なのはjsPsychのオプションであるignore(‘name01’)を使って、列そのものを飛ばすという方法です。

Qualtrics上のブロック内のjsに、jsPsychの実験を読み込んだり、データを渡したりする記述をしますが、その際にデータの一時保存(姓・名)に使っていた列を消すように指定しておきます。

この指定があると、上でデータの肥大化を起こしていた”name01″列を消去することができます。複数の列を消去する際は、「.ignore(‘name01’).ignore(‘name02’)」といった風に連ねればOK。

その2:addPropertiesを使わない

2つ目は、jsPsych.data.get()メソッドを使って、明示的に名前を質問したブロックから回答データを引っ張って来て、IAT部分で利用する方法もあります。internal-node-idなどで指定する必要があったりと少々面倒くささはあります。

追記:その3


Twitterでアドバイス頂いたのですが、予め姓名を保存するための変数をグローバルで宣言しておき、on_finish内でその変数に値を渡すことで解決しそうです。これが一番シンプルかつ良い方法かもしれません。

おまけ:もし、欠損が生じたら…

"rt":929.6899999971502,"stimulus":"清らか","key_press":69...

このような欠損が生じても、途中までのデータとして読み込む方法は、存在します(なんとか頑張った)。

大抵の場合、上記のように「,”key_press”:69…」みたいな形で、末尾が終わっています。Rのstringrパッケージを使って、一番後ろから”,”の位置を検索し、”,”key_press”:69…”を削除、末尾に”}]”を追加します。強制的にJSON形式のデータとして正常な形にすることで、欠損はありながらも、なんとか読み込めるようになります。

実施前のデータチェックとデバッグはしっかりと

今回このような問題が起きた理由としては、デバッグが不十分であったことです。

もちろん、実施前には、ちゃんとQualtricsにデータが保存されているかは確認していました。しかし、姓・名・あだ名の長い人までは考慮できておらず、今回のような問題が発生しました。

実験や調査を開始する前には、自分の想定しないサイズのデータ入力も試し、正常に記録されるか確認した上で開始するようにしましょう。