--- title: "FAQ Page" output: rmarkdown::html_vignette description: > Frequently Asked Questions vignette: > %\VignetteIndexEntry{FAQ Page} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} library(projoint) library(dplyr) library(ggplot2) library(patchwork) ``` ## What's the difference between "profile-level" and "choice-level" conjoint analysis??
Choice-level analysis is simpler, easier, and more powerful than profile-level analysis. Conjoint designs originated in market research and psychology where each respondent is asked to rate each of two different profiles (e.g., two products). Each of the two ratings provided separate information, and the two are analyzed as separate observations. Researchers with this profile-level design find it convenient to arrange their data with one profile per row, and thus twice as many rows as respondents.

Unfortunately, when social scientists adopted the conjoint survey design, they kept the same profile-level design but changed the outcome measure from separate ratings to a single choice between the two profiles (e.g., to reflect a voter choice between two candidates). In this situation, respondents asked to make one choice between the two profiles that are exactly dependent, as choosing one necessarily meant not choosing the other (e.g., in a two-candidate partisan election, one observation would be "Democrat" and the other would be "not the Republican"). Using this profile-level design with 2*n rows but only n independent observations requires the introduction of complicated statistical procedures to correct for the dependence induced solely by the researcher's decision to organize the data in this complicated way.

We recommend the much simpler and more powerful choice-level design. The idea is to arrange data at the level of the respondent's choice, so that each row in the data matrix includes information about one choice (and both profiles together, with n observations and n rows). Our AJPS article clarifies this point, shows how this choice-level analysis vastly simplifies the notation, statistical analysis procedures, and intuition, and greatly expands the substantive questions conjoint analysis be used to answer.

## What if I have profile-level data?
Transform your data to choice-level, which is simpler and more powerful. To replicate old analyses, you can also use our profile-level tools
Profile-Level MMs (All Levels) ```{r, echo = FALSE} data("exampleData1") outcomes <- paste0("choice", 1:8) outcomes <- c(outcomes, "choice1_repeated_flipped") out1 <- reshape_projoint(exampleData1, outcomes) ``` ```{r} mm0 <- projoint(out1, .structure = "profile_level", .estimand = "mm") print(mm0) summary(mm0) ```
Profile-Level MMs (Specific Level) ```{r} qoi_1 <- set_qoi( .structure = "profile_level", .estimand = "mm", .att_choose = "att1", .lev_choose = "level1" ) mm1 <- projoint(out1, .qoi = qoi_1) print(mm1) summary(mm1) ```
Profile-Level MMs (Specific Level, Manual IRR) ```{r} mm1b <- projoint(out1, .qoi = qoi_1, .irr = 0.75) print(mm1b) summary(mm1b) ```
Profile-Level AMCEs (All Levels) ```{r} amce0 <- projoint(out1, .structure = "profile_level", .estimand = "amce") print(amce0) summary(amce0) ```
Profile-Level AMCEs (Specific Level) ```{r} qoi_3 <- set_qoi( .structure = "profile_level", .estimand = "amce", .att_choose = "att1", .lev_choose = "level3", .att_choose_b = "att1", .lev_choose_b = "level1" ) amce1 <- projoint(out1, .qoi = qoi_3) print(amce1) summary(amce1) ```
Profile-Level AMCEs (Specific Level, Manual IRR) ```{r} amce1b <- projoint(out1, .qoi = qoi_3, .irr = 0.75) print(amce1b) summary(amce1b) ```
💡 Tip: When to Use .by_var Use .by_var only when comparing profile-level MMs between two groups (e.g., Democrats vs. Republicans). For AMCEs or choice-level quantities, .by_var is not currently supported.
### 📈 Profile-Level MMs and AMCEs
Estimate ```{r} data("out1_arranged") mm <- projoint(out1_arranged, .structure = "profile_level") amce <- projoint(out1_arranged, .structure = "profile_level", .estimand = "amce") ```
Visualize * Marginal Means ```{r, fig.width = 6, fig.height = 6} plot(mm) ``` * AMCEs ```{r, fig.width = 6, fig.height = 6} plot(amce) ```
Profile-Level Subgroup Comparison: White vs. Non-White Respondents ```{r, fig.height = 6.5, fig.width = 7} outcomes <- c(paste0("choice", 1:8), "choice1_repeated_flipped") df <- exampleData1 |> mutate(white = ifelse(race == "White", 1, 0)) df_0 <- df |> filter(white == 0) |> reshape_projoint(outcomes) df_1 <- df |> filter(white == 1) |> reshape_projoint(outcomes) df_d <- df |> reshape_projoint(outcomes, .covariates = "white") data_file <- system.file("extdata", "labels_arranged.csv", package = "projoint") if (data_file == "") stop("File not found!") df_0 <- read_labels(df_0, data_file) df_1 <- read_labels(df_1, data_file) df_d <- read_labels(df_d, data_file) out_0 <- projoint(df_0, .structure = "profile_level") out_1 <- projoint(df_1, .structure = "profile_level") out_d <- projoint(df_d, .structure = "profile_level", .by_var = "white") plot_0 <- plot(out_0) plot_1 <- plot(out_1) plot_d <- plot(out_d, .by_var = TRUE) plot_0 + coord_cartesian(xlim = c(0.2, 0.8)) + labs(title = "Non-white", x = "AMCE") + theme(plot.title = element_text(hjust = 0.5)) + plot_1 + coord_cartesian(xlim = c(0.2, 0.8)) + labs(title = "White", x = "AMCE") + theme(axis.text.y = element_blank(), plot.title = element_text(hjust = 0.5)) + plot_d + coord_cartesian(xlim = c(-0.4, 0.4)) + labs(title = "Difference", x = "Difference") + theme(axis.text.y = element_blank(), plot.title = element_text(hjust = 0.5)) ```
## Is there other conjoint software??
See Anton Strezhnev's Conjoint Survey Design Tool (Link: conjointSDT) ### 1. Generate a JavaScript or PHP randomizer Anton Strezhnev's **Conjoint Survey Design Tool** (Link: [conjointSDT](https://github.com/astrezhnev/conjointsdt/)) produces a JavaScript or PHP randomizer. #### JavaScript The JavaScript randomizer can be inserted into the first screen of your Qualtrics survey using **Edit Question JavaScript**. Example screenshot: ![](https://yhoriuchi.github.io/projoint/man/figures/embedded_js.png){#id .class width=80% height=80%} - Example JavaScript: [Download here](https://raw.githubusercontent.com/yhoriuchi/projoint/master/data-raw/example.js) The JavaScript runs internally within Qualtrics and generates *embedded fields* for each conjoint task. For example: - `"K-1-1-7"` = value for the 7th attribute, first profile, first task - `"K-5-2-5"` = value for the 5th attribute, second profile, fifth task #### PHP Alternatively, the PHP randomizer must be hosted externally. Example hosted on our server: https://www.horiuchi.org/php/ACHR_Modified_2.php (PHP file [here](https://raw.githubusercontent.com/yhoriuchi/projoint/master/data-raw/ACHR_Modified_2.php)) This method was used in: [Agadjanian, Carey, Horiuchi, and Ryan (2023)](https://www.nowpublishers.com/article/Details/QJPS-21119) --- ### 2. Modify your JavaScript or PHP randomizer You may want to add constraints — for example, **prevent ties** between profiles. To do this, you can manually modify your JavaScript or PHP. In the future, **projoint** will offer easier ways to add constraints! Until then, resources like [OpenAI’s GPT-4](https://openai.com/gpt-4) can help you edit scripts. Example PHP snippet ensuring racial balance between profiles: ```php $treat_profile_one = "B-" . (string)$p . "-1-" . (string)$treat_number; $treat_profile_two = "B-" . (string)$p . "-2-" . (string)$treat_number; $cond1 = $returnarray[$treat_profile_one] == "White" && $returnarray[$treat_profile_two] == $type; $cond2 = $returnarray[$treat_profile_two] == "White" && $returnarray[$treat_profile_one] == $type; if ($cond1 or $cond2) { $complete = True; } ``` If you have good examples of manual constraints, please email [Yusaku Horiuchi](mailto:yusaku.horiuchi@gmail.com)! --- ### 3. Add conjoint tables with embedded fields in Qualtrics After generating the randomizer, you must create **HTML tables** displaying embedded fields for each task. Example of the first task: ![](https://yhoriuchi.github.io/projoint/man/figures/screenshot_first.png){#id .class width=80% height=80%} - Example HTML file: [task_first.html](https://raw.githubusercontent.com/yhoriuchi/projoint/master/data-raw/task_first.html) Each conjoint study typically includes **5-10 tasks**. The embedded fields update across tasks: e.g., `"K-1..."` for Task 1, `"K-2..."` for Task 2, and so on. --- #### Adding a repeated task (recommended!) It’s easy to create a **repeated task** for intra-respondent reliability (IRR) estimation: - Copy the HTML for Task 1 later into the survey (e.g., after Task 5) - **Flip** Profile 1 and Profile 2 (swap the embedded field digits) Example repeated task: ![](https://yhoriuchi.github.io/projoint/man/figures/screenshot_last.png){#id .class width=80% height=80%} - Example HTML: [task_repeated.html](https://raw.githubusercontent.com/yhoriuchi/projoint/master/data-raw/task_repeated.html) --- ### 4. Sample Qualtrics survey template We provide a full **Qualtrics QSF file** ready to use! ```{r, echo=FALSE, warning = F} library(downloadthis) download_link( link = "https://raw.githubusercontent.com/yhoriuchi/projoint/master/data-raw/CHKKK_Mummolo_and_Nall_full_replication_W1_Lucid_-_August_2021.qsf", button_label = "Download QSF file", button_type = "danger", has_icon = TRUE, icon = "fa fa-save", self_contained = FALSE ) ```
This file recreates a standard conjoint survey setup based on Mummolo and Nall (2017).