Install any skill in seconds. Free to start, no credit card required.
Get Started Free →brycewang-stanford/conjoint-cleaning
Clean and reshape Qualtrics conjoint exports to analysis-ready long format.
Passed 19 of 23 test cases with the skill, and 16 of 23 without it.
and 2 more in the full report
4 fixed15 passed either way3 still failing1 broke
Tokens, turns and time describe resource use, not a dollar price.
One of 4 test cases the skill fixed. Same model, same prompt, with and without the skill.
When recoding string attribute levels into factors for conjoint analysis in dplyr, we want to make sure pilot-only levels or typos don't silently default or slip through as valid factor levels. Show the R recoding function call with the appropriate safeguard flag.
| Checked | Without skill | With skill |
|---|---|---|
| Uses recode_factor with .default = NA_character_ to explicitly trap unrecognized values. | Missed | Passed |
The instructions your model reads when the skill loads.
Export format: When exporting from Qualtrics, select "Use choice text" (not "Use numeric values") so that attribute levels appear as human-readable labels. If working with non-Latin scripts (Chinese, Korean, Arabic), export as XLSX rather than CSV to avoid UTF-8/ANSI encoding issues. On Windows with East Asian locales, read.csv() may still require Sys.setlocale() to match the file encoding before import (see ?cjoint::read.qualtrics East Asian Language Support).
Metadata rows: Current Qualtrics CSV exports include 3 header rows before respondent data: (1) variable identifiers, (2) question text/descriptions, (3) ImportId JSON. Legacy exports have 2 rows. The cjoint::read.qualtrics() parameter new.format = TRUE (set explicitly; default is FALSE) handles the 3-row format. For manual import via readxl::read_excel() or readr::read_csv(), skip the appropriate number of metadata rows after reading headers.
Randomization order columns: If "Export viewing order data" is enabled, Qualtrics adds _DO_ columns (e.g., Block1_DO) containing pipe-separated integers showing element display order. These are useful for task-order robustness checks but are not needed for the core reshape.
Qualtrics conjoint experiments use one of three implementation methods, each producing different column naming conventions:
Method A — Conjoint Survey Design Tool (Strezhnev): Generates JavaScript that Qualtrics executes to randomize profiles. Column naming follows F-{task}-{profile}-{attribute} for attribute levels and F-{task}-{attribute} for attribute names. The cjoint R package's read.qualtrics() function is purpose-built for this format.
Method B — Custom JavaScript + Embedded Data: Researchers write JavaScript to randomize attributes and store values in Qualtrics embedded data fields. Column naming is researcher-defined. Two common conventions: (i) C{x}-F-{task}-{idx} for attribute names and C{x}-F-{task}-{profile}-{idx} for profile values; (ii) the Graham (2020) convention, choice{task}_{attr}{profile} with fixed attribute order (e.g., choice1_bread1) or c{task}_attrib{pos}_name / c{task}_attrib{pos}_sand{profile} when attribute order is also randomized. Requires manual reshaping (Section 4).
Method C — Loop & Merge: Each loop iteration represents one conjoint task. Embedded data fields are referenced via ${e://Field/variable_name} and displayed with ${lm://Field/N}. Column names reflect the embedded data field structure. Requires manual reshaping.
Before writing any cleaning code: Inspect the actual column headers, the QSF survey definition file, or any JavaScript in the survey to determine which method was used. Do not assume a column naming convention.
Before writing custom reshaping code, check whether an existing package handles the data format:
cjoint::read.qualtrics() — Purpose-built for Conjoint SDT exports (Method A). Reads Qualtrics CSV directly, handles metadata rows, outputs one row per profile with a selected column. Parameters: responses (choice column names), covariates (respondent-level variables), respondentID, new.format (TRUE for 3-row headers), ranks (for rank/rating/top-L designs). Supports binary forced choice, profile ranks, per-profile ratings, and top-L choices; see ?cjoint::read.qualtrics Details for the four response types. Requires PHP/JS output from the Conjoint Survey Design Tool.
cjdata::reshape_conjoint() — Lightweight alternative. Functions: read_Qualtrics() + reshape_conjoint(). Handles basic wide-to-long conversion. Requires the terminal character of each outcome string to be {"1","2"} or {"A","B"} (so "Candidate A" works; Japanese zenkaku digits supported). Respondent covariates merged separately.
projoint::reshape_projoint() — For measurement-error-corrected analysis per Clayton, Horiuchi, Kaufman, King, and Komisarchik (2023). Built-in support for repeated tasks (IRR estimation), missing-agreement imputation (.fill = TRUE), and bias-corrected AMCEs. Outcome column names must contain task-ID digits, and the repeated-task outcome must be the last element of .outcomes. Expects wide columns named K-{task}-{attribute} and K-{task}-{profile}-{attribute} by default (.alphabet = "K"); selected profile is parsed from the final character of each outcome string via .choice_labels (default c("A","B")). Specify .flipped = TRUE when the repeated task presents profiles in reversed left/right order (see exampleData1 vs. exampleData2 in the manual); this changes how agreement is computed. Trap: projoint::read_Qualtrics() hard-codes a 2-row metadata skip (legacy format). For current 3-row Qualtrics exports, pre-strip the third metadata row or read manually via readr::read_csv(skip = 3) before calling reshape_projoint().
cregg::cj_tidy() — Reshapes wide data across the three-level respondent/task/profile hierarchy via two named lists: profile_variables (features and profile-specific outcomes that vary within a task) and task_variables (variables that vary by task but not across profiles within it). Crucially, a choice variable that names the chosen profile ("left"/"right") goes in task_variables and must be recoded after reshaping, whereas per-profile "chosen" indicators go in profile_variables — getting this wrong silently corrupts the outcome. Constraint handling is not a cj_tidy feature; two-way design constraints are specified downstream via * in the amce()/cj() formula.
Package decision rule (default then escape hatch):
cjoint::read.qualtrics()projoint::reshape_projoint()cjdata::reshape_conjoint()test cases passed, vs 16 / 23 without
More skills from the same source and nearby in the registry, with their headline benchmark lift.