Skip to contents

🎯 Estimate Corrected MMs or AMCEs

In conjoint analysis, default MMs and AMCEs can be biased due to measurement error from intra-respondent variability.

projoint corrects for this bias automatically.


📦 Prepare Example Data

outcomes <- paste0("choice", 1:8)
outcomes <- c(outcomes, "choice1_repeated_flipped")
out1 <- reshape_projoint(exampleData1, outcomes)

🛠️ Why Use IDs (e.g., att1, level1)?

Before estimating quantities, it’s important to understand how attribute and level IDs work inside projoint.

We recommend working with attribute IDs rather than actual text labels because:

  • Safer against special characters, languages, or typos
  • Allows multiple attributes to have identical labels (e.g., “High” for both “Teaching Quality” and “Research Quality”)

Check attribute-level mappings:

out1$labels
## # A tibble: 24 × 4
##    attribute                level                        attribute_id level_id  
##    <chr>                    <chr>                        <chr>        <chr>     
##  1 Housing Cost             15% of pre-tax income        att1         att1:leve…
##  2 Housing Cost             30% of pre-tax income        att1         att1:leve…
##  3 Housing Cost             40% of pre-tax income        att1         att1:leve…
##  4 Presidential Vote (2020) 30% Democrat, 70% Republican att2         att2:leve…
##  5 Presidential Vote (2020) 50% Democrat, 50% Republican att2         att2:leve…
##  6 Presidential Vote (2020) 70% Democrat, 30% Republican att2         att2:leve…
##  7 Racial Composition       50% White, 50% Nonwhite      att3         att3:leve…
##  8 Racial Composition       75% White, 25% Nonwhite      att3         att3:leve…
##  9 Racial Composition       90% White, 10% Nonwhite      att3         att3:leve…
## 10 Racial Composition       96% White, 4% Nonwhite       att3         att3:leve…
## # ℹ 14 more rows

You can also save these labels for easier editing:

save_labels(out1, "labels.csv")

📈 Estimate Marginal Means (MMs)

Choice-Level MMs (Specific Level)
qoi_2 <- set_qoi(
  .structure = "choice_level",
  .att_choose = "att1",
  .lev_choose = "level3",
  .att_notchoose = "att1",
  .lev_notchoose = "level1"
)

mm2 <- projoint(out1, .qoi = qoi_2, .ignore_position = FALSE)
print(mm2)
## 
## Projoint results object
## -------------------------
## Estimand:  mm 
## Structure:  choice_level 
## Standard error method:  analytical 
## IRR:  Estimated 
## Tau:  0.172 
## Number of estimates:  2
summary(mm2)
## 
## Summary of Projoint Estimates
## ------------------------------
## Estimand:  mm 
## Structure:  choice_level 
## Standard error method:  analytical 
## IRR:  Estimated 
## Tau:  0.172
## # A tibble: 2 × 7
##   estimand       estimate     se conf.low conf.high att_level_choose
##   <chr>             <dbl>  <dbl>    <dbl>     <dbl> <chr>           
## 1 mm_uncorrected    0.402 0.0258    0.352     0.453 att1:level3     
## 2 mm_corrected      0.351 0.0408    0.271     0.431 att1:level3     
## # ℹ 1 more variable: att_level_notchoose <chr>
Profile-Level MMs (All Levels)
mm0 <- projoint(out1, .structure = "profile_level", .estimand = "mm")
print(mm0)
## 
## Projoint results object
## -------------------------
## Estimand:  mm 
## Structure:  profile_level 
## Standard error method:  analytical 
## IRR:  Estimated 
## Tau:  0.172 
## Number of estimates:  48
summary(mm0)
## 
## Summary of Projoint Estimates
## ------------------------------
## Estimand:  mm 
## Structure:  profile_level 
## Standard error method:  analytical 
## IRR:  Estimated 
## Tau:  0.172
## # A tibble: 48 × 6
##    estimand       estimate     se conf.low conf.high att_level_choose
##    <chr>             <dbl>  <dbl>    <dbl>     <dbl> <chr>           
##  1 mm_uncorrected    0.574 0.0134    0.548     0.601 att1:level1     
##  2 mm_corrected      0.614 0.0207    0.573     0.654 att1:level1     
##  3 mm_uncorrected    0.485 0.0134    0.458     0.511 att1:level2     
##  4 mm_corrected      0.477 0.0204    0.437     0.517 att1:level2     
##  5 mm_uncorrected    0.445 0.0131    0.419     0.470 att1:level3     
##  6 mm_corrected      0.416 0.0203    0.376     0.455 att1:level3     
##  7 mm_uncorrected    0.489 0.0133    0.463     0.515 att2:level1     
##  8 mm_corrected      0.483 0.0202    0.443     0.522 att2:level1     
##  9 mm_uncorrected    0.524 0.0130    0.498     0.549 att2:level2     
## 10 mm_corrected      0.536 0.0200    0.497     0.575 att2:level2     
## # ℹ 38 more rows
Profile-Level MMs (Specific Level)
qoi_1 <- set_qoi(
  .structure = "profile_level",
  .estimand = "mm",
  .att_choose = "att1",
  .lev_choose = "level1"
)

mm1 <- projoint(out1, .qoi = qoi_1)
print(mm1)
## 
## Projoint results object
## -------------------------
## Estimand:  mm 
## Structure:  profile_level 
## Standard error method:  analytical 
## IRR:  Estimated 
## Tau:  0.172 
## Number of estimates:  2
summary(mm1)
## 
## Summary of Projoint Estimates
## ------------------------------
## Estimand:  mm 
## Structure:  profile_level 
## Standard error method:  analytical 
## IRR:  Estimated 
## Tau:  0.172
## # A tibble: 2 × 7
##   estimand       estimate     se conf.low conf.high att_level_choose
##   <chr>             <dbl>  <dbl>    <dbl>     <dbl> <chr>           
## 1 mm_uncorrected    0.574 0.0134    0.548     0.601 att1:level1     
## 2 mm_corrected      0.614 0.0207    0.573     0.654 att1:level1     
## # ℹ 1 more variable: att_level_notchoose <chr>
Profile-Level MMs (Specific Level, Manual IRR)
mm1b <- projoint(out1, .qoi = qoi_1, .irr = 0.75)
print(mm1b)
## 
## Projoint results object
## -------------------------
## Estimand:  mm 
## Structure:  profile_level 
## Standard error method:  analytical 
## IRR:  Assumed (0.75) 
## Tau:  0.146 
## Number of estimates:  2
summary(mm1b)
## 
## Summary of Projoint Estimates
## ------------------------------
## Estimand:  mm 
## Structure:  profile_level 
## Standard error method:  analytical 
## IRR:  Assumed (0.75) 
## Tau:  0.146
## # A tibble: 2 × 7
##   estimand       estimate     se conf.low conf.high att_level_choose
##   <chr>             <dbl>  <dbl>    <dbl>     <dbl> <chr>           
## 1 mm_uncorrected    0.574 0.0134    0.548     0.601 att1:level1     
## 2 mm_corrected      0.605 0.0190    0.568     0.643 att1:level1     
## # ℹ 1 more variable: att_level_notchoose <chr>

📉 Estimate AMCEs

Choice-Level AMCEs (Specific Level)
qoi_4 <- set_qoi(
  .structure = "choice_level",
  .estimand = "amce",
  .att_choose = "att1",
  .lev_choose = "level3",
  .att_notchoose = "att1",
  .lev_notchoose = "level1",
  .att_choose_b = "att1",
  .lev_choose_b = "level2",
  .att_notchoose_b = "att1",
  .lev_notchoose_b = "level1"
)

amce2 <- projoint(out1, .qoi = qoi_4, .ignore_position = TRUE)
print(amce2)
## 
## Projoint results object
## -------------------------
## Estimand:  amce 
## Structure:  choice_level 
## Standard error method:  analytical 
## IRR:  Estimated 
## Tau:  0.172 
## Number of estimates:  2
summary(amce2)
## 
## Summary of Projoint Estimates
## ------------------------------
## Estimand:  amce 
## Structure:  choice_level 
## Standard error method:  analytical 
## IRR:  Estimated 
## Tau:  0.172
## # A tibble: 2 × 9
##   estimand         estimate     se conf.low conf.high att_level_choose
##   <chr>               <dbl>  <dbl>    <dbl>     <dbl> <chr>           
## 1 amce_uncorrected  -0.0484 0.0270   -0.101   0.00448 att1:level3     
## 2 amce_corrected    -0.0739 0.0414   -0.155   0.00727 att1:level3     
## # ℹ 3 more variables: att_level_notchoose <chr>,
## #   att_level_choose_baseline <chr>, att_level_notchoose_baseline <chr>
Profile-Level AMCEs (All Levels)
amce0 <- projoint(out1, .structure = "profile_level", .estimand = "amce")
print(amce0)
## 
## Projoint results object
## -------------------------
## Estimand:  amce 
## Structure:  profile_level 
## Standard error method:  analytical 
## IRR:  Estimated 
## Tau:  0.172 
## Number of estimates:  34
summary(amce0)
## 
## Summary of Projoint Estimates
## ------------------------------
## Estimand:  amce 
## Structure:  profile_level 
## Standard error method:  analytical 
## IRR:  Estimated 
## Tau:  0.172
## # A tibble: 34 × 7
##    estimand         estimate     se conf.low conf.high att_level_choose
##    <chr>               <dbl>  <dbl>    <dbl>     <dbl> <chr>           
##  1 amce_uncorrected -0.0899  0.0190 -0.127     -0.0527 att1:level2     
##  2 amce_corrected   -0.137   0.0290 -0.194     -0.0801 att1:level2     
##  3 amce_uncorrected -0.130   0.0188 -0.167     -0.0931 att1:level3     
##  4 amce_corrected   -0.198   0.0294 -0.256     -0.140  att1:level3     
##  5 amce_uncorrected  0.0348  0.0186 -0.00170    0.0713 att2:level2     
##  6 amce_corrected    0.0530  0.0284 -0.00258    0.109  att2:level2     
##  7 amce_uncorrected -0.00177 0.0188 -0.0386     0.0350 att2:level3     
##  8 amce_corrected   -0.00270 0.0286 -0.0589     0.0535 att2:level3     
##  9 amce_uncorrected  0.0240  0.0204 -0.0159     0.0640 att3:level2     
## 10 amce_corrected    0.0366  0.0312 -0.0246     0.0979 att3:level2     
## # ℹ 24 more rows
## # ℹ 1 more variable: att_level_choose_baseline <chr>
Profile-Level AMCEs (Specific Level)
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)
## 
## Projoint results object
## -------------------------
## Estimand:  amce 
## Structure:  profile_level 
## Standard error method:  analytical 
## IRR:  Estimated 
## Tau:  0.172 
## Number of estimates:  2
summary(amce1)
## 
## Summary of Projoint Estimates
## ------------------------------
## Estimand:  amce 
## Structure:  profile_level 
## Standard error method:  analytical 
## IRR:  Estimated 
## Tau:  0.172
## # A tibble: 2 × 9
##   estimand         estimate     se conf.low conf.high att_level_choose
##   <chr>               <dbl>  <dbl>    <dbl>     <dbl> <chr>           
## 1 amce_uncorrected   -0.130 0.0188   -0.167   -0.0931 att1:level3     
## 2 amce_corrected     -0.198 0.0294   -0.256   -0.140  att1:level3     
## # ℹ 3 more variables: att_level_notchoose <chr>,
## #   att_level_choose_baseline <chr>, att_level_notchoose_baseline <chr>
Profile-Level AMCEs (Specific Level, Manual IRR)
amce1b <- projoint(out1, .qoi = qoi_3, .irr = 0.75)
print(amce1b)
## 
## Projoint results object
## -------------------------
## Estimand:  amce 
## Structure:  profile_level 
## Standard error method:  analytical 
## IRR:  Assumed (0.75) 
## Tau:  0.146 
## Number of estimates:  2
summary(amce1b)
## 
## Summary of Projoint Estimates
## ------------------------------
## Estimand:  amce 
## Structure:  profile_level 
## Standard error method:  analytical 
## IRR:  Assumed (0.75) 
## Tau:  0.146
## # A tibble: 2 × 9
##   estimand         estimate     se conf.low conf.high att_level_choose
##   <chr>               <dbl>  <dbl>    <dbl>     <dbl> <chr>           
## 1 amce_uncorrected   -0.130 0.0188   -0.167   -0.0931 att1:level3     
## 2 amce_corrected     -0.184 0.0266   -0.236   -0.132  att1:level3     
## # ℹ 3 more variables: att_level_notchoose <chr>,
## #   att_level_choose_baseline <chr>, att_level_notchoose_baseline <chr>

🔎 Predict Intra-Respondent Reliability (IRR)

If your design does not include a repeated task, you can predict IRR using predict_tau(), based on observed respondent behavior.

Predict IRR Using predict_tau()
data(out1_arranged)
predicted_irr <- predict_tau(out1_arranged)

print(predicted_irr)
## Tau estimated using the extrapolation method: 0.743
summary(predicted_irr)
## # A tibble: 8 × 2
##       x predicted
##   <int>     <dbl>
## 1     0     0.743
## 2     1     0.709
## 3     2     0.675
## 4     3     0.640
## 5     4     0.606
## 6     5     0.572
## 7     6     0.537
## 8     7     0.503
plot(predicted_irr)


💡 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.


🌟 What’s Next?

Now that you have estimated key quantities, you’re ready to visualize your results clearly and effectively!

➡️ Continue to: Visualize Your Results
⬅️ Back to: Wrangle Your Data
🏠 Home: Home