본문으로 건너뛰기
튜토리얼21분 분량

라이선스가 끝나기 전에 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건에서 설문을 멈추며, 두 End of Survey 요소는 모두 완료 코드와 함께 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_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를 읽습니다
두 End of Survey 리디렉션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"을 읽습니다. 헤드라인 블록의 두 질문은 설정의 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에서 나중에 자리 수를 늘릴 수 있습니다.
  • Timing. 헤드라인은 이제 어노테이션 항목이고, Potato는 각 참여자의 user_state.json에 항목별 시간을 기록합니다. Timing 질문은 제거됩니다.
  • 슬라이더 문구. 2.12.1의 가져오기는 슬라이더의 문장 라벨을 질문 텍스트에 덧붙여 "...watching news: Minutes per day"를 만들었으며, surveys/News_habits.json의 설명은 원래 질문으로 되돌렸습니다. 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설문 페이지의 답변단계, 페이지, 질문, 선택지, 답변

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. 열 하나입니다. participants.csv에서 screened_out이 1인 행에는 설문 답변이 있고 평가는 없습니다.

다음으로 볼 자료