*! version 1.0.0 22may2021

Title

conjoint -- Analysis and visualisation of conjoint (factorial) experiments

Syntax

conjoint
depvar
indepvars
[if] [in]
,
estimate(estimate_options)
[options display_options]

Options

Estimate Options
amce estimate average marginal component effects (AMCEs)

mm estimate marginal means (MMs)

Options
id(varname) variable identifying respondents for calculating clustered standard errors

subgroup(varname) variable identifying subgroups to be analysed

baselevels(numlist) list of the baselevels for each variable (if amce are estimated)

constraints(varlist) list of sets of variables to identify profile constraints
(if amce are estimated)

h0(#) null hypothesis value (if mm are estimated)

Display Options
notable suppress coefficient table

graph[(#)] plot coefficients and type of plot

Description

conjoint can analyse and visualise choice-based conjoint (factorial) experiments. More specifically, conjoint can
estimate average marginal component effects (AMCE) and marginal means (MM) following the methods described in
Hainmueller et al., (2014) and Leeper et al., (2020) and
implemented in the R packages, cjoint (Barari et al., 2018)
and cregg (Leeper and Barnfield, 2020). conjoint can estimate these
for fully randomised designs and AMCEs for designs with unlimited and complex profile constraints. conjoint
can also calculate estimates across subgroups, with different baselevels (AMCEs only) and null hypothesis
values (MMs only). The results can be simply and easily plotted via coefplot.

Options

Estimate Options

estimate() specifies the estimate type which can be amce or mm. amce
represent the average change in probability of a profile being selected if an attribute (variable) changes
from one level (the baselevel) to another level (the focal level). Alternatively, mm represent the
average probability a profile is selected given an attribute level.

Options

id(varname) specifies a variable identifying respondents for calculating clustered standard errors.

subgroup(varname) specifies a variable identifying subgroups over which to repeat the estimation.

baselevels(numlist) manually specifies the baselevel for each attribute in order to estimate the ACME
of each attribute level relative to that level. If not specified, the default baselevels are the first level
for each attribute. If specified, baselevels must be entered for every attribute
and in the order they appear in indepvars. The default is the first level of each attribute. For example,
with three attributes, baselevels could be manually specified with base(1 1 4) if the baselevels are to
be those represented by values of 1 for the first and second variable, and the level represented by
values of 4 for the third variable (only applicable if AMCEs are estimated).

constraints(varlist) specifies sets of attributes (variables) where there are constrained or restricted
attribute level combinations. Sets of attributes should be described using interactions (#) between the
attributes and the constrained level combinations (within those sets of variables) will be detected
automatically. Although multiple sets of constraints are possible, and each set can include unlimited
attributes, each attribute can only appear in one set. Attributes can also be included here and not in
indepvars if their AMCEs are not to be estimated. For example, if there are implausible, and so constrained
level combinations involving variables X and Y, this could be specified using constraint(X#Y)
(only applicable if AMCEs are estimated).

h0(#) specifies the null hypothesis value for calculating t-statistics and p-values. If not specified, the
default value is 0.5 as most conjoints involve selecting from two alternatives and so the null hypothesis value
for each attribute level is 50%, or more specifically, H0 = 0.5 (only applicable if MMs are estimated).

Display Options

notable suppresses the display of the coefficients table.

graph[(#)] specifies to plot the coefficients via coefplot. graph or graph(0) specifies that all
estimates (which can include from different subgroups if relevant) are plotted on the same set of axes. Otherwise
# specifies that each set of estimates are plotted on separate sets of axes or subgraphs and arranged as # columns
with the number of rows necessary for the number of subgraphs. For example, if plotting two sets of
estimates, graph or graph(0) would plot them on the same set of axes, graph(1) would plot them
on separate axes stacked vertically in one column, and graph(2) would plot them side-by-side arranged in two columns.

Examples

Example 1

For an example using conjoint, we can use a immigration conjoint experiment dataset
(Hainmueller et al., 2013) as analysed in Hainmueller et al., (2014),
and using the two main R conjoint packages, cjoint (Barari et al., 2018)
and cregg (Leeper and Barnfield, 2020). This dataset, included as an ancillary file
(immigration_conjoint.dta) with accompanying do file (immigration_conjoint.do), includes responses from a sample
of American adults who were asked to choose from hypothetical immigrants that they believe should be allowed
into the United States.

First we can load in the data:

. use immigration_conjoint

We can estimate AMCEs using all attributes in the design with the standard errors adjusted for
clustering:

. conjoint Chosen_Immigrant Gender Education Language_Skills Country_of_Origin Job Job_Experience
Job_Plans Reason_for_Application Prior_Entry, est(amce) id(CaseID)

Next, and knowing that some combinations of country of origin and reason for application and education
and job were considered implausible and so restricted from the profiles seen by the participants, the same model
can be run but incorporating these constraints. This would equate to the first model that would be estimated using
cjoint on page 5 of Barari et al., (2018):

. conjoint Chosen_Immigrant Gender Education Language_Skills Country_of_Origin Job Job_Experience
Job_Plans Reason_for_Application Prior_Entry, est(amce) id(CaseID)
constraint(Country_of_Origin#Reason_for_Application Education#Job)

We could also run the same model but change the baselevel for language skills (the third attribute),
but remember we must also specify the baselevels for every attribute:

. conjoint Chosen_Immigrant Gender Education Language_Skills Country_of_Origin Job Job_Experience
Job_Plans Reason_for_Application Prior_Entry, est(amce) id(CaseID)
constraint(Country_of_Origin#Reason_for_Application Education#Job) base(1 1 4 1 1 1 1 1 1)

We could also use the same variables but estimate MMs as would be estimated using cregg on
page 9 of Leeper and Barnfield (2020):

. conjoint Chosen_Immigrant Gender Education Language_Skills Country_of_Origin Job Job_Experience
Job_Plans Reason_for_Application Prior_Entry, est(mm) id(CaseID)

Example 2

For a second example using conjoint, we can use a refugee return conjoint experiment dataset
(Ghosn et al., 2021a) as analysed in Ghosn et al., (2021b). This dataset,
included as an ancillary file (refugee_return_conjoint.dta) with accompanying do file (refugee_return_conjoint.do), includes
responses from a sample of Syrian refugees who were asked to choose from hypothetical locations to which to
consider returning.

First we can load in the data:

. use refugee_return_conjoint

We can estimate AMCEs across all participants and using all attributes and the standard errors adjusted for clustering
as shown in the left panel in Figure 3 of Ghosn et al., (2021b) using:

. conjoint Chosen ChancePeace Easework HarmR NumPpl, est(amce) id(ID)

We can also estimate the AMCEs by experience, or not, of violence as shown in the middle and right panel
in the same figure by specifying ExpViol as the subgroup variable:

. conjoint Chosen ChancePeace Easework HarmR NumPpl, est(amce) id(ID) subgroup(ExpViol)

The graph option can be specified with both of these commands to produce separate graphs of the effects. However to
combine them into the same figure (as per Figure 3) we could extract the results matrices from e() after each
conjoint command and adapt the code used to create each figure which is stored in e(graph_code) after each
commands.

Specifically, we would re-run the command estimating AMCEs across all participants:

. conjoint Chosen ChancePeace Easework HarmR NumPpl, est(amce) id(ID)

If we use ereturn list we can see these results are stored in e(results) and can be saved (as they will be
deleted when conjoint is run again) using:

. matrix overall_results = e(results)

We would also re-run the command estimating AMCEs for those who have, and have not, experienced violence but this time append
the option graph(2) to generate the graph code. Note we specify 2 as this will plot the estimates on two subgraphs
which are arranged side-by-side (in 2 columns) and this is most similar to our final intended graph (of 3 plots side-by-side).

. conjoint Chosen ChancePeace Easework HarmR NumPpl, est(amce) id(ID) subgroup(ExpViol) graph(2)

We can again use ereturn list again and see the results are stored in e(results_No) and e(results_Yes) based on
the labels of the two levels. We should again save these matrices:

. matrix no_exp_viol_results = e(results_No)

. matrix exp_viol_results = e(results_Yes)

Next we can use the display command with _asis (see display) to view the code used to generate the graph:

. display _asis "`e(graph_code)'"

From this code we can see how the results matrices (in this case they were called results_No and results_Yes)
are referred to and used. So, by adding our other matrix, matrix(overall_results[,1]), bylabel(Overall),
renaming the current two matrix references to match our new matrix names (e.g. exp_viol_results instead of
results_Yes), and change cols(2) to cols(3) to show our plots in 3 columns rather than 2, we can replicate
Figure 3 from Ghosn et al., (2021b) by:

. coefplot matrix(overall_results[,1]), bylabel(Overall) || matrix(no_exp_viol_results[,1]), bylabel(No experience)
|| matrix(exp_viol_results[,1]), bylabel(Experienced violence) ||, ci(( 5 6)) keep(*:) xline(0, lpattern(-) lcolor(black))
coeflabels( Low= "Low" Moderate= "Moderate" High= "High" Easy= "Easy" Moderate= "Moderate" Hard= "Hard" Low= "Low"
Moderate= "Mo derate" High= "High" None= "None" Some= "Some" Many= "Many" ) eqlabels( "Chance of peace lasting a year"
"Ease of finding work" "Chance of harm on route" "Number of people known there", asheadings) byopts(graphregion(col(white))
cols(3)) subtitle(, fcolor (gs15)) scale(0.7) xtitle(Estimated AMCEs)

Note you might want to change the sizes (or styles) of various parts of the plot. For example, the marker size: by adding msize(),
the x-axis title: by adding size() to xtitle(), and labels: by adding xlabel(,labsize()), the level labels: by adding
labsize() to coeflabels(), attribute labels: by adding labsize() to eqlabels(), and the subplot labels: by adding
size() to subtitle() (see also coefplot). If we repeat the above plot but change all these to small we finish with:

. coefplot matrix(overall_results[,1]), bylabel(Overall) || matrix(no_exp_viol_results[,1]), bylabel(No experience) ||
matrix(exp_viol_results[,1]), bylabel(Experienced violence) ||, ci(( 5 6)) keep(*:) xline(0, lpattern(-) lcolor(black)) coeflabels( Low= "Low"
Moderate= "Moderate" High= "High" Easy= "Easy" Moderate= "Moderate" Hard= "Hard" Low= "Low" Moderate= "Moderate" High= "High"
None= "None" Some= "Some" Many= "Many", labsize(small)) eqlabels( "Chance of peace lasting a year" "Ease of finding work"
"Chance of harm on route" "Number of people known there", asheadings labsize(small)) byopts(graphregion(col(white)) cols(3))
subtitle(, fcolor (gs15) size(small)) scale(0.7) xtitle(Estimated AMCEs, size(small)) xlabel(,labsize(small)) msize(small)

Remarks

Although conjoint can theoretically handle constraints involving sets of unlimited variables, estimation requires the generation of an
expression and this can exceed the limit allowed by Stata. This can happen in conjoint when there are too many variables
in a particular set, there are too many levels across the variables in a set, or the variable names are collectively too long. This should
not however occur when there are large numbers of constraints but each constraint only involves a few variables. For example, when you have
constraints involving a and b, c and d (specified as a#b c#d); whereas Stata may report an "expression too long" error if
you have complex constraints involving combinations of a,b,c and d (specified as a#b#c#d). This may be addressed in a future version.

Stored Results

conjoint stores some or all of the following in e():

Scalars

e(N) number of observations*

e(df_r) residual degrees of freedom*

e(df_m) model degrees of freedom* (if AMCEs are estimated)

e(r2) R-squared* (if AMCEs are estimated)

e(F) F statistic* (if AMCEs are estimated)

e(N_clust) number of clusters* (if id() is specified)

e(h0) null hypothesis value (if MMs are estimated)

Macros

e(graph_code) code used to generate graph (if graph[()] is specified)

e(baselevels) list of baselevels (if AMCEs are estimated)

e(constraints) list of constraints (if AMCEs are estimated constraints() is specified)

e(estimate) estimate type

e(indepvars) name of independent variables

e(model) ols

e(vce) vcetype

e(title) title in estimation output

e(depvar) name of dependent variable

e(cmdline) command as typed

e(cmd) conjoint

e(clustvar) name of cluster variable (if id() is specified)

Matrices

e(results) results table*

Note: Stored results marked with * will be stored for each subgroup using the notation e('stored result'_'subgroup label')
if subgroup() is specified.

Acknowledgments

This was completed as part of the award W911-NF-17-1-0030 from the Department of Defense and U.S. Army Research Office/Army
Research Laboratory under the Minerva Research Initiative. The views expressed are those of the author and should
not be attributed to the Department of Defense or the Army Research Office/Army Research Laboratory.

References

Barari, S., Berwick, E., Hainmueller, J., Hopkins, D., Liu, S., Strezhnev, A., & Yamamoto, T. 2018. cjoint: AMCE Estimator for
Conjoint Experiments. R package.

Ghosn, F., Chu, T.S., Simon, M., Braithwaite, A., Frith, M.J., & Jandali, J. 2021a. Replication Data for Journey Back Home:
Violence, Anchoring, and Refugee Decisions to Return. https://doi.org/10.7910/DVN/UGI0MH

Ghosn, F., Chu, T.S., Simon, M., Braithwaite, A., Frith, M.J., & Jandali, J. 2021b. The Journey Home: Violence, Anchoring, and
Refugee Decisions to Return. American Political Science Review, 1–17. https://doi.org/10.1017/S0003055421000344

Hainmueller, J., Hopkins, D.J., & Yamamoto, T. 2013. Replication data for: Causal Inference in Conjoint Analysis: Understanding
Multidimensional Choices via Stated Preference Experiments. https://doi.org/10.7910/DVN/THJYQR

Hainmueller, J., Hopkins, D.J., & Yamamoto, T. 2014. Causal Inference in Conjoint Analysis: Understanding Multidimensional
Choices via Stated Preference Experiments. Political Analysis, 22(1): 1-30. https://doi.org/10.1093/pan/mpt024

Leeper, T.J., & Barnfield, M. 2020. cregg: Simple Conjoint Tidying, Analysis, and Visualization. R package.

Leeper, T., Hobolt, S., & Tilley, J. 2020. Measuring Subgroup Preferences in Conjoint Experiments. Political Analysis,
28(2): 207-221. https://doi.org/10.1017/pan.2019.30

Author

Michael J. Frith

University College London

London, UK

michael.frith@ucl.ac.uk

Comments, criticisms, and suggestions are all welcome.