| Title: | Design and Analyze Choice-Based Conjoint Experiments |
|---|---|
| Description: | Design and evaluate choice-based conjoint survey experiments. Generate a variety of survey designs, including random designs, frequency-based designs, and D-optimal designs, as well as "labeled" designs (also known as "alternative-specific designs"), designs with "no choice" options, and designs with dominant alternatives removed. Conveniently inspect and compare designs using a variety of metrics, including design balance, overlap, and D-error, and simulate choice data for a survey design either randomly or according to a utility model defined by user-provided prior parameters. Conduct a power analysis for a given survey design by estimating the same model on different subsets of the data to simulate different sample sizes. Bayesian D-efficient designs using the 'cea' and 'modfed' methods are obtained using the 'idefix' package by Traets et al (2020) <doi:10.18637/jss.v096.i03>. Choice simulation and model estimation in power analyses are handled using the 'logitr' package by Helveston (2023) <doi:10.18637/jss.v105.i10>. |
| Authors: | John Helveston [cre, aut, cph] (ORCID: <https://orcid.org/0000-0002-2657-9191>) |
| Maintainer: | John Helveston <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.7.2 |
| Built: | 2026-05-13 08:05:40 UTC |
| Source: | https://github.com/jhelvy/cbctools |
Simulate choices for a survey design, either randomly or according to a utility model defined by user-provided prior parameters. When priors are provided, choices are simulated using the same probability computation framework as used in cbc_design() for consistency.
cbc_choices(design, priors = NULL)cbc_choices(design, priors = NULL)
design |
A |
priors |
A |
Returns the input design with an additional choice column
identifying the simulated choices.
library(cbcTools) # Create profiles and design profiles <- cbc_profiles( price = c(1, 2, 3), type = c("A", "B", "C"), quality = c("Low", "High") ) design <- cbc_design( profiles = profiles, n_alts = 2, n_q = 4 ) # Simulate random choices (default) choices_random <- cbc_choices(design) # Create priors and simulate utility-based choices priors <- cbc_priors( profiles = profiles, price = -0.1, type = c(0.5, 0.2), # vs reference level quality = 0.3 ) choices_utility <- cbc_choices(design, priors = priors)library(cbcTools) # Create profiles and design profiles <- cbc_profiles( price = c(1, 2, 3), type = c("A", "B", "C"), quality = c("Low", "High") ) design <- cbc_design( profiles = profiles, n_alts = 2, n_q = 4 ) # Simulate random choices (default) choices_random <- cbc_choices(design) # Create priors and simulate utility-based choices priors <- cbc_priors( profiles = profiles, price = -0.1, type = c(0.5, 0.2), # vs reference level quality = 0.3 ) choices_utility <- cbc_choices(design, priors = priors)
This function compares multiple CBC designs across key quality metrics including D-error, balance, overlap, and structural characteristics. Useful for evaluating different design methods or parameter settings.
cbc_compare(..., metrics = "all", sort_by = "d_error", ascending = NULL)cbc_compare(..., metrics = "all", sort_by = "d_error", ascending = NULL)
... |
Any number of |
metrics |
Character vector specifying which metrics to compare.
Options: "structure", "efficiency", "balance", "overlap", or "all" (default).
Can specify multiple: |
sort_by |
Character. Metric to sort designs by. Options: "d_error" (default), "balance", "overlap", "profiles_used", "generation_time", or "none" |
ascending |
Logical. If TRUE, sort in ascending order (lower is better). If FALSE, sort in descending order (higher is better). Default depends on metric. |
A cbc_comparison object containing comparison results, printed in
a formatted table.
library(cbcTools) # Create profiles profiles <- cbc_profiles( price = c(1, 2, 3), type = c("A", "B", "C"), quality = c("Low", "High") ) # Create different designs design_random <- cbc_design( profiles = profiles, method = "random", n_alts = 2, n_q = 4 ) design_stochastic <- cbc_design( profiles = profiles, method = "stochastic", n_alts = 2, n_q = 4 ) # Compare designs cbc_compare(design_random, design_stochastic) # Named comparison with specific metrics cbc_compare( Random = design_random, Stochastic = design_stochastic, metrics = c("efficiency", "balance"), sort_by = "d_error" )library(cbcTools) # Create profiles profiles <- cbc_profiles( price = c(1, 2, 3), type = c("A", "B", "C"), quality = c("Low", "High") ) # Create different designs design_random <- cbc_design( profiles = profiles, method = "random", n_alts = 2, n_q = 4 ) design_stochastic <- cbc_design( profiles = profiles, method = "stochastic", n_alts = 2, n_q = 4 ) # Compare designs cbc_compare(design_random, design_stochastic) # Named comparison with specific metrics cbc_compare( Random = design_random, Stochastic = design_stochastic, metrics = c("efficiency", "balance"), sort_by = "d_error" )
This function is depreciated. Use cbc_encode() instead
cbc_decode(data)cbc_decode(data)
data |
A |
The input object with categorical variables restored to their original format
This function creates experimental designs for choice-based conjoint experiments using multiple design approaches including optimization and frequency-based methods.
cbc_design( profiles, method = "random", priors = NULL, n_alts, n_q, n_resp = 100, n_blocks = 1, n_cores = NULL, no_choice = FALSE, label = NULL, balance_by = NULL, randomize_questions = TRUE, randomize_alts = TRUE, remove_dominant = FALSE, dominance_types = c("total", "partial"), dominance_threshold = 0.8, max_dominance_attempts = 50, max_iter = 50, n_start = 5, include_probs = FALSE, use_idefix = TRUE )cbc_design( profiles, method = "random", priors = NULL, n_alts, n_q, n_resp = 100, n_blocks = 1, n_cores = NULL, no_choice = FALSE, label = NULL, balance_by = NULL, randomize_questions = TRUE, randomize_alts = TRUE, remove_dominant = FALSE, dominance_types = c("total", "partial"), dominance_threshold = 0.8, max_dominance_attempts = 50, max_iter = 50, n_start = 5, include_probs = FALSE, use_idefix = TRUE )
profiles |
A data frame of class |
method |
Choose the design method: "random", "shortcut", "minoverlap", "balanced", "stochastic", "modfed", or "cea". Defaults to "random" |
priors |
A |
n_alts |
Number of alternatives per choice question |
n_q |
Number of questions per respondent (or per block) |
n_resp |
Number of respondents (for random/shortcut designs) or 1 (for optimized designs that get repeated) |
n_blocks |
Number of blocks in the design. Defaults to 1 |
n_cores |
Number of cores to use for parallel processing in the design search. Defaults to NULL, in which case it is set to the number of available cores minus 1. |
no_choice |
Include a "no choice" option? Defaults to FALSE |
label |
The name of the variable to use in a "labeled" design. Defaults to NULL |
balance_by |
Character vector of attribute names to balance sampling across. Ensures balanced representation across levels of specified attributes. Only compatible with "random", "shortcut", "minoverlap", and "balanced" methods. Cannot be used with labeled designs or D-optimal methods ("stochastic", "modfed", "cea"). Defaults to NULL |
randomize_questions |
Randomize question order for each respondent? Defaults to TRUE (optimized methods only) |
randomize_alts |
Randomize alternative order within questions? Defaults to TRUE (optimized methods only) |
remove_dominant |
Remove choice sets with dominant alternatives? Defaults to FALSE |
dominance_types |
Types of dominance to check: "total" and/or "partial" |
dominance_threshold |
Threshold for total dominance detection. Defaults to 0.8 |
max_dominance_attempts |
Maximum attempts to replace dominant choice sets. Defaults to 50. |
max_iter |
Maximum iterations for optimized designs. Defaults to 50 |
n_start |
Number of random starts for optimized designs. Defaults to 5 |
include_probs |
Include predicted probabilities in resulting design? Requires |
use_idefix |
If |
The method argument determines the design approach used:
"random": Creates designs by randomly sampling profiles for each respondent independently
"shortcut": Frequency-based greedy algorithm that balances attribute level usage
"minoverlap": Greedy algorithm that minimizes attribute overlap within choice sets
"balanced": Greedy algorithm that maximizes overall attribute balance across the design
"stochastic": Stochastic profile swapping with D-error optimization (first improvement found)
"modfed": Modified Fedorov algorithm with exhaustive profile swapping for D-error optimization
"cea": Coordinate Exchange Algorithm with attribute-by-attribute D-error optimization
The table below summarizes method compatibility with design features:
| Method | No choice? | Labeled designs? | Restricted profiles? | balance_by? | Blocking? | Interactions? | Dominance removal? |
| "random" | Yes | Yes | Yes | Yes | No | Yes | Yes |
| "shortcut" | Yes | Yes | Yes | Yes | No | No | Yes |
| "minoverlap" | Yes | Yes | Yes | Yes | No | No | Yes |
| "balanced" | Yes | Yes | Yes | Yes | No | No | Yes |
| "stochastic" | Yes | Yes | Yes | No | Yes | Yes | Yes |
| "modfed" | Yes | Yes | Yes | No | Yes | Yes | Yes |
| "cea" | Yes | Yes | No | No | Yes | Yes | Yes |
All methods ensure the following criteria are met:
No duplicate profiles within any choice set
No duplicate choice sets within any respondent
If remove_dominant = TRUE, choice sets with dominant alternatives are eliminated (optimization methods only)
The balance_by argument enables balanced sampling across specified attributes,
solving the problem of attribute-specific features that create imbalanced designs.
For example, consider an experiment on alternative vehicle powertrains with a "powertrain"
attribute for gas and electric vehicles. If you had an "electric_vehicle_range" attribute,
it should be 0 for non-electric powertrains, but using restrictions can lead to
over-representation of electric vehicles. Using balance_by = "powertrain" ensures that each
choice question samples proportionally from gas and electric powertrains, maintaining balance
even when electric vehicles have additional attributes.
Multiple attributes can be balanced simultaneously using balance_by = c("attr1", "attr2"),
which creates groups based on unique combinations of the specified attributes.
Creates designs where each respondent sees completely independent, randomly generated choice sets.
These methods use frequency-based algorithms that make locally optimal choices:
Shortcut: Balances attribute level usage within questions and across the overall design
Minoverlap: Minimizes attribute overlap within choice sets while allowing some overlap for balance
Balanced: Maximizes overall attribute balance, prioritizing level distribution over overlap reduction
These methods provide good level balance without requiring priors or D-error calculations and offer fast execution suitable for large designs.
These methods minimize D-error to create statistically efficient designs:
Stochastic: Random profile sampling with first improvement acceptance
Modfed: Exhaustive profile testing for best improvement (slower but thorough)
CEA: Coordinate exchange testing attribute levels individually (requires full factorial profiles)
When use_idefix = TRUE (the default), the function leverages the highly optimized
algorithms from the idefix package for 'cea' and 'modfed' design generation methods.
This can provide significant speed improvements, especially for larger
problems.
Key benefits of idefix integration:
Faster optimization algorithms with C++ implementation
Better handling of large candidate sets
Optimized parallel processing
Advanced blocking capabilities for multi-block designs
A cbc_design object containing the experimental design
library(cbcTools) # Create profiles for an apple choice experiment profiles <- cbc_profiles( price = c(1, 1.5, 2, 2.5, 3), type = c("Fuji", "Gala", "Honeycrisp"), freshness = c("Poor", "Average", "Excellent") ) # Basic random design design_random <- cbc_design( profiles = profiles, n_alts = 3, n_q = 6, n_resp = 100 ) head(design_random) # Inspect design cbc_inspect(design_random) # Greedy design with balanced frequency design_balanced <- cbc_design( profiles = profiles, method = "balanced", n_alts = 3, n_q = 6, n_resp = 100 ) # Design with priors using D-optimal method priors <- cbc_priors( profiles = profiles, price = -0.25, type = c("Gala" = 0.5, "Honeycrisp" = 1.0), freshness = c("Average" = 0.6, "Excellent" = 1.2) ) design_optimal <- cbc_design( profiles = profiles, method = "stochastic", priors = priors, n_alts = 3, n_q = 6, n_resp = 100, n_start = 3 ) # Compare designs cbc_compare( "Random" = design_random, "Balanced" = design_balanced, "D-optimal" = design_optimal )library(cbcTools) # Create profiles for an apple choice experiment profiles <- cbc_profiles( price = c(1, 1.5, 2, 2.5, 3), type = c("Fuji", "Gala", "Honeycrisp"), freshness = c("Poor", "Average", "Excellent") ) # Basic random design design_random <- cbc_design( profiles = profiles, n_alts = 3, n_q = 6, n_resp = 100 ) head(design_random) # Inspect design cbc_inspect(design_random) # Greedy design with balanced frequency design_balanced <- cbc_design( profiles = profiles, method = "balanced", n_alts = 3, n_q = 6, n_resp = 100 ) # Design with priors using D-optimal method priors <- cbc_priors( profiles = profiles, price = -0.25, type = c("Gala" = 0.5, "Honeycrisp" = 1.0), freshness = c("Average" = 0.6, "Excellent" = 1.2) ) design_optimal <- cbc_design( profiles = profiles, method = "stochastic", priors = priors, n_alts = 3, n_q = 6, n_resp = 100, n_start = 3 ) # Compare designs cbc_compare( "Random" = design_random, "Balanced" = design_balanced, "D-optimal" = design_optimal )
This function converts categorical variables between different coding schemes. Standard coding keeps categorical variables as-is (factor or character). Dummy coding uses a reference category (all zeros) with indicator variables for other levels. Effects coding uses -1 for the reference category to ensure coefficients sum to zero.
cbc_encode(data, coding = NULL, ref_levels = NULL)cbc_encode(data, coding = NULL, ref_levels = NULL)
data |
A |
coding |
Character. Type of encoding: "standard", "dummy", or "effects". If NULL and ref_levels is NULL, data is returned unchanged. If NULL and ref_levels is specified, the current encoding is maintained. |
ref_levels |
Named list specifying reference levels for categorical variables.
For example: |
The input object with specified encoding applied
library(cbcTools) # Create profiles with categorical variables profiles <- cbc_profiles( price = c(10, 20, 30), quality = c("Low", "Medium", "High"), brand = c("A", "B") ) # Create design (defaults to standard coding) design <- cbc_design( profiles = profiles, n_alts = 2, n_q = 4 ) # Convert to dummy coding design_dummy <- cbc_encode(design, coding = "dummy") head(design_dummy) # Convert to effects coding design_effects <- cbc_encode(design, coding = "effects") head(design_effects) # Convert back to standard design_standard <- cbc_encode(design_dummy, coding = "standard") head(design_standard) # Custom reference levels with dummy coding design_dummy2 <- cbc_encode( design, coding = "dummy", ref_levels = list(quality = "Medium", brand = "B") ) head(design_dummy2) # Update reference levels without changing encoding design_updated <- cbc_encode( design_dummy, ref_levels = list(quality = "High") ) head(design_updated)library(cbcTools) # Create profiles with categorical variables profiles <- cbc_profiles( price = c(10, 20, 30), quality = c("Low", "Medium", "High"), brand = c("A", "B") ) # Create design (defaults to standard coding) design <- cbc_design( profiles = profiles, n_alts = 2, n_q = 4 ) # Convert to dummy coding design_dummy <- cbc_encode(design, coding = "dummy") head(design_dummy) # Convert to effects coding design_effects <- cbc_encode(design, coding = "effects") head(design_effects) # Convert back to standard design_standard <- cbc_encode(design_dummy, coding = "standard") head(design_standard) # Custom reference levels with dummy coding design_dummy2 <- cbc_encode( design, coding = "dummy", ref_levels = list(quality = "Medium", brand = "B") ) head(design_dummy2) # Update reference levels without changing encoding design_updated <- cbc_encode( design_dummy, ref_levels = list(quality = "High") ) head(design_updated)
This function provides detailed inspection of choice experiment designs across multiple dimensions including design structure, efficiency metrics, attribute balance, overlap patterns, and variable encoding.
cbc_inspect(design, sections = "all", verbose = FALSE)cbc_inspect(design, sections = "all", verbose = FALSE)
design |
A |
sections |
Character vector specifying which sections to show.
Options: "structure", "efficiency", "balance", "overlap", "encoding", or "all" (default).
Can specify multiple: |
verbose |
Logical. If TRUE, shows additional technical details. If FALSE (default), shows simplified output. |
A cbc_inspection object containing the inspection results
library(cbcTools) # Create profiles and design profiles <- cbc_profiles( price = c(1, 2, 3), type = c("A", "B", "C"), quality = c("Low", "High") ) design <- cbc_design( profiles = profiles, n_alts = 2, n_q = 4 ) # Inspect all sections (default) - prints automatically cbc_inspect(design) # Store results for later use inspection <- cbc_inspect(design, sections = "balance") inspection # prints the same output # Verbose output with technical details cbc_inspect(design, verbose = TRUE)library(cbcTools) # Create profiles and design profiles <- cbc_profiles( price = c(1, 2, 3), type = c("A", "B", "C"), quality = c("Low", "High") ) design <- cbc_design( profiles = profiles, n_alts = 2, n_q = 4 ) # Inspect all sections (default) - prints automatically cbc_inspect(design) # Store results for later use inspection <- cbc_inspect(design, sections = "balance") inspection # prints the same output # Verbose output with technical details cbc_inspect(design, verbose = TRUE)
This function estimates the same model multiple times using different sample sizes to assess statistical power. It returns both the estimated models and a summary of coefficient estimates, standard errors, and power statistics.
cbc_power( data, outcome = "choice", obsID = "obsID", pars = NULL, randPars = NULL, n_breaks = 10, n_q = NULL, panelID = NULL, alpha = 0.05, return_models = FALSE, n_cores = NULL, ... )cbc_power( data, outcome = "choice", obsID = "obsID", pars = NULL, randPars = NULL, n_breaks = 10, n_q = NULL, panelID = NULL, alpha = 0.05, return_models = FALSE, n_cores = NULL, ... )
data |
A data frame containing choice data. Can be a |
outcome |
Name of the outcome variable column (1 for chosen, 0 for not). Defaults to "choice". |
obsID |
Name of the observation ID column. Defaults to "obsID". |
pars |
Names of the parameters to estimate. If NULL (default), will
auto-detect from column names for |
randPars |
Named vector of random parameters and their distributions ('n' for normal, 'ln' for log-normal). Defaults to NULL. |
n_breaks |
Number of sample size groups to test. Defaults to 10. |
n_q |
Number of questions per respondent. Auto-detected for |
panelID |
Name of the panel ID column for panel data. Auto-detected
as "respID" for multi-respondent |
alpha |
Significance level for power calculations. Defaults to 0.05. |
return_models |
If TRUE, includes full model objects in returned list. Defaults to FALSE. |
n_cores |
Number of cores for parallel processing. Defaults to
|
... |
Additional arguments passed to |
A cbc_power object containing:
power_summary: Data frame with sample sizes, coefficients, estimates,
standard errors, t-statistics, and power
models: List of estimated models (if return_models = TRUE)
sample_sizes: Vector of sample sizes tested
n_breaks: Number of breaks used
alpha: Significance level used
library(cbcTools) # Create profiles and design profiles <- cbc_profiles( price = c(1, 2, 3), type = c("A", "B", "C"), quality = c("Low", "High") ) design <- cbc_design(profiles, n_alts = 2, n_q = 6) # Simulate choices priors <- cbc_priors(profiles, price = -0.1, type = c(0.5, 0.2), quality = 0.3) choices <- cbc_choices(design, priors) # Run power analysis power_results <- cbc_power(choices, n_breaks = 8) # View results print(power_results) plot(power_results)library(cbcTools) # Create profiles and design profiles <- cbc_profiles( price = c(1, 2, 3), type = c("A", "B", "C"), quality = c("Low", "High") ) design <- cbc_design(profiles, n_alts = 2, n_q = 6) # Simulate choices priors <- cbc_priors(profiles, price = -0.1, type = c(0.5, 0.2), quality = 0.3) choices <- cbc_choices(design, priors) # Run power analysis power_results <- cbc_power(choices, n_breaks = 8) # View results print(power_results) plot(power_results)
Creates a standardized prior specification object for use in CBC analysis
functions like cbc_choices() and cbc_design(). Supports both fixed and random
parameters, with flexible specification of categorical variable levels and
interaction terms between fixed parameters.
cbc_priors( profiles, no_choice = NULL, n_draws = 100, draw_type = "halton", interactions = NULL, ... )cbc_priors( profiles, no_choice = NULL, n_draws = 100, draw_type = "halton", interactions = NULL, ... )
profiles |
A data frame of profiles created by |
no_choice |
Prior specification for no-choice alternative. Can be:
|
n_draws |
Number of draws for DB-error calculation if using Bayesian
priors. Defaults to |
draw_type |
Specify the draw type as a character: |
interactions |
A list of interaction specifications created by |
... |
Named arguments specifying priors for each attribute:
|
Fixed parameters assume all respondents have the same preference coefficients. Specify these as simple numeric values.
Random parameters assume preference coefficients vary across respondents
according to a specified distribution. Use rand_spec() to define the
distribution type, mean, and standard deviation.
For categorical variables, you can specify priors in two ways:
Unnamed vector: Provide coefficients for all levels except the first (which becomes the reference level). Order matters and should match the natural order of levels.
Named vector: Explicitly map coefficient values to specific levels. Any level not specified becomes the reference level.
Use the interactions parameter with int_spec() to include interaction
effects between attributes. Only interactions between fixed parameters are
supported. For categorical variables involved in interactions, you must
specify the relevant levels.
When including a no-choice alternative, provide a no_choice parameter.
This can be either a fixed numeric value or a rand_spec() for random
no-choice utility.
A structured prior specification object including parameter draws for random coefficients and interaction terms. This object contains:
pars: Vector of mean parameter values
par_draws: Matrix of parameter draws (if random parameters specified)
correlation: Correlation matrix for random parameters (if applicable)
interactions: List of interaction specifications
attrs: Detailed attribute information
Additional metadata for validation and compatibility checking
library(cbcTools) # Create profiles for examples profiles <- cbc_profiles( price = c(1, 1.5, 2, 2.5, 3), type = c('Fuji', 'Gala', 'Honeycrisp'), freshness = c('Poor', 'Average', 'Excellent') ) # Example 1: Simple fixed priors priors_fixed <- cbc_priors( profiles = profiles, price = -0.25, # Negative = prefer lower prices type = c(0.5, 1.0), # "Fuji" is reference level freshness = c(0.6, 1.2) # "Poor" reference level ) # Example 2: Named categorical priors (more explicit) priors_named <- cbc_priors( profiles = profiles, price = -0.25, type = c("Gala" = 0.5, "Honeycrisp" = 1.0), # "Fuji" is reference freshness = c("Average" = 0.6, "Excellent" = 1.2) # "Poor" is reference ) # Example 3: Random parameters - normal distributions for "price" and "freshness" priors_random <- cbc_priors( profiles = profiles, price = rand_spec( dist = "n", mean = -0.25, sd = 0.1 ), type = c(0.5, 1.0), freshness = rand_spec( dist = "n", mean = c(0.6, 1.2), sd = c(0.1, 0.1) ) ) # Example 4: Correlated random parameters priors_correlated <- cbc_priors( profiles = profiles, price = rand_spec( dist = "n", mean = -0.1, sd = 0.05, correlations = list( cor_spec( with = "type", with_level = "Honeycrisp", value = 0.3 ) ) ), type = rand_spec( dist = "n", mean = c("Gala" = 0.1, "Honeycrisp" = 0.2), sd = c("Gala" = 0.05, "Honeycrisp" = 0.1) ), freshness = c(0.1, 0.2) ) # Example 5: With interaction terms priors_interactions <- cbc_priors( profiles = profiles, price = -0.25, type = c("Fuji" = 0.5, "Honeycrisp" = 1.0), freshness = c("Average" = 0.6, "Excellent" = 1.2), interactions = list( # Price sensitivity varies by apple type int_spec( between = c("price", "type"), with_level = "Fuji", value = 0.1 ), int_spec( between = c("price", "type"), with_level = "Honeycrisp", value = 0.2 ), # Type preferences vary by freshness int_spec( between = c("type", "freshness"), level = "Honeycrisp", with_level = "Excellent", value = 0.3 ) ) ) # Example 6: Including no-choice option priors_nochoice_fixed <- cbc_priors( profiles = profiles, price = -0.25, type = c(0.5, 1.0), freshness = c(0.6, 1.2), no_choice = -0.5 # Negative values make no-choice less attractive ) # Example 7: Random no-choice priors_nochoice_random <- cbc_priors( profiles = profiles, price = -0.25, type = c(0.5, 1.0), freshness = c(0.6, 1.2), no_choice = rand_spec(dist = "n", mean = -0.5, sd = 0.2) ) # View the priors priors_fixed priors_randomlibrary(cbcTools) # Create profiles for examples profiles <- cbc_profiles( price = c(1, 1.5, 2, 2.5, 3), type = c('Fuji', 'Gala', 'Honeycrisp'), freshness = c('Poor', 'Average', 'Excellent') ) # Example 1: Simple fixed priors priors_fixed <- cbc_priors( profiles = profiles, price = -0.25, # Negative = prefer lower prices type = c(0.5, 1.0), # "Fuji" is reference level freshness = c(0.6, 1.2) # "Poor" reference level ) # Example 2: Named categorical priors (more explicit) priors_named <- cbc_priors( profiles = profiles, price = -0.25, type = c("Gala" = 0.5, "Honeycrisp" = 1.0), # "Fuji" is reference freshness = c("Average" = 0.6, "Excellent" = 1.2) # "Poor" is reference ) # Example 3: Random parameters - normal distributions for "price" and "freshness" priors_random <- cbc_priors( profiles = profiles, price = rand_spec( dist = "n", mean = -0.25, sd = 0.1 ), type = c(0.5, 1.0), freshness = rand_spec( dist = "n", mean = c(0.6, 1.2), sd = c(0.1, 0.1) ) ) # Example 4: Correlated random parameters priors_correlated <- cbc_priors( profiles = profiles, price = rand_spec( dist = "n", mean = -0.1, sd = 0.05, correlations = list( cor_spec( with = "type", with_level = "Honeycrisp", value = 0.3 ) ) ), type = rand_spec( dist = "n", mean = c("Gala" = 0.1, "Honeycrisp" = 0.2), sd = c("Gala" = 0.05, "Honeycrisp" = 0.1) ), freshness = c(0.1, 0.2) ) # Example 5: With interaction terms priors_interactions <- cbc_priors( profiles = profiles, price = -0.25, type = c("Fuji" = 0.5, "Honeycrisp" = 1.0), freshness = c("Average" = 0.6, "Excellent" = 1.2), interactions = list( # Price sensitivity varies by apple type int_spec( between = c("price", "type"), with_level = "Fuji", value = 0.1 ), int_spec( between = c("price", "type"), with_level = "Honeycrisp", value = 0.2 ), # Type preferences vary by freshness int_spec( between = c("type", "freshness"), level = "Honeycrisp", with_level = "Excellent", value = 0.3 ) ) ) # Example 6: Including no-choice option priors_nochoice_fixed <- cbc_priors( profiles = profiles, price = -0.25, type = c(0.5, 1.0), freshness = c(0.6, 1.2), no_choice = -0.5 # Negative values make no-choice less attractive ) # Example 7: Random no-choice priors_nochoice_random <- cbc_priors( profiles = profiles, price = -0.25, type = c(0.5, 1.0), freshness = c(0.6, 1.2), no_choice = rand_spec(dist = "n", mean = -0.5, sd = 0.2) ) # View the priors priors_fixed priors_random
This function creates a data frame of of all possible combinations of attribute levels.
cbc_profiles(...)cbc_profiles(...)
... |
Any number of named vectors defining each attribute and their levels,
e.g. |
A data frame of all possible combinations of attribute levels with
class cbc_profiles.
library(cbcTools) # Generate all profiles for a simple conjoint experiment about apples profiles <- cbc_profiles( price = c(1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5), type = c("Fuji", "Gala", "Honeycrisp"), freshness = c('Poor', 'Average', 'Excellent') )library(cbcTools) # Generate all profiles for a simple conjoint experiment about apples profiles <- cbc_profiles( price = c(1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5), type = c("Fuji", "Gala", "Honeycrisp"), freshness = c('Poor', 'Average', 'Excellent') )
This function returns a restricted set of profiles as a data frame.
cbc_restrict(profiles, ...)cbc_restrict(profiles, ...)
profiles |
A data frame of class |
... |
Any number of restricted pairs of attribute levels, defined as
pairs of logical expressions separated by commas. For example, the
restriction |
A restricted set of profiles as a data frame with class cbc_profiles.
library(cbcTools) # Generate all profiles for a simple conjoint experiment about apples profiles <- cbc_profiles( price = c(1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5), type = c("Fuji", "Gala", "Honeycrisp"), freshness = c('Poor', 'Average', 'Excellent') ) # Obtain a restricted subset of profiles based on pairs of logical # expressions. The example below contains the following restrictions: # - `"Gala"` apples will not be shown with the prices `1.5`, `2.5`, & `3.5`. # - `"Honeycrisp"` apples will not be shown with prices less than `2`. # - `"Honeycrisp"` apples will not be shown with the `"Poor"` freshness. # - `"Fuji"` apples will not be shown with the `"Excellent"` freshness. profiles_restricted <- cbc_restrict( profiles, type == "Gala" & price %in% c(1.5, 2.5, 3.5), type == "Honeycrisp" & price > 2, type == "Honeycrisp" & freshness == "Poor", type == "Fuji" & freshness == "Excellent" )library(cbcTools) # Generate all profiles for a simple conjoint experiment about apples profiles <- cbc_profiles( price = c(1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5), type = c("Fuji", "Gala", "Honeycrisp"), freshness = c('Poor', 'Average', 'Excellent') ) # Obtain a restricted subset of profiles based on pairs of logical # expressions. The example below contains the following restrictions: # - `"Gala"` apples will not be shown with the prices `1.5`, `2.5`, & `3.5`. # - `"Honeycrisp"` apples will not be shown with prices less than `2`. # - `"Honeycrisp"` apples will not be shown with the `"Poor"` freshness. # - `"Fuji"` apples will not be shown with the `"Excellent"` freshness. profiles_restricted <- cbc_restrict( profiles, type == "Gala" & price %in% c(1.5, 2.5, 3.5), type == "Honeycrisp" & price > 2, type == "Honeycrisp" & freshness == "Poor", type == "Fuji" & freshness == "Excellent" )
Provides automated suggestions for prior specifications based on attribute scales and desired effect sizes. This function analyzes your profile attributes and generates starting values for priors that can be refined based on domain knowledge.
cbc_suggest_priors( profiles, effect_size = c("moderate", "small", "large"), categorical_effect = NULL, direction = NULL )cbc_suggest_priors( profiles, effect_size = c("moderate", "small", "large"), categorical_effect = NULL, direction = NULL )
profiles |
A data frame of profiles created by |
effect_size |
Character. Desired effect size: |
categorical_effect |
Numeric. Effect size increment for categorical
levels. Defaults to |
direction |
Named list mapping attribute names to |
This function analyzes each attribute in your profiles and suggests prior parameter values scaled to produce the desired effect size. For continuous attributes, coefficients are scaled so that the full attribute range produces a utility contribution matching the target effect size. For categorical attributes, levels are assigned evenly spaced coefficients with the first level as the reference.
These suggestions are starting points that should be refined based on:
Domain knowledge about attribute importance
Previous research or pilot studies
Expected relative importance between attributes
Sign considerations (e.g., negative coefficients for cost)
The function prints a formatted output with:
Copy-paste ready code for cbc_priors()
Explanation of suggested values
Expected utility ranges
Notes and recommendations
Invisibly returns a named list of suggested prior values. The function primarily prints formatted output to the console.
library(cbcTools) # Create example profiles profiles <- cbc_profiles( price = c(1, 1.5, 2, 2.5, 3), type = c('Fuji', 'Gala', 'Honeycrisp'), freshness = c('Poor', 'Average', 'Excellent') ) # Get moderate effect size suggestions (default) cbc_suggest_priors(profiles) # Get small effect size suggestions cbc_suggest_priors(profiles, effect_size = "small") # Get large effect size suggestions cbc_suggest_priors(profiles, effect_size = "large") # Specify direction for price (should be negative) suggestions <- cbc_suggest_priors( profiles, effect_size = "moderate", direction = list(price = "negative") ) # Use suggestions as a starting point # Then adjust based on domain knowledge priors <- cbc_priors( profiles, price = -0.5, # Adjusted from suggestion type = c("Gala" = 0.3, "Honeycrisp" = 0.8), freshness = c("Average" = 0.4, "Excellent" = 0.9) )library(cbcTools) # Create example profiles profiles <- cbc_profiles( price = c(1, 1.5, 2, 2.5, 3), type = c('Fuji', 'Gala', 'Honeycrisp'), freshness = c('Poor', 'Average', 'Excellent') ) # Get moderate effect size suggestions (default) cbc_suggest_priors(profiles) # Get small effect size suggestions cbc_suggest_priors(profiles, effect_size = "small") # Get large effect size suggestions cbc_suggest_priors(profiles, effect_size = "large") # Specify direction for price (should be negative) suggestions <- cbc_suggest_priors( profiles, effect_size = "moderate", direction = list(price = "negative") ) # Use suggestions as a starting point # Then adjust based on domain knowledge priors <- cbc_priors( profiles, price = -0.5, # Adjusted from suggestion type = c("Gala" = 0.3, "Honeycrisp" = 0.8), freshness = c("Average" = 0.4, "Excellent" = 0.9) )
Create a correlation specification for random parameters
cor_spec(with, value, level = NULL, with_level = NULL)cor_spec(with, value, level = NULL, with_level = NULL)
with |
Character. Name of attribute to correlate with |
value |
Numeric. Correlation value between -1 and 1 |
level |
Character. For categorical variables, specific level to correlate from |
with_level |
Character. For categorical variables, specific level to correlate with |
A correlation specification list
Create an interaction specification for fixed parameters
int_spec(between, value, level = NULL, with_level = NULL)int_spec(between, value, level = NULL, with_level = NULL)
between |
Character vector of length 2 specifying the two attributes to interact |
value |
Numeric. Interaction coefficient value |
level |
Character. For categorical variables, specific level of first attribute |
with_level |
Character. For categorical variables, specific level of second attribute |
An interaction specification list
# Continuous * continuous interaction int_spec(between = c("price", "weight"), value = 0.1) # Continuous * categorical interactions (must specify categorical level) int_spec(between = c("price", "type"), with_level = "Fuji", value = 0.15) int_spec(between = c("price", "type"), with_level = "Gala", value = 0.05) # Categorical * categorical interactions (must specify both levels) int_spec(between = c("type", "freshness"), level = "Fuji", with_level = "Poor", value = -0.2)# Continuous * continuous interaction int_spec(between = c("price", "weight"), value = 0.1) # Continuous * categorical interactions (must specify categorical level) int_spec(between = c("price", "type"), with_level = "Fuji", value = 0.15) int_spec(between = c("price", "type"), with_level = "Gala", value = 0.05) # Categorical * categorical interactions (must specify both levels) int_spec(between = c("type", "freshness"), level = "Fuji", with_level = "Poor", value = -0.2)
Compare power across multiple designs
plot_compare_power(..., type = "power", power_threshold = 0.8)plot_compare_power(..., type = "power", power_threshold = 0.8)
... |
Named cbc_power objects to compare |
type |
Type of plot: "power" for power curves or "se" for standard error curves |
power_threshold |
Power threshold for horizontal reference line (only for power plots). Defaults to 0.8 |
A ggplot object comparing power curves
Plot method for cbc_power objects
## S3 method for class 'cbc_power' plot(x, type = "power", power_threshold = 0.8, ...)## S3 method for class 'cbc_power' plot(x, type = "power", power_threshold = 0.8, ...)
x |
A cbc_power object |
type |
Type of plot: "power" for power curves or "se" for standard error curves |
power_threshold |
Power threshold for horizontal reference line (only for power plots). Defaults to 0.8 |
... |
Additional arguments passed to ggplot |
Returns a ggplot2 object (class: "gg", "ggplot") that can be further customized, saved, or displayed. The plot visualizes either statistical power curves or standard error curves across different sample sizes for each parameter in the power analysis, with appropriate axis labels, legends, and reference lines.
Print method for cbc_choices objects
## S3 method for class 'cbc_choices' print(x, ...)## S3 method for class 'cbc_choices' print(x, ...)
x |
A cbc_choices object |
... |
Additional arguments passed to print |
Returns the input cbc_choices object invisibly (class: c("cbc_choices", "data.frame")). This function is called for its side effect of printing a formatted summary of the CBC choice data to the console, including choice task structure, simulation details, choice rates by alternative, and a preview of the choice data.
Print method for cbc_comparison objects
## S3 method for class 'cbc_comparison' print(x, ...)## S3 method for class 'cbc_comparison' print(x, ...)
x |
A cbc_comparison object |
... |
Additional arguments passed to print |
Returns the input cbc_comparison object invisibly (class: c("cbc_comparison", "list")). This function is called for its side effect of printing a formatted comparison table of multiple CBC designs to the console, including design metrics, performance rankings, and interpretation guidelines.
Concise print method for cbc_design objects
## S3 method for class 'cbc_design' print(x, ...)## S3 method for class 'cbc_design' print(x, ...)
x |
A cbc_design object |
... |
Additional arguments passed to print |
Returns the input cbc_design object invisibly (class: c("cbc_design", "data.frame")). This function is called for its side effect of printing a concise summary of the CBC design to the console, including design method, structure, D-error metrics, profile usage, and a preview of the design data.
Print method for cbc_inspection objects
## S3 method for class 'cbc_inspection' print(x, ...)## S3 method for class 'cbc_inspection' print(x, ...)
x |
A cbc_inspection object |
... |
Additional arguments passed to print |
Returns the input cbc_inspection object invisibly (class: c("cbc_inspection", "list")). This function is called for its side effect of printing a comprehensive inspection report of the CBC design to the console, including sections on design structure, efficiency metrics, attribute balance, overlap analysis, and variable encoding.
Print method for cbc_power objects
## S3 method for class 'cbc_power' print(x, ...)## S3 method for class 'cbc_power' print(x, ...)
x |
A cbc_power object |
... |
Additional arguments passed to print |
Returns the input cbc_power object invisibly (class: c("cbc_power", "list")). This function is called for its side effect of printing a formatted summary of the CBC power analysis results to the console, including sample size ranges, significance levels, parameter summaries, and power estimates across different sample sizes.
Print method for cbc_priors objects
## S3 method for class 'cbc_priors' print(x, ...)## S3 method for class 'cbc_priors' print(x, ...)
x |
A cbc_priors object |
... |
Additional arguments passed to print |
Returns the input cbc_priors object invisibly (class: c("cbc_priors", "list")). This function is called for its side effect of printing a formatted summary of the CBC priors specifications to the console, including parameter types, distributions, means, standard deviations, and any correlation structures.
Print method for cbc_profiles objects
## S3 method for class 'cbc_profiles' print(x, ...)## S3 method for class 'cbc_profiles' print(x, ...)
x |
A cbc_profiles object |
... |
Additional arguments passed to print |
Returns the input cbc_profiles object invisibly (class: c("cbc_profiles", "data.frame")). This function is called for its side effect of printing a formatted summary of the CBC profiles object to the console, including attribute information, profile counts, any applied restrictions, and a preview of the data.
Create a random parameter specification
rand_spec(dist = "n", mean, sd, correlations = NULL)rand_spec(dist = "n", mean, sd, correlations = NULL)
dist |
Character. Distribution type: "n" for normal, "ln" for log-normal, or "cn" for censored normal |
mean |
Numeric. Mean parameter value(s) |
sd |
Numeric. Standard deviation parameter value(s) |
correlations |
List of correlation specifications created by cor_spec() |
A random parameter specification list
Summary method for cbc_power objects
## S3 method for class 'cbc_power' summary(object, power_threshold = 0.8, ...)## S3 method for class 'cbc_power' summary(object, power_threshold = 0.8, ...)
object |
A cbc_power object |
power_threshold |
Minimum power threshold to report sample size requirements |
... |
Additional arguments |
Returns the input cbc_power object invisibly (class: c("cbc_power", "list")). This function is called for its side effect of printing a detailed summary to the console showing sample size requirements for achieving specified power thresholds for each parameter, including exact power levels and standard errors at the required sample sizes.