コンテンツへスキップ
チュートリアル17分で読めます

ライセンスが切れる前に Qualtrics の調査を Potato に移す

アカウントが閉鎖される前に .qsf と回答をエクスポートし、potato import で調査をインポートして、インポートレポートに挙がった各項目を修正します。

Potato Team

所属大学が Qualtrics へのアクセスを終了または制限しようとしている調査研究者やラボ管理者は、このチュートリアルに従って、一つの調査を Qualtrics から Potato 2.13.1 に移し、.qsf のエクスポートから Prolific の調査と CSV エクスポートまでを行うことができます。たとえば、ラドバウド大学の社会科学部は Qualtrics を段階的に廃止しており、研究者に 2026 年 12 月 1 日までに Qualtrics のデータと資料を削除するよう求めています。同学部は研究者に LimeSurvey を案内しています。LimeSurvey は単純な質問紙に適しており、Potato は、回答者に見せるものを変えたり、回答者に項目を評定させたりする調査に適しています。このチュートリアルの調査は、後者の種類の実験です。Qualtrics から移行するは、Qualtrics の各機能を Potato のキーに対応付けており、調査のインポートはインポートのフラグを一覧にしています。このページでは、一つの調査をすべての手順にわたって追います。

調査の例

例は、このチュートリアルのために書かれた、見出しの信頼性についての実験です。.qsf には実際の回答も、ライセンスされた素材も含まれません。各回答者は四つのニュース見出しを評定し、ランダマイザーが、見出しが全国紙のものか、ソーシャルメディアのアカウントのものかを決めます。調査のフローは次の順に進みます。

  1. 埋め込みデータ要素が、調査リンクから PROLIFIC_PID を保存します。
  2. 同意ブロックには、同意しない回答者を調査の終了へ飛ばすスキップロジックがあります。
  3. スクリーナーブロックがニュースの閲読と年齢を尋ね、分岐によって、オンラインでニュースを読まない人の調査を終了させます。
  4. Evenly Present Elements をオンにしたランダマイザーが、二つの埋め込みデータ要素のうち一つを提示し、source を「a national newspaper」または「a social media account」に設定します。
  5. 見出しブロックは、四つの見出しに対してランダムな順序で Loop & Merge を実行します。質問文には ${e://Field/source} と ${lm://Field/1} がパイプされ、Timing 質問がページでの時間を記録します。
  6. 二つ目のランダマイザーが、メディア信頼ブロックとニュース習慣ブロックをランダムな順序で表示します。メディア信頼はマトリクス表で、ニュース習慣のフォローアップ質問には、「Social media」の選択肢に対する表示ロジックがあります。
  7. 属性ブロックは、Request Response を設定した任意のメールアドレスの質問、操作チェック、source が「a social media account」のときだけ表示される自由記述の質問で終わります。
  8. クォータが 400 件の完了で調査を止め、二つの調査終了要素はどちらも、完了コードを付けて Prolific にリダイレクトします。

Qualtrics からの .qsf と回答のエクスポート

.qsf ファイルには、調査の質問、ブロック、フロー、ロジックが含まれます。ファイルには回答は含まれず、Qualtrics は回答を別にエクスポートします。アカウントが閉鎖される前に、両方のエクスポートを行ってください。

  1. 調査の Survey タブで Tools をクリックし、Import/Export を選び、Export survey を選びます。Qualtrics が .qsf ファイルをダウンロードします。
  2. Data & Analysis タブの Data セクションで Export & Import をクリックし、Export Data を選びます。CSV を選び、Download all fields の選択を維持し、回答のテキストなら Export labels、数値コードなら Export values を選んで、Download をクリックします。
  3. 調査でファイルのアップロードや署名を収集した場合は、同じダイアログの User Submitted Files からファイルをダウンロードします。

古い分析スクリプトが数値コードを読み込んでいる場合は、回答をもう一度、値付きでエクスポートしてください。すべてのエクスポートは、削除日の前に、所属機関のデータポリシーが定める場所に保管してください。Potato は選択式の質問への各回答を、選択肢のテキストとして保存します。Export labels も同じ形式で書き出すため、分析では、古い回答と新しい回答が一つのコーディング方式を共有できます。

potato import による .qsf のインポート

このチュートリアルで確認したリリースをインストールし、.qsf に対してインポートを実行します。

bash
pip install potato-annotation==2.13.1
potato import -i headlines.qsf -o headline-study/

インポーターはファイルから Qualtrics 形式を検出し、-f qualtrics は形式を明示的に指定します。コマンドは、サマリーと書き出されたファイルの一覧を表示します。

text
Imported 7 page(s) and 15 question(s) from Qualtrics.
  8 construct(s) did not carry over; see IMPORT_REPORT.md:
    - quota QO_completes: quota: 400 completes
    - flow FL_2: embedded data: PROLIFIC_PID (recipient)
    - flow FL_6: end-of-survey redirect: https://app.prolific.com/submissions/complete?cc=C1SCREEN
    - block 'Headlines': loop and merge: looping by Static; the block is imported once
    - QID5 (accuracy): piped text: ${e://Field/source}, ${lm://Field/1} (shown as written)
    - QID7 (headline_timer): timing question: Potato records time on page and the browser itself
    - QID14 (email): request response: Qualtrics asks before moving on unanswered; Potato has no soft requirement
    - flow FL_15: end-of-survey redirect: https://app.prolific.com/submissions/complete?cc=C1HEADLN
  warning: the survey can screen participants out before its randomizer, but Potato assigns a condition on arrival, so conditions.balance_on is 'completed': screened-out and abandoned participants do not count toward a cell
  wrote headline-study/surveys/Consent.json
  wrote headline-study/surveys/Screener.json
  wrote headline-study/surveys/Headlines.json
  wrote headline-study/surveys/Media_trust.json
  wrote headline-study/surveys/News_habits.json
  wrote headline-study/surveys/Demographics.json
  wrote headline-study/surveys/Demographics_p2.json
  wrote headline-study/data/items.jsonl
  wrote headline-study/config.yaml
  wrote headline-study/IMPORT_REPORT.md
  wrote headline-study/README.md
 
Run it:
  potato start headline-study/config.yaml -p 8000

各ブロックは surveys/ の一つのページになり、Demographics 内の改ページが二つ目のページ Demographics_p2 を始めました。config.yaml は、プレースホルダーのアノテーションタスクの前に、ページを phases.order に列挙し、data/items.jsonl には三つのプレースホルダー項目があります。IMPORT_REPORT.md は、上の八つの項目と警告を繰り返し、各 Qualtrics の質問 ID を Potato の質問名に対応付ける表を加えます。

インポートが変換したロジック

調査のロジックの大半は、Potato のルールとして取り込まれました。同意のスキップロジックとスクリーナーの分岐は exit_when ルールになり、埋め込みデータのランダマイザーは被験者間要因になり、二つ目のランダマイザーはカウンターバランスのグループになりました。生成された config.yaml の抜粋は、その三つすべてを示します。

yaml
conditions:
  factors:
    source:
    - a national newspaper
    - a social media account
  assignment: balanced
  balance_on: completed
phases:
  Screener:
    type: prestudy
    file: surveys/Screener.json
    exit_when:
      show_when:
      - schema: reads_news
        operator: equals
        value: 'No'
      logic: all
      message: Thank you. This is the end of the study.
  counterbalance:
  - pages:
    - Media_trust
    - News_habits
    method: random

assignment: balanced は Evenly Present Elements に由来します。source を検査していた表示ロジックは condition.source を検査するようになり、「Social media」の表示ロジックは、プラットフォームの質問の display_logic ルールになりました。マトリクス表は multirate 質問に、Force Response は required: true に、年齢の質問は 18 から 99 に制限された number 質問になりました。「Somewhere else」のテキストボックスは自由記述フィールドに、選択肢のランダム化は randomize_order になりました。

インポートされた調査はすでに動作します。potato start headline-study/config.yaml -p 8000 で調査を起動し、何かを編集する前にすべてのページを読んでください。

レポートされた項目の修正

レポートの八つの項目には、それぞれ判断が必要です。表は、各項目と、このチュートリアルが行う修正を対にして示しており、二つのリダイレクトは一行にまとめています。

レポートの項目修正
Headlines の Loop & Merge四つの見出しがデータファイルの項目になり、アノテーションフェーズで評定されます
見出しの質問内のパイプされたテキスト見出しが項目のテキストになり、{condition.source} が出所を指定します
Timing 質問削除します。Potato は各参加者の user_state.json に、アノテーション項目ごとの時間を保持します
埋め込みデータ PROLIFIC_PIDlogin.type: url_direct が、調査リンクから ID を読み取ります
二つの調査終了リダイレクトcrowdsourcing.prolific.completion が、二つの完了コードを列挙します
400 件の完了のクォータProlific の調査の募集人数が、完了数の上限になります
メールアドレスの質問の Request Responseメールアドレスの質問を削除します

ループするブロックのアノテーションフェーズへの移動

Loop & Merge ブロックは、フィールドのリストに対して同じ質問を繰り返し、Potato のアノテーションフェーズは、データファイルの項目に対してアノテーションスキームを繰り返します。そのため、見出しは調査の外へ出て、一行に一項目ずつ data/headlines.jsonl に入ります。

json
{"id": "h1", "text": "Shared by {condition.source}: City council approves four-day school week starting in fall"}
{"id": "h2", "text": "Shared by {condition.source}: New study finds coffee drinkers live longer"}
{"id": "h3", "text": "Shared by {condition.source}: State to replace all lead water pipes by 2030"}
{"id": "h4", "text": "Shared by {condition.source}: Local hospital ends weekend emergency care"}

Potato は、項目のテキスト内の {condition.source} を参加者の水準に置き換えます。全国紙の条件の参加者は、「Shared by a national newspaper: City council approves four-day school week starting in fall」を読みます。Headlines ブロックの二つの質問は、設定の annotation_schemes になり、surveys/Headlines.json と data/items.jsonl は削除されます。assignment_strategy: random は、各参加者に四つの見出しをすべて、ランダムな順序で渡します。元の調査は、ループの順序を同じようにランダム化していました。

Qualtrics では、信頼、習慣、属性のブロックは見出しの後に来ていました。それらのページは現在、アノテーションフェーズの後に続き、各ページの type は prestudy から poststudy に変わります。

同意とスクリーナー

Prolific は研究者に、同意しない参加者を戻るための経路へ案内し、決して拒否しないよう求めています(Prolific の調査内スクリーニングのガイド)。Potato 2.13.1 では、すべての exit_when ルールが同じスクリーンアウトのコードを与えるため、同意の拒否はスクリーナーのコードを受け取ることになります。そのため、同意ページは exit_when ルールと「I do not agree」の選択肢を失い、ページのテキストは、同意しない人に Prolific で調査を返却するよう求めます。

インポートは Force Response を required: true にも変えました。Potato 2.13.1 からは、サーバーが調査ページで required: true と required_label の両方を検査するため、別の方法でページを送信する参加者は、どちらもスキップできません。2.12.1 では、required: true はブラウザでのみ検査されていました。同意とスクリーナーは誰が調査に到達するかを決めるため、どちらの質問も required_label を使います。surveys/Consent.json の同意の質問は次のとおりです。

json
{
  "name": "consent",
  "annotation_type": "radio",
  "labels": ["I agree"],
  "description": "Do you agree to take part in this study?",
  "label_requirement": {"required_label": ["I agree"]}
}

surveys/Screener.json の reads_news 質問は、両方の選択肢を "required_label": ["Yes", "No"] として列挙し、サーバーは、特定の回答を求めずに、回答があることを要求します。スクリーナーの exit_when ルールは、「No」と答えた人の調査を終了させます。

メールアドレスの質問の削除

Prolific は、研究者が Prolific の事前承認なしに参加者の個人のメールアドレスを収集することを許可していません。Prolific のガイダンスは、研究についての最新情報の提供を、認められない理由の一つとして挙げています。Prolific は研究者に、Prolific のメッセージシステムを通じて参加者に連絡するよう求めています。surveys/Demographics.json からメールアドレスの質問を削除すれば、Request Response の項目も解決します。Potato には Request Response に相当するものがなく、label_requirement のない質問は、リマインダーなしの任意の質問になります。

完了した参加者での条件のバランス

Qualtrics は、スクリーナーの後のランダマイザーに回答者が到達した時点で source を設定しました。Potato は、参加者が最初に到着したとき、同意ページの前に条件を割り当てます。そのため、スクリーナーでスクリーンアウトされた参加者にもセルが割り当てられ、デフォルトの balance_on: assigned では、それらのスクリーンアウトがバランスに数えられます。2.13.1 のインポーターは、ランダマイザーの前にスクリーナーがあることを検出し、balance_on: completed を設定して、インポートの出力に示された警告を表示します。balance_on: completed は、スクリーンアウトされずに終了した参加者と、最後の操作から in_progress_minutes(デフォルトは 60)以内でまだ作業中の参加者を数えます。2.12.1 のインポーターは、balance_on をデフォルトのままにしていました。

その他の小さな修正

  • クォータ。 Potato には Qualtrics のクォータに相当するものがありません。Prolific の調査の募集人数が完了数の上限になり、Prolific は後から募集人数を増やせます。
  • 時間計測。 見出しは現在アノテーション項目であり、Potato は各参加者の user_state.json に項目ごとの時間を記録します。Timing 質問は削除します。
  • スライダーの文言。 2.12.1 のインポートは、スライダーの文のラベルを質問文に追加して「...watching news: Minutes per day」を作り、surveys/News_habits.json の description は元の質問に戻しました。2.13.1 のインポートは元の質問を保持します。

完成した設定

下の設定は完全なもので、2.12.1 と 2.13.1 の両方で python -m potato.validate_cli config.yaml --strict を通ります。

yaml
annotation_task_name: Headline credibility study
task_dir: .
output_annotation_dir: annotation_output/
data_files:
  - data/headlines.jsonl
item_properties:
  id_key: id
  text_key: text
assignment_strategy: random
 
login:
  type: url_direct
  url_argument: PROLIFIC_PID
user_config:
  allow_all_users: true
  users: []
 
crowdsourcing:
  provider: prolific
  prolific:
    completion:
      code: C1HEADLN
      screened_out_code: C1SCREEN
 
conditions:
  factors:
    source: ["a national newspaper", "a social media account"]
  assignment: balanced
  balance_on: completed
 
phases:
  order: [Consent, Screener, annotation, Media_trust, News_habits, Demographics, Demographics_p2]
  Consent:
    type: prestudy
    file: surveys/Consent.json
  Screener:
    type: prestudy
    file: surveys/Screener.json
    exit_when:
      show_when:
        - {schema: reads_news, operator: equals, value: "No"}
  annotation:
    type: annotation
  Media_trust:
    type: poststudy
    file: surveys/Media_trust.json
  News_habits:
    type: poststudy
    file: surveys/News_habits.json
  Demographics:
    type: poststudy
    file: surveys/Demographics.json
  Demographics_p2:
    type: poststudy
    file: surveys/Demographics_p2.json
  counterbalance:
    - pages: [Media_trust, News_habits]
      method: random
 
annotation_schemes:
  - annotation_type: radio
    name: accuracy
    description: How accurate is the claim in this headline?
    labels: ["Not at all accurate", "Not very accurate", "Somewhat accurate", "Very accurate"]
    label_requirement:
      required: true
  - annotation_type: radio
    name: share
    description: Would you share this headline with a friend?
    labels: ["Yes", "No", "Not sure"]
    label_requirement:
      required: true
 
export_include_phase_data: true

インポートは export_include_phase_data: true を設定しており、この設定は残します。この設定がないと、エクスポートは、同意から属性までの調査ページで与えられたすべての回答を除外し、phase_responses.csv を書き出しません。crowdsourcing ブロックは、Prolific に、元の調査の各リダイレクトに一つずつ、二つのコードを与えます。終了した参加者には C1HEADLN が表示され、スクリーナーの exit_when ルールでスクリーンアウトされた参加者には C1SCREEN が表示されます。インポートは各ルールの message を保持していましたが、Potato 2.12.1 はこれを表示せず、完成した設定では削除しています。

Prolific または SONA での募集

Prolific では、URL パラメーターで Prolific ID を記録する方法を選び、調査の URL を、サーバーのアドレスと三つのパラメーターにします。

text
https://your-server.example/?PROLIFIC_PID={{%PROLIFIC_PID%}}&STUDY_ID={{%STUDY_ID%}}&SESSION_ID={{%SESSION_ID%}}

C1HEADLN と C1SCREEN を Prolific の調査に完了コードとして追加し、C1SCREEN には Prolific の「Screened out」ラベルを付けます。完了ページは、各参加者を二つのうち一つのコードとともに Prolific に戻します。同意しない参加者は Prolific で調査を返却し、コードは受け取りません。クォータの代わりに、募集人数を 400 に設定します。

SONA の参加者プールでは、上の設定の login ブロックと crowdsourcing ブロックを次の二つのブロックに置き換えます。

yaml
login:
  type: url_direct
  url_argument: sona_code
 
crowdsourcing:
  provider: sona
  sona:
    hostname: yourdept.sona-systems.com
    experiment_id: 123
    credit_token: your-credit-token

ホスト名、実験 ID、クレジットトークンは、SONA の調査情報ページから得られます。SONA の調査の URL を https://your-server.example/?sona_code=%SURVEY_CODE% に設定します。参加者が終了すると、Potato は SONA のサーバー側のクレジット呼び出しでクレジットを付与し、その呼び出しが失敗した場合、完了ページは SONA のクレジットリンクにフォールバックします。クラウドソーシング統合は、両方のプロバイダーをさらに詳しく扱っています。

調査の実行とテスト

プロジェクトフォルダーからサーバーを起動します。

bash
potato start config.yaml -p 8000

公開前に、毎回新しい ID で http://localhost:8000/?PROLIFIC_PID=TEST1&STUDY_ID=s1&SESSION_ID=x1 を開いて、数人のテスト参加者として調査を通して試してください。スクリーナーで一度「No」と答え、テスト参加者に C1SCREEN のコードが表示されることを確認します。終了した参加者には C1HEADLN が表示され、信頼と習慣のページは、参加者全体で両方の順序で現れるはずです。テスト参加者は条件に数えられ、エクスポートにも現れます。本番の公開の前に、サーバーを停止し、annotation_output/ を削除してください。参加者は、公開されたアドレスを通じてのみ調査に到達します。サーバーをオンラインにする方法は、VPS への Potato のデプロイで説明されています。

回答の CSV へのエクスポート

Potato は、調査の進行中に、各参加者の回答を annotation_output/<participant>/user_state.json に保存します。CSV エクスポートは、それらのファイルを三つの表にします。

bash
python -m potato.export --config config.yaml --format csv --output results/

コマンドは results/annotations.csv、results/participants.csv、results/phase_responses.csv を書き出します。

ファイル一行の単位内容
annotations.csv参加者と見出し評定。accuracy.Very accurate のように、回答の選択肢ごとに一列
participants.csv参加者condition_source の条件、到着順、カウンターバランスされたページの順序、スクリーンアウトが起きたページ
phase_responses.csv調査ページの回答フェーズ、ページ、質問、選択肢、回答

6 人のシミュレートされた参加者による Potato 2.12.1 でのテスト実行は、participants.csv と phase_responses.csv の最初の行を次のように書き出しました。

text
user_id,condition_source,condition_ordinal,cell_ordinal,latin_ordinal,final_phase,screened_out,screened_out_page,skipped_pages,page_orders,question_orders,runtime_runs,runtime_answers
5f00a9c,a social media account,0,0,,done,0,,,"{""group_0"": [""Media_trust"", ""News_habits""]}",{},{},{}
5f01a9c,a national newspaper,1,0,,done,0,,,"{""group_0"": [""News_habits"", ""Media_trust""]}",{},{},{}
 
user_id,phase,page,sequence,schema,label_name,value
5f00a9c,prestudy,Consent,0,consent,I agree,I agree
5f00a9c,prestudy,Screener,0,reads_news,Yes,Yes
5f00a9c,prestudy,Screener,1,age,age,20
5f00a9c,poststudy,Media_trust,0,trust,Newspapers,A great deal

R、Stata、SPSS は三つのファイルすべてを読み込み、user_id がファイルを結合します。annotations.csv では、行の accuracy の評定は、値が入っている accuracy. の列です。participants.csv で screened_out が 1 の行には、調査の回答があり、評定はありません。

次に読むもの