Marketing - MaxDiff - Varying Coefficients

From Q
Jump to: navigation, search

Runs a boosted varying coefficients model on MaxDiff data.

Example

The table below shows the output of a boosted varying coefficients model using MaxDiff data on technology companies. In this case, 2 covariates have been selected (likelihood of recommending Apple and Samsung) and a boosted 3-class latent class analysis over respondents is run at the end. The histograms show the distribution of preference shares across respondents.

The Design input table needs to be in a form similar to the one shown below. The 'Version' column is optional when there is only one version in the design. The 'Question' column is also optional. However, if these columns are included, they must have the names 'Version' and 'Question'. The columns after this contain the indices of the alternatives presented to the respondents.

Options

Experimental Design

Design location One of,

Use an existing table Select an existing table in the project in Design.
Experimental design R output Select a MaxDiff design created with Marketing - MaxDiff - Experimental Design.
Variables Provide Alternatives (and optionally Design version) where each alternative contains the alternatives presented by question, analogous to the columns of a tabular design.
Provide a URL Enter a URL in Design URL.

Design The design table. This may contain a 'Version' column and if not present there is assumed to be one version. It may also contain a 'Question' column. All other columns are assumed to contain the alternatives presented, hence the number of other columns defines the number of alternatives per question.

Design URL The URL to a CSV file containing the design.

Alternative labels Labels for the alternatives. This can be left out in most cases as the alternatives can usually be extracted from the best and worst selections.

Respondent Data

Version A variable which indicates which version of the design was provided to each respondent.

Best selections The best selections for each question.

Worst selections The worst selections for each question.

Missing data See Missing Data Options.

Model

Type Switch between MaxDiff models: Latent Class Analysis, Hierarchical Bayes and Varying Coefficients.

Covariates Covariates to be used in the model.

Additional latent class analysis Whether to run a final latent class analysis over respondents.

Number of classes The number of classes in the latent class analysis over respondents.

MaxDiff logit Choose between Tricked Logit and Rank-Ordered Logit with Ties. The former is faster but the latter is used in Segments > Latent Class Analysis for MaxDiff in Q.

Questions left out for cross-validation The number of questions to leave out per respondent for cross-validation.

Code

var allow_control_groups = Q.fileFormatVersion() > 10.9; // Group controls for Displayr and later versions of Q

if (allow_control_groups)
    form.group("Experimental design")

var dt = form.comboBox({name: "formDesignLocation", label: "Design source", alternatives: ["Use an existing table", "Experimental design R output", "Variables", "Provide a URL"],
                        default_value: "Use an existing table", prompt: "Select design source"}).getValue();
if (dt == "Use an existing table")
    form.dropBox({name: "formDesign", label: "Design", types: ["Table", "RItem:matrix,array,data.frame,table"], required: true, prompt: "Select a design from a table"});
else if (dt == "Experimental design R output")
    form.dropBox({name: "formDesign", label: "Design", types: ["RItem:MaxDiffDesign,data.frame"], required: true, prompt: "Select a MaxDiff design object"});
else if (dt == "Variables")
{
    form.dropBox({label: "Alternatives",
                  types:["Variable: Numeric, Categorical, OrderedCategorical"],
                  name: "formAlternatives", required: true, multi: true,
                  prompt: "Select design alternative variables"});
    form.dropBox({label: allow_control_groups ? "Design version" : "Experimental design version",
                  types:["Variable: Numeric, Categorical, OrderedCategorical"],
                  name: "formDesignVersion", required: false,
                  prompt: "Select the design version variable"});
}
else
    form.textBox({name: "formURL", label: "Design URL", required: true, prompt: "Specify a URL to the design file"});

if (dt != "Experimental design R output")
    form.textBox({name: "formLabels", label: "Alternative labels", required: false,
                  prompt: "For example: Coke, Diet Coke, Pepsi. Not required if deduced from design or responses."});

if (allow_control_groups)
    form.group("Respondent data")

form.dropBox({label: allow_control_groups ? "Version" : "Version variable",
            types:["Variable: Numeric, Categorical, OrderedCategorical"],
            name: "formVersion", required: false, prompt: "Select the respondent version variable"});
form.dropBox({label: "Best selections", 
            types:["Variable: Numeric, Categorical, OrderedCategorical"], 
            name: "formBest", multi: true, prompt: "Select the best choice variables"});
form.dropBox({label: "Worst selections", 
            types:["Variable: Numeric, Categorical, OrderedCategorical"], 
            name: "formWorst", multi: true, prompt: "Select the worst choice variables"});
form.comboBox({label: "Missing data", name: "formMissing",
               alternatives: ["Error if missing data", "Exclude cases with missing data", "Use partial data"],
               default_value: "Use partial data", prompt: "Options for handling cases with missing data"});

if (allow_control_groups)
    form.group("Model")
var type = form.comboBox({name: "formType", label: "Type", alternatives: ["Latent Class Analysis", "Hierarchical Bayes", "Varying Coefficients"],
                          default_value: "Varying Coefficients", prompt: "Select the MaxDiff analysis type"});
var is_lc = type.getValue() == "Latent Class Analysis";
var is_hb = type.getValue() == "Hierarchical Bayes";
var is_vc = type.getValue() == "Varying Coefficients";

var web_mode = (!!Q.isOnTheWeb && Q.isOnTheWeb());
if (is_hb && Q.fileFormatVersion() < 12.31 && !web_mode)
    alert("A newer version of Q (version 5.3) is required to run Hierarchical Bayes. Please contact support@q-researchsoftware.com to upgrade.");

if (is_lc)
   form.setHeading("MaxDiff - " + "Latent Class Analysis");
else if (is_vc)
   form.setHeading("MaxDiff - " + "Varying Coefficients");
else if (is_hb)
   form.setHeading("MaxDiff - " + "Hierarchical Bayes");
if (is_vc || is_hb)
    form.dropBox({label: "Covariates",
            types:["Variable: Numeric, Categorical, OrderedCategorical"], 
            name: "formCovariates", multi: true, required: is_vc, prompt: "Select covariate variables"});
if (is_vc)
    var lc = form.checkBox({label: "Additional latent class analysis", name: "formLC", default_value: true, prompt: "Run a final latent class analysis"});

if (is_lc | (is_vc && lc.getValue()))
    form.numericUpDown({name: "formClassesLC", label: "Number of classes", default_value: 1, increment: 1, maximum:100, minimum: 1,
                        prompt: "Specify the number of classes in the model"});
if (is_hb) // separate controls for HB and LC so classes are not carried over
    form.numericUpDown({name: "formClassesHB", label: "Number of classes", default_value: 1, increment: 1, maximum:100, minimum: 1,
                        prompt: "Specify the number of classes in the model"});
form.comboBox({label: "MaxDiff logit", alternatives: ["Tricked Logit", "Rank-Ordered Logit with Ties"], name: "formModel",
               default_value: "Tricked Logit", prompt: "Select MaxDiff logit treatment"});
form.numericUpDown({name: "formCV", label: "Questions left out for cross-validation", default_value: 0, increment: 1,
                    maximum:100, minimum: 0, prompt: "Specify number of questions to leave out"});
if (is_hb)
{
    form.numericUpDown({name: "formIterations", label: "Iterations", default_value: 100, increment: 10,
                        maximum:1000000, minimum: 1, prompt: "Specify number of hierarchical Bayes iterations"});
    form.numericUpDown({name: "formChains", label: "Chains", default_value: 8, increment: 1,
                        maximum:1000, minimum: 1, prompt: "Specify number of chains"});
    form.numericUpDown({name: "formMaxTreeDepth", label: "Maximum tree depth", default_value: 10, increment: 1,
                        maximum:1000, minimum: 1, prompt: "Specify maximum tree depth (only change if necessary)"});
}
library(flipMaxDiff)
df <- if (formType == "Varying Coefficients" && exists("formCovariates")) {
    names(formCovariates) <- sapply(formCovariates, function(x) attr(x, "label"))
    formCovariates
} else
    NULL
 
if (formType == "Hierarchical Bayes"){
    frml <- QFormula(~formCovariates)
    dat <- QDataFrame(formCovariates)
    if (!length(dat))
        frml <- dat <- NULL
}else
    frml <- dat <- NULL

max.diff <- FitMaxDiff(design = if(exists("formDesign")) formDesign else if (exists("formURL")) read.csv(formURL),
    version = if (is.null(formVersion))  rep(1, length(formBest[[1]])) else formVersion,
    best = if (exists("formBest")) formBest,
    worst = if (exists("formWorst")) formWorst,
    design.alternatives = if (exists("formAlternatives")) formAlternatives,
    design.version = if (exists("formDesignVersion")) formDesignVersion,
    alternative.names = if (exists("formLabels") && formLabels != "") formLabels else NULL,
    n.classes = get0("formClassesLC", ifnotfound = 0) + get0("formClassesHB", ifnotfound = 0),
    subset = if (all(QFilter)) NULL else QFilter,
    weights = QPopulationWeight,
    missing = formMissing,
    characteristics = df,
    cov.formula = frml, cov.data = dat,
    lc = if (exists("formLC")) formLC else TRUE,
    output = "Parameters",
    tasks.left.out = formCV,
    is.tricked = if(exists("formModel")) formModel == "Tricked Logit" else TRUE,
    algorithm = if (formType == "Hierarchical Bayes") "HB-Stan" else "Default",
    hb.iterations = if(exists("formIterations")) formIterations else 0,
    hb.chains = if(exists("formChains")) formChains else 0,
    hb.max.tree.depth = if(exists("formMaxTreeDepth")) formMaxTreeDepth else 0,
    hb.sigma.prior.rate = 1,
    hb.sigma.prior.shape = 1)

See Also

Other MaxDiff models:

Compare MaxDiff models:

Create an ensemble of MaxDiff models:

Save variables from MaxDiff varying coefficients outputs:

See MaxDiff Software or What is MaxDiff? for an overview of key MaxDiff concepts and resources, and also Latent Class Analysis Software.