jhelvy / cbcTools

An R package with tools for designing choice based conjoint (cbc) survey experiments and conducting power analyses
https://jhelvy.github.io/cbcTools/
Other
5 stars 5 forks source link

cbc_design includes restricted profiles as NA when method = "orthogonal" #21

Closed mmardehali closed 12 months ago

mmardehali commented 1 year ago

This issue was previously fixed for Bayesian designs using cbc_design, however, if the method is changed to "orthogonal", restricted profiles still show up in the final orthogonal design, with NA as profileID (see lines 24, 31, and 36 of the results below). Also, running the following code issues a lot of the same warnings when creating orthogonal design. Details below:

Code:

library(cbcTools)
library(logitr)

Nresp = 20
Nchoice = 16 
Nalt = 4
HeadN <- Nalt*Nchoice

profiles <- cbc_profiles(
  cost = seq(20, 30, 5), #generates sequence of numbers between 20 and 30 inclusive, 5 by 5. --Ratio Data
  brand = c("O", "HH"), #--Nominal Data
  usrrt = seq(30, 20, -5), #generates sequence of numbers between 4.8 and 3.2 inclusive, -0.8 by -0.8, to have the highest rating first so the top generated profile is the best. --Ratio Data
  accinf = c("H", "M", "L", "U") #--Ordinal Data
)

rstrct_profiles <- cbc_restrict(
  profiles,
  cost == 20 & brand == "O" & usrrt == 30 & accinf == "H", #exclude dominant alternative with the best levels for each attribute
  cost == 30 & brand == "HH" & usrrt == 20 & accinf == "U" #exclude the worst alternative with the worst levels for each attribute
)

design_ortho <- cbc_design(
  profiles = rstrct_profiles,
  n_resp = Nresp,
  n_alts = Nalt,
  n_q = Nchoice,
  method = "orthogonal"
)

DF_design_ortho <- as.data.frame(design_ortho)
FirstOrtho <- head(DF_design_ortho, HeadN)
FirstOrtho

Results:

Orthogonal array found; using 72 out of 70 profiles for design
There were 50 or more warnings (use warnings() to see the first 50)
   profileID respID qID altID obsID cost brand usrrt accinf
1         12      1   1     1     1   20     O    20      H
2         47      1   1     2     1   30    HH    25      L
3         63      1   1     3     1   20    HH    25      U
4         25      1   1     4     1   25     O    25      M
5          8      1   2     1     2   30     O    25      H
6         45      1   2     2     2   20    HH    25      L
7         27      1   2     3     2   20    HH    25      M
8         26      1   2     4     2   30     O    25      M
9         41      1   3     1     3   30    HH    30      L
10        40      1   3     2     3   25    HH    30      L
11        46      1   3     3     3   25    HH    25      L
12        20      1   3     4     3   30     O    30      M
13        19      1   4     1     4   25     O    30      M
14        51      1   4     2     4   20    HH    20      L
15         8      1   4     3     4   30     O    25      H
16         2      1   4     4     4   30     O    30      H
17        32      1   5     1     5   30     O    20      M
18         3      1   5     2     5   20    HH    30      H
19        50      1   5     3     5   30     O    20      L
20        63      1   5     4     5   20    HH    25      U
21        50      1   6     1     6   30     O    20      L
22        45      1   6     2     6   20    HH    25      L
23        30      1   6     3     6   20     O    20      M
24        NA      1   6     4     6   30    HH    20      U
25        37      1   7     1     7   25     O    30      L
26        29      1   7     2     7   30    HH    25      M
27        59      1   7     3     7   30    HH    30      U
28        62      1   7     4     7   30     O    25      U
29        40      1   8     1     8   25    HH    30      L
30        51      1   8     2     8   20    HH    20      L
31        NA      1   8     3     8   30    HH    20      U
32        39      1   8     4     8   20    HH    30      L
33        34      1   9     1     9   25    HH    20      M
34        39      1   9     2     9   20    HH    30      L
35        36      1   9     3     9   20     O    30      L
36        NA      1   9     4     9   30    HH    20      U
37        44      1  10     1    10   30     O    25      L
38        23      1  10     2    10   30    HH    30      M
39        63      1  10     3    10   20    HH    25      U
40        59      1  10     4    10   30    HH    30      U
41        41      1  11     1    11   30    HH    30      L
42        10      1  11     2    11   25    HH    25      H
43        59      1  11     3    11   30    HH    30      U
44        54      1  11     4    11   20     O    30      U
45        13      1  12     1    12   25     O    20      H
46         1      1  12     2    12   25     O    30      H
47        21      1  12     3    12   20    HH    30      M
48        67      1  12     4    12   25     O    20      U
49        31      1  13     1    13   25     O    20      M
50        43      1  13     2    13   25     O    25      L
51         5      1  13     3    13   30    HH    30      H
52        33      1  13     4    13   20    HH    20      M
53        12      1  14     1    14   20     O    20      H
54        22      1  14     2    14   25    HH    30      M
55        34      1  14     3    14   25    HH    20      M
56        28      1  14     4    14   25    HH    25      M
57        59      1  15     1    15   30    HH    30      U
58        40      1  15     2    15   25    HH    30      L
59        41      1  15     3    15   30    HH    30      L
60        47      1  15     4    15   30    HH    25      L
61        26      1  16     1    16   30     O    25      M
62        62      1  16     2    16   30     O    25      U
63        50      1  16     3    16   30     O    20      L
64        35      1  16     4    16   30    HH    20      M

Expanding warnings:

> warnings()
Warning messages:
1: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 8)
2: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 2)
3: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 12)
4: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 9)
5: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 13)
6: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 16)
7: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 1)
8: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 9)
9: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 4)
10: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 14)
11: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 1)
12: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 16)
13: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 7)
14: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 8)
15: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 6)
16: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 2)
17: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 12)
18: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 6)
19: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 13)
20: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 16)
21: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 1)
22: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 9)
23: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 13)
24: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 14)
25: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 1)
26: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 16)
27: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 7)
28: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 8)
29: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 6)
30: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 2)
31: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 12)
32: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 6)
33: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 13)
34: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 16)
35: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 1)
36: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 9)
37: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 13)
38: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 14)
39: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 1)
40: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 16)
41: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 7)
42: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 8)
43: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 6)
44: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 2)
45: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 12)
46: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 6)
47: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 13)
48: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 16)
49: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 1)
50: In (function (..., deparse.level = 1)  ... :
  number of columns of result is not a multiple of vector length (arg 9)
jhelvy commented 1 year ago

Oops, yup this is a problem. Actually, you really shouldn't attempt an orthogonal design with restricted profiles as by eliminating prohibited rows from the design you are pretty much by definition not going to get an orthogonal design. I'll look into whether the {DoE.base} package can take a restricted set of profiles - that's the package I'm using under the hood for orthogonal design. I'm 99% sure it's "no", but I want to confirm. My instinct is to simply not allow this by adding a stop() if someone is using a restricted profile set with the orthogonal method.

jhelvy commented 12 months ago

This was fixed in v0.5.0