Resources

Discrete Choice 3

 /****************************************************************/
 /*          S A S   S A M P L E   L I B R A R Y                 */
 /*                                                              */
 /*    NAME: MR2010F                                             */
 /*   TITLE: Discrete Choice 3                                   */
 /* PRODUCT: STAT                                                */
 /*  SYSTEM: ALL                                                 */
 /*    KEYS: marketing research                                  */
 /*   PROCS: PHREG, TRANSREG, OPTEX, FACTEX, PLAN, IML           */
 /*    DATA:                                                     */
 /*                                                              */
 /* SUPPORT: saswfk                      UPDATE:  01Oct2010      */
 /*     REF: MR-2010F Discrete Choice                            */
 /*    MISC: This file contains SAS code for the "Discrete       */
 /*          Choice" report, the 01Oct2010 edition, for SAS 9.2. */
 /*                                                              */
 /*          You must install the following macros from          */
 /* http://support.sas.com/techsup/tnote/tnote_stat.html#market  */
 /*                                                              */
 /*          ChoicEff Efficient Choice Designs                   */
 /*          MktAllo  Process a Choice Allocation Study Data Set */
 /*          MktBal   Balanced Experimental Design               */
 /*          MktBIBD  Balanced Incomplete Block Design           */
 /*          MktBlock Block an Experimental Design               */
 /*          MktBSize Balanced Incomplete Block Design Sizes     */
 /*          MktDes   Efficient Experimental Designs             */
 /*          MktDups  Eliminate Duplicate Runs or Choice Sets    */
 /*          MktEval  Evaluate an Experimental Design            */
 /*          MktEx    Efficient Experimental Designs             */
 /*          MktKey   Aid Making the MktRoll KEY= Data Set       */
 /*          MktLab   Change Names, Levels in a Design           */
 /*          MktMDiff MaxDiff (Best-Worst) Choice Modeling       */
 /*          MktMerge Merge a Choice Design with Choice Data     */
 /*          MktOrth  List Orthogonal Designs MktEx Can Make     */
 /*          MktPPro  Optimal Partial Profile Designs            */
 /*          MktRoll  Roll Out a Design Into a Choice Design     */
 /*          MktRuns  Experimental Design Sizes                  */
 /*          PhChoice Customize PROC PHREG for Choice Models     */
 /*                                                              */
 /****************************************************************/

************* Begin PHREG Output Customization **************;
options ls=80 ps=60 nonumber nodate;

%phchoice(on)

**************** Begin Vacation Example Code ****************;

title 'Vacation Example';

%mktruns(3 ** 15)

%mktorth(range=n=36)

proc sort data=mktdeslev out=list(drop=x:);
   by descending x3;
   where x3;
   run;

proc print; run;

%let m   = 6;                    /* m alts including constant        */
%let mm1 = %eval(&m - 1);        /* m - 1                            */
%let n   = 18;                   /* number of choice sets per person */
%let blocks = 2;                 /* number of blocks                 */

%mktex(3 ** 15 2, n=&n * &blocks, seed=151)

* Due to machine differences, you might not get the same design if you run
* the step above, so here is the design that is used in the book;
data randomized; input x1-x16 @@; datalines;
1 1 3 3 1 3 3 1 2 1 2 1 3 3 3 2 3 1 3 2 2 3 3 2 1 2 1 2 2 2 2 2 3 3 1 2
1 2 1 1 1 1 2 2 3 1 1 2 1 3 3 1 1 1 1 2 2 2 3 2 1 3 1 1 3 2 3 1 1 1 3 3
1 3 2 3 1 2 2 2 1 2 1 2 3 1 3 1 1 2 3 1 2 2 3 1 2 3 3 3 2 3 1 3 3 3 2 2
2 2 3 1 3 3 2 3 1 3 2 3 1 2 3 1 3 2 1 1 3 2 1 3 3 3 1 2 2 2 2 3 1 1 3 1
3 1 3 2 3 2 1 3 2 3 3 1 2 3 1 2 1 2 2 3 2 1 2 2 1 1 2 2 2 3 1 2 2 1 2 2
3 3 2 1 1 3 2 3 1 3 1 1 1 1 1 1 3 2 3 2 3 3 2 2 3 2 1 1 2 2 3 2 1 2 2 2
3 2 2 1 3 3 2 1 2 1 1 3 1 1 1 2 1 3 1 1 1 1 3 2 3 2 3 1 3 3 2 1 3 1 3 2
1 1 3 2 3 1 2 1 2 1 1 1 3 2 2 1 2 1 2 1 2 3 1 1 3 1 2 3 2 1 2 1 2 2 2 2
3 3 2 3 3 1 3 1 2 3 1 2 3 3 2 1 1 3 2 2 3 3 1 2 3 1 1 1 1 2 2 2 3 2 1 3
2 2 3 3 3 1 1 1 1 3 1 1 2 2 2 1 3 2 1 3 1 2 1 2 3 3 3 2 2 2 3 2 2 1 1 1
2 1 1 3 3 2 1 1 2 3 1 1 1 3 3 1 3 2 1 3 2 3 1 2 2 2 2 1 2 3 3 2 2 3 3 1
3 1 1 2 1 2 2 3 1 2 1 1 3 3 3 3 2 2 2 2 1 1 3 3 3 1 2 3 3 2 1 3 3 1 1 2
3 3 1 2 2 1 2 2 3 3 3 3 3 3 3 2 3 1 2 1 1 2 2 2 2 1 1 3 2 2 3 1 1 3 3 1
2 2 2 1 1 3 1 1 1 1 3 1 1 2 1 2 1 3 2 3 2 3 1 2 2 1 2 1 1 3 2 2 2 2 3 3
2 2 2 3 1 1 3 2 2 1 2 2 1 1 3 3 3 1 3 2 1 1 3 1 2 1 1 3 2 2 2 1 2 2 3 2
1 2 2 2 1 1 1 1 2 3 1 3 1 1 3 3 3 3 2 1 2 3 3 3 3 2 3 2 1 1 3 3 2 1 2 1
;

data design; input x1-x16 @@; datalines;
1 1 1 1 1 1 1 1 1 1 1 1 1 2 3 1 1 1 1 1 2 2 3 3 2 2 3 3 1 1 2 1 1 1 2 2
1 1 2 2 3 3 3 3 1 2 3 2 1 1 2 2 3 3 3 3 1 1 2 2 1 3 1 2 1 2 1 3 1 3 2 3
3 2 1 2 2 3 1 1 1 2 1 3 3 1 3 2 2 3 2 1 2 1 2 1 1 2 3 1 2 3 1 2 3 1 2 3
2 1 3 2 1 2 3 1 3 2 2 1 1 3 3 2 2 2 2 2 1 3 2 3 2 3 2 1 2 1 3 1 3 2 1 1
1 3 2 3 3 2 1 2 1 2 1 3 3 3 3 1 1 3 3 2 1 2 3 1 3 2 2 1 3 3 2 2 1 3 3 2
2 1 1 3 2 3 1 2 3 1 1 2 2 1 1 3 2 3 1 2 1 3 3 2 3 3 2 2 2 1 1 3 3 2 2 1
3 1 2 3 3 1 1 2 2 1 3 1 1 3 2 3 2 3 2 1 3 3 3 1 2 1 3 1 3 1 3 2 3 2 1 2
3 2 1 1 2 2 2 2 2 2 2 2 2 2 2 2 1 2 3 1 2 2 2 2 3 3 1 1 3 3 1 1 1 1 2 1
2 2 3 3 1 1 1 1 2 2 3 3 1 3 1 2 2 2 3 3 2 2 3 3 1 1 1 1 1 2 3 2 2 3 1 2
1 3 3 2 2 1 1 3 2 2 2 2 2 3 1 2 3 1 2 3 1 2 3 1 2 1 3 2 2 3 2 1 1 2 1 3
3 1 3 2 2 1 2 1 2 3 2 1 2 1 3 1 1 3 2 3 2 3 1 1 3 1 2 3 1 2 3 1 2 3 1 2
2 1 3 2 3 1 2 3 2 1 1 3 3 2 2 1 2 2 2 2 3 1 3 2 2 3 2 1 1 2 1 3 2 1 2 1
3 1 3 2 3 2 1 2 2 1 3 1 2 3 1 1 3 2 1 2 1 2 1 3 1 3 2 3 3 2 1 1 3 2 1 2
2 1 3 1 3 1 3 2 3 3 3 1 3 2 2 1 1 3 3 2 1 2 3 1 3 1 1 2 3 2 2 1 3 1 2 3
2 1 1 3 3 3 2 2 3 3 1 1 2 2 2 2 3 3 1 1 1 3 1 2 3 3 1 1 3 3 1 1 2 2 2 2
1 2 3 2 3 3 3 3 1 1 2 2 1 1 2 2 1 1 2 1 3 3 3 3 3 3 3 3 3 3 3 3 1 2 3 1
;

%mkteval(data=randomized)

%mktex(3 ** 15,                     /* all attrs of all alternatives        */
       n=&n * &blocks,              /* total number of choice sets          */
       init=randomized(drop=x16),   /* initial design                       */
       options=check,               /* check initial design efficiency      */
       examine=i v)                 /* show information & variance matrices */

%mktlab(data=randomized, vars=x1-x5 x11-x15 x6 x9 x7 x8 x10 Block,
        out=sasuser.VacationLinDesBlckd)

proc sort data=sasuser.VacationLinDesBlckd; by block; run;

%mkteval(blocks=block)

%mktkey(5 3 t)

title 'Vacation Example';

data key;
   input Place $ 1-10 (Lodge Scene Price) ($);
   datalines;
Hawaii      x1    x6     x11
Alaska      x2    x7     x12
Mexico      x3    x8     x13
California  x4    x9     x14
Maine       x5    x10    x15
Home        .     .      .
;

%mktroll(design=sasuser.VacationLinDesBlckd, key=key, alt=place,
         out=sasuser.VacationChDes)

proc print data=sasuser.VacationLinDesBlckd(obs=2);
   id Block;
   var x1-x15;
   run;

proc print data=sasuser.VacationChDes(obs=12);
   id set; by set;
   run;

proc format;
   value price 1 = ' 999'      2 = '1249'
               3 = '1499'      0 = '   0';
   value scene 1 = 'Mountains' 2 = 'Lake'
               3 = 'Beach'     0 = 'Home';
   value lodge 1 = 'Cabin'     2 = 'Bed & Breakfast'
               3 = 'Hotel'     0 = 'Home';
   run;

data sasuser.VacationChDes;
   set sasuser.VacationChDes;
   if place = 'Home' then do; lodge = 0; scene = 0; price = 0; end;
   price = input(put(price, price.), 5.);
   format scene scene. lodge lodge.;
   run;

proc print data=sasuser.VacationChDes(obs=12);
   id set; by set;
   run;

title2 'Evaluate the Choice Design';

%choiceff(data=sasuser.VacationChDes,/* candidate set of choice sets        */
          init=sasuser.VacationChDes(keep=set), /* select these sets        */
          intiter=0,                /* evaluate without internal iterations */
                                    /* alternative-specific effects model   */
                                    /* zero=none - use all levels of place  */
                                    /* order=data - do not sort levels      */
          model=class(place / zero=none order=data)
                                    /* place * price ... - interactions or  */
                                    /*    alternative-specific effects      */
                class(place * price place * scene place * lodge /
                      zero=none     /* zero=none - use all levels of place  */
                      order=formatted) / /* order=formatted - sort levels   */
                lprefix=0           /* lpr=0 labels created from just levels*/
                cprefix=0           /* cpr=0 names created from just levels */
                separators=' ' ', ',/* use comma sep to build interact terms*/

          nsets=36,                 /* number of choice sets                */
          nalts=6,                  /* number of alternatives               */
          beta=zero)                /* assumed beta vector, Ho: b=0         */

proc reg data=tmp_cand;
   model Alaska_1499 = Alaska Alaska_999 Alaska_1249 / noint;
   run; quit;

proc freq data=tmp_cand;
   tables Alaska_0;
   run;

title2 'Evaluate the Choice Design';
%choiceff(data=sasuser.VacationChDes,/* candidate set of choice sets        */
          init=sasuser.VacationChDes(keep=set), /* select these sets        */
          intiter=0,                /* evaluate without internal iterations */
                                    /* alternative-specific effects model   */
                                    /* ref level for place is 'Home'        */
                                    /* order=data - do not sort levels      */
          model=class(place / zero='Home' order=data)
                                    /* ref level for place is 'Home'        */
                                    /* ref level for price is 0             */
                                    /* ref level for scene is 'Home'        */
                                    /* ref level for lodge is 'Home'        */
                                    /* order=formatted - sort levels        */
                class(place * price place * scene place * lodge /
                      zero='Home' '0' 'Home' 'Home' order=formatted) /
                lprefix=0           /* lpr=0 labels created from just levels*/
                cprefix=0           /* cpr=0 names created from just levels */
                separators=' ' ', ',/* use comma sep to build interact terms*/
          nsets=36,                 /* number of choice sets                */
          nalts=6,                  /* number of alternatives               */
          beta=zero)                /* assumed beta vector, Ho: b=0         */

title2 'Evaluate the Choice Design';

%choiceff(data=sasuser.VacationChDes,/* candidate set of choice sets        */
          init=sasuser.VacationChDes(keep=set), /* select these sets        */
          intiter=0,                /* evaluate without internal iterations */
                                    /* alternative-specific effects model   */
                                    /* ref level for place is 'Home'        */
                                    /* order=data - do not sort levels      */
          model=class(place / zero='Home' order=data)
                                    /* ref level for place is 'Home'        */
                                    /* ref level for price is 0             */
                                    /* ref level for scene is 'Home'        */
                                    /* ref level for lodge is 'Home'        */
                                    /* order=formatted - sort levels        */
                class(place * price place * scene place * lodge /
                      zero='Home' '0' 'Home' 'Home' order=formatted) /
                lprefix=0           /* lpr=0 labels created from just levels*/
                cprefix=0           /* cpr=0 names created from just levels */
                separators=' ' ', ',/* use comma sep to build interact terms*/

          nsets=36,                 /* number of choice sets                */
          nalts=6,                  /* number of alternatives               */
                                    /* extra model terms to drop from model */
          drop=Alaska_1499 California_1499 Hawaii_1499 Maine_1499
               Mexico_1499 AlaskaMountains CaliforniaMountains
               HawaiiMountains MaineMountains MexicoMountains AlaskaHotel
               CaliforniaHotel HawaiiHotel MaineHotel MexicoHotel,
          beta=zero)                /* assumed beta vector, Ho: b=0         */

%mktdups(branded, data=sasuser.VacationChDes,
         nalts=6, factors=place price scene lodge)

ods listing close; /* suppress a LOT of output */

title;
proc sort data=sasuser.VacationLinDesBlckd; by block; run;

options ls=80 ps=60 nodate nonumber;

data _null_;
   array dests[&mm1] $ 10 _temporary_ ('Hawaii' 'Alaska' 'Mexico'
                                       'California' 'Maine');
   array prices[3]   $  5 _temporary_ ('$999' '$1249' '$1499');
   array scenes[3]   $ 13 _temporary_
                     ('the Mountains' 'a Lake' 'the Beach');
   array lodging[3]  $ 15 _temporary_
                     ('Cabin' 'Bed & Breakfast' 'Hotel');
   array x[15];
   file print linesleft=ll;

   set sasuser.VacationLinDesBlckd;
   by block;

   if first.block then do;
      choice = 0;
      put _page_;
      put @50 'Form: ' block  ' Subject: ________' //;
      end;
   choice + 1;

   if ll < 19 then put _page_;
   put choice 2. ') Circle your choice of '
       'vacation destinations:' /;
   do dest = 1 to &mm1;
      put '    ' dest 1. ') ' dests[dest]
          +(-1) ', staying in a ' lodging[x[dest]]
          'near ' scenes[x[&mm1 + dest]] +(-1) ',' /
          '       with a package cost of '
         prices[x[2 * &mm1 + dest]] +(-1) '.' /;
      end;
   put "    &m) Stay at home this year." /;
   run;

ods listing;

title 'Vacation Example';

data results;
   input Subj Form (choose1-choose&n) (1.) @@;
   datalines;
  1  1 111353313351554151   2  2 344113155513111413   3  1 132353331151534151
  4  2 341133131523331143   5  1 142153111151334143   6  2 344114111543131151
  7  1 141343111311154154   8  2 344113111343121111   9  1 141124131151342155
 10  2 344113131523131141  11  1 311423131353524144  12  2 332123151413331151
 13  1 311244331352134155  14  2 341114111543131153  15  1 141253111351344151
 16  2 344135131323331143  17  1 142123313154132141  18  2 542113151323131141
 19  1 145314111311144111  20  2 344111131313431143  21  1 133343131313432145
 22  2 344141151213131153  23  1 113453411153334155  24  2 343145151511131153
 25  1 141434111152332144  26  2 334415131511121141  27  1 344144113151334144
 28  2 544344131531131115  29  1 313424133351334151  30  2 344114135513124141
 31  1 131413321111334154  32  2 354113151541131141  33  1 114423121315534144
 34  2 344431151541115141  35  1 141324311331334151  36  2 344114155343131141
 37  1 112423333353534151  38  2 352134131323331141  39  1 112424615353334151
 40  2 444115151523131141  41  1 131123111312532154  42  2 344111131513131131
 43  1 312443131355341155  44  2 344111131333431141  45  1 311453111311534124
 46  2 332111131523134151  47  1 112153333351534111  48  2 342113151513331141
 49  1 114453311351334151  50  2 343115131323132141  51  1 112324333311542144
 52  2 341411151313121154  53  1 143453113353334151  54  2 344113151513134141
 55  1 311314111113334144  56  2 344111151343331151  57  1 111423333153134151
 58  2 544114131523331131  59  1 314144311313134141  60  2 344124131253131143
 61  1 112224121351132141  62  2 344311431523331143  63  1 132223233313332151
 64  2 344124151323331155  65  1 141444313351154154  66  2 341131151333131151
 67  1 112443111311354141  68  2 342144151523135145  69  1 312453133353134114
 70  2 343114431343334141  71  1 353443333311534151  72  2 351114151323335154
 73  1 134124133311334141  74  2 341111151513131143  75  1 142123131111334151
 76  2 331144131543131141  77  1 145353313131532154  78  2 355134131523121151
 79  1 115443311355334121  80  2 344111131323131111  81  1 151223113152332123
 82  2 344114135323134141  83  1 111114311142132125  84  2 554113135323111131
 85  1 311423135351332144  86  2 344141151513131145  87  1 113154111353334151
 88  2 342114151523331111  89  1 115414111151332154  90  2 345115451521134111
 91  1 141153131131131154  92  2 344114111513141143  93  1 314443531152134153
 94  2 344111131323121151  95  1 115123111352534151  96  2 541143151223111151
 97  1 142324113342532153  98  2 344114151533331143  99  1 112424113351334154
100  2 344114131333134141 101  1 111414113355114544 102  2 544113451321334511
103  1 111424311353334134 104  2 341115155313324141 105  1 131314331353132151
106  2 344143131523331141 107  1 233444311353332154 108  2 344113131513234141
109  1 141144121353534154 110  2 343131151251331151 111  1 341443313131334151
112  2 341114151523131134 113  1 131424311121532144 114  2 341114151333341143
115  1 111143123311144544 116  2 343114431541111343 117  1 111123113313134154
118  2 344114151523331141 119  1 111123333111533154 120  2 344113131523131151
121  1 212244111154334151 122  2 342114151343334141 123  1 141123513354544144
124  2 354131431343131151 125  1 132313313351334121 126  2 334115151331135153
127  1 312423131453144154 128  2 344415131513531143 129  1 112423331353534151
130  2 341111151333136153 131  1 141453113131132151 132  2 344115131343231153
133  1 115444131351444553 134  2 344114451513321154 135  1 112653131351334145
136  2 544115151253131141 137  1 112113131321334141 138  2 344114131213334141
139  1 313444511353334121 140  2 344113131323131111 141  1 142123111353134151
142  2 342113151333135141 143  1 111413133352143144 144  2 334131151513131131
145  1 135443311353134144 146  2 345114451521121141 147  1 112424313352331141
148  2 344113151313321144 149  1 112313111351144151 150  2 344115231523131151
151  1 115424611351534154 152  2 344113151453334143 153  1 241143111351534154
154  2 344114131211331151 155  1 114434331311134141 156  2 344114131524331113
157  1 112314311154432145 158  2 341113151353111131 159  1 131454131353332141
160  2 341114151223131351 161  1 111124111315332141 162  2 344143155551131141
163  1 113413311352135554 164  2 342113155523331143 165  1 111443111151334154
166  2 344111131323134143 167  1 112124111313154354 168  2 344113131333131151
169  1 115424513353134151 170  2 544114131343421141 171  1 112444331363334141
172  2 342114131323331151 173  1 112444111351534154 174  2 354141151523331111
175  1 213414311353334141 176  2 344143151533331143 177  1 114434133311314151
178  2 344114151523331113 179  1 141113311354534151 180  2 341144131334321141
181  1 241453113113534154 182  2 344113135223131151 183  1 111444113351514145
184  2 351414151323111113 185  1 142423131351332154 186  2 344134151513131145
187  1 313123131352134121 188  2 341143151323131144 189  1 115443133151534151
190  2 333134151123331141 191  1 112423111351134154 192  2 344411151253321153
193  1 111113311351131141 194  2 334115131523331133 195  1 112123113313534151
196  2 345124155313331144 197  1 142154311311434151 198  2 344115151323121141
199  1 141423111351534154 200  2 342131451313134141
;

%mktmerge(design=sasuser.VacationChDes, data=results, out=res2, blocks=form,
          nsets=&n, nalts=&m, setvars=choose1-choose&n)

proc print data=res2(obs=12);
   id subj form set; by subj form set;
   run;

proc transreg design=5000 data=res2 nozeroconstant norestoremissing;
   model class(place / zero=none order=data)
         class(price scene lodge / zero=none order=formatted) /
         lprefix=0;
   output out=coded(drop=_type_ _name_ intercept);
   id subj set form c;
   run;

proc print data=coded(obs=6);
   id place;
   var subj set form c price scene lodge;
   run;

proc print data=coded(obs=6) label;
   var pl:;
   run;

proc print data=coded(obs=6) label;
   id place;
   var sc:;
   run;

proc print data=coded(obs=6) label;
   id place;
   var lo: pr:;
   run;

proc phreg data=coded brief;
   model c*c(2) = &_trgind / ties=breslow;
   strata subj set;
   run;

%put &_trgind;

proc transreg design data=res2 nozeroconstant norestoremissing;
   model class(place / zero='Home' order=data) identity(price)
         class(scene lodge / zero='Home' 'Home' order=formatted) /
         lprefix=0;
   output out=coded(drop=_type_ _name_ intercept);
   label price = 'Price';
   id subj set form c;
   run;

proc phreg data=coded brief;
   model c*c(2) = &_trgind / ties=breslow;
   strata subj set;
   run;

data res3;
   set res2;
   PriceL = price;
   if price then pricel = (price - 1249) / 250;
   run;

proc transreg design=5000 data=res3 nozeroconstant norestoremissing;
   model class(place / zero='Home' order=data)
         pspline(pricel / degree=2)
         class(scene lodge / zero='Home' 'Home' order=formatted) /
         lprefix=0;
   output out=coded(drop=_type_ _name_ intercept);
   label pricel = 'Price';
   id subj set form c;
   run;

proc phreg data=coded brief;
   model c*c(2) = &_trgind / ties=breslow;
   strata subj set;
   run;

data res4;
   set res3;
   if scene = 0 then scene = .;
   if lodge = 0 then lodge = .;
   run;

proc transreg design=5000 data=res4 nozeroconstant norestoremissing;
   model class(place / zero='Home' order=data)
         pspline(pricel / degree=2)
         class(scene lodge /
               effects zero='Mountains' 'Hotel' order=formatted) /
         lprefix=0;
   output out=coded(drop=_type_ _name_ intercept);
   label pricel = 'Price';
   id subj set form c;
   run;

proc print data=coded(obs=6) label; run;

proc phreg data=coded brief;
   model c*c(2) = &_trgind / ties=breslow;
   strata subj set;
   run;

data key;
   input Place $ 1-10 (Lodge Scene Price) ($);
   datalines;
Hawaii      x1  x6   x11
Alaska      x2  x7   x12
Mexico      x3  x8   x13
California  x4  x9   x14
Maine       x5  x10  x15
.           .   .    .
;

%mktroll(design=sasuser.VacationLinDesBlckd, key=key, alt=place,
         out=sasuser.VacationChDes)

%mktmerge(design=sasuser.VacationChDes, data=results, out=res2, blocks=form,
          nsets=&n, nalts=&m, setvars=choose1-choose&n,
          stmts=%str(price = input(put(price, price.), 5.);
                     format scene scene. lodge lodge.;))

proc print data=res2(obs=12); run;

proc transreg design=5000 data=res2 nozeroconstant norestoremissing;
   model class(place / zero=none order=data)
         class(place * price place * scene place * lodge /
               zero=none order=formatted) / lprefix=0 sep=' ' ', ';
   output out=coded(drop=_type_ _name_ intercept);
   id subj set form c;
   run;

proc print data=coded(obs=6) label noobs; run;

proc phreg data=coded brief;
   model c*c(2) = &_trgind / ties=breslow;
   strata subj set;
   run;

* Begin Vacation Example and Artificial Data Generation Code*;

options ls=80 ps=60 nonumber nodate;
title;

%mktex(3 ** 15,                     /* 15 three-level factors               */
       n=36,                        /* 36 rows in linear arrang - 36 ch sets*/
       seed=205)                    /* random number seed                   */

%mktblock(data=randomized,          /* block randomized design              */
          nblocks=2,                /* create two blocks of 18 choice sets  */
          out=blocked,              /* output data set for blocked design   */
          seed=114)                 /* random number seed                   */

                                    /* make Place from the destinations     */
                                    /* make Lodge from x1-x5                */
                                    /* make Scene from x6-x10               */
                                    /* make Price from x11-x15              */
                                    /* make 'stay at home' from all missing */
data key;
   input Place $ 1-10 (Lodge Scene Price) ($);
   datalines;
Hawaii      x1  x6   x11
Alaska      x2  x7   x12
Mexico      x3  x8   x13
California  x4  x9   x14
Maine       x5  x10  x15
.           .   .    .
;

%mktroll(design=blocked,            /* make choice design from blocked      */
                                    /* linear arrangement from %mktblock    */
         key=key,                   /* use rules in KEY data set            */
         alt=place,                 /* alternative name variable is Place   */
         out=sasuser.ChoiceDesign,  /* permanent data set for results       */
         options=nowarn,            /* don't warn about extra variables     */
         keep=block)                /* keep the blocking variable           */

proc format;                        /* map 1, 2, 3 levels to actual levels  */
   value price 1 = '1499'      2 = '1749'            3 = '1999'  . = ' ';
   value scene 1 = 'Mountains' 2 = 'Lake'            3 = 'Beach' . = ' ';
   value lodge 1 = 'Cabin'     2 = 'Bed & Breakfast' 3 = 'Hotel' . = ' ';
   run;

data sasuser.ChoiceDesign;          /* assign formats to vars in the design */
   set sasuser.ChoiceDesign;
   format scene scene. lodge lodge. price price.;
   run;

proc print data=sasuser.ChoiceDesign; /* display sets and check results     */
   by block set; id block set;
   run;

                                    /* Evaluate the choice design           */
%choiceff(data=sasuser.ChoiceDesign,/* candidate set of choice sets         */
          init=sasuser.ChoiceDesign(keep=set), /* select these sets         */
          intiter=0,                /* evaluate without internal iterations */
                                    /* alternative-specific effects model   */
                                    /* zero=none - no ref levels for place  */
                                    /* order=data - do not sort levels      */
          model=class(place / zero=none order=data)
                                    /* zero=' ' - no ref level for first    */
                                    /* factor (place), ordinary ref levels  */
                                    /* for other factors (price -- lodge).  */
                                    /* order=formatted - sort levels        */
                                    /* use blank sep to build interact terms*/
                class(place * price place * scene place * lodge /
                      zero=' ' order=formatted separators='' ' ') /
                                    /* no ref level for place               */
                                    /* use blank sep to build interact terms*/
                lprefix=0           /* lpr=0 labels created from just levels*/
                cprefix=0,          /* cpr=0 names created from just levels */
          nsets=72,                 /* number of choice sets                */
          nalts=6,                  /* number of alternatives               */
          beta=zero)                /* assumed beta vector, Ho: b=0         */

data Test;          /* Make one copy of the input SAS data set.             */
                    /* DATA step does automatic looping, it automatically   */
                    /* writes out the observation to a SAS data set, and it */
                    /* automatically stops when it hits the end of file on  */
                    /* the input SAS data set.  With 216 observations in    */
                    /* the input SAS data set, there are 216 passes through */
                    /* the DATA step, and since there is no OUTPUT          */
                    /* statement, each observation is automatically written */
                    /* to the output SAS data set by an implicit OUTPUT.    */
   set sasuser.ChoiceDesign;
   run;

data Test;          /* Make one copy of the input SAS data set.  There is   */
                    /* one pass through this DATA step, and the DO loop     */
                    /* reads 216 observations from the input SAS data set.  */

                    /* Do the looping yourself.                             */
   do i = 1 to 216; /* 36 choice sets and 6 alternatives = 216 observations */

                    /* SET statement with POINT=i reads the ith             */
                    /* observation, and the variable i is automatically     */
                    /* dropped from the output SAS data set.                */
      set sasuser.ChoiceDesign point=i;

      output;       /* Write out each observation to a SAS data set.        */
                    /* Without this statement, an OUTPUT statement          */
                    /* implicitly appears at the end of the DATA step,      */
                    /* which would have written out only the last           */
                    /* observation if the STOP statement hadn't stopped the */
                    /* DATA step first.                                     */
      end;

   stop;            /* Must specify STOP since it never hits the end of the */
                    /* data file (it never attempts to read past the last   */
                    /* record).  Infinite loop without this statement.      */
   run;

data Test;          /* Make two copies of the input SAS data set.           */
                    /* There is one pass through this DATA step, the outer  */
                    /* DO loop creates two copies, and the inner DO loop    */
                    /* reads 216 observations from the input SAS data set   */
                    /* (twice due to the outer DO loop).                    */

   do Subject = 1 to 2;/* Two copies.                                       */

                    /* Do the looping yourself.                             */
      do i = 1 to 216; /* 36 choice sets and 6 alternatives = 216 obs       */

                    /* SET statement reads the ith observation, and the     */
                    /* variable i is automatically dropped from the output  */
                    /* SAS data set.                                        */
         set sasuser.ChoiceDesign point=i;

         output;    /* Write out each observation to a SAS data set.        */
                    /* Without this statement, an OUTPUT statement          */
                    /* implicitly appears at the end of the DATA step,      */
                    /* which would have written out only the last           */
                    /* observation if the STOP statement hadn't stopped the */
                    /* DATA step first.                                     */
         end;
      end;

   stop;            /* Must specify STOP since it never hits the end of the */
                    /* data file (it never attempts to read past the last   */
                    /* record).  Infinite loop without this statement.      */
   run;

                    /* Make an informat that will convert the character     */
                    /* values of the Place variable into the integers       */
                    /* 1 - 5.                                               */
proc format;
   invalue plinf 'Hawaii' = 1 'Alaska' = 2 'Mexico' = 3
                 'California' = 4 'Maine' = 5;
   run;

data _null_;
   /* DATA _NULL_ allows you to use the DATA step without creating an       */
   /* output SAS data set.  The result is a list of artificial data written */
   /* to the SAS log.                                                       */
   /*                                                                       */
   /* Specify a list of expected utilities for each level of each           */
   /* attribute in an array for each attribute.  Recall that the Price,     */
   /* Scene, and Lodge have actual values 1, 2, 3 that correspond to the    */
   /* formatted values shown here:                                          */
   /*                                                                       */
   /* value price 1 = '1499'      2 = '1749'            3 = '1999'          */
   /* value scene 1 = 'Mountains' 2 = 'Lake'            3 = 'Beach'         */
   /* value lodge 1 = 'Cabin'     2 = 'Bed & Breakfast' 3 = 'Hotel'         */
   /*                                                                       */
   /* In the design data set, actual values are stored not the formatted    */
   /* values.  However, Place has only actual values.                       */
   /*                                                                       */
   /* When Place = 'Hawaii',                                                */
   /* input(place, plinf.) = 1, and the utility, dests[1] = 5;              */
   /* when Place = 'Alaska',                                                */
   /* input(place, plinf.) = 2, and the utility, dests[2] = -1;             */
   /* and so on.                                                            */
   /*                                                                       */
   /* When Scene = 1, and the formatted value is 'Mountains',               */
   /* scenes[1] = -1; and so on.                                            */
   /*                                                                       */
   /* Price has values 1 to 3 and they can be used directly in the          */
   /* utility function (or in a way similar to the other attributes).       */
   /*                                                                       */
   /* _temporary_ is used when the goal is for an array name and an         */
   /* index to access a list of values, and no data set variables are       */
   /* created or needed.                                                    */
   /*                                                                       */
   /* Be careful that your array names and variable names do not            */
   /* conflict with variable names in the input design data set.            */

   array dests[5]    _temporary_ (5 -1 4 3 2);
   array scenes[3]   _temporary_ (-1 0 1);
   array lodging[3]  _temporary_ (0 3 2);

   array u[6];              /* An array to store the utility of each alt    */

   Subject = 0;             /* Subject number                               */

   do s = 1 to 100;         /* Create data for 100 subjects per block       */

      i = 0;                /* Observation number in the design data set    */
      do BlockNum = 1 to 2; /* Create data for 2 blocks of 100 subjects     */
         Subject + 1;       /* Subject number                               */

         /* put /        - go to a new line                                 */
         /* blocknum 3.  - write the block number in 3 columns              */
         /* +2           - skip two columns                                 */
         /* subject  3.  - write the subject number in 3 columns            */
         /* +2           - skip two columns                                 */
         /* @@;          - hold the output line for the data yet to come    */
         put / blocknum 3. +2 subject 3. +2 @@;

         do SetNum = 1 to 18; /* Loop over the 18 sets in a block           */
            do Alt = 1 to 6;  /* Loop over the 6 alts in a set              */

               i + 1;         /* same as i = i + 1; design index,           */
                              /* i = 1 to 216 (2 blocks x 18 sets x 6 alts) */

                              /* Read the ith observation of the choice     */
                              /* design.  Note that you are reading the     */
                              /* choice design not the linear arrangement.  */
                              /* Just read in the variables that you need.  */
               set sasuser.ChoiceDesign(keep=place--price) point=i;

               if place ne ' '/* process the destinations differently       */
                  then do;    /* from the constant 'stay at home'           */
                  p = input(place, plinf.); /* map place values to 1-5      */
                  u[alt] = 1 +              /* add 1 just for not at home   */
                           dests[p] +       /* util for destination         */
                           scenes[scene] +  /* util for scenery             */
                           lodging[lodge] - /* util for lodging             */
                           price;           /* negative util for price      */

                  if place = 'Hawaii' and   /* add in Hawaii/Beach          */
                     scene = 3 then         /* interaction                  */
                     u[alt] = u[alt] + 2;

                  if place = 'Maine' and    /* add Maine on a lake in a     */
                     scene = 2 and lodge = 1/* cabin interaction            */
                     then u[alt] = u[alt] + 1;

                  end;

               else u[alt] = 0;                  /* util for stay at home   */

               u[alt] = u[alt] + 3 * normal(17); /* add error to utils      */
                                                 /* change '3' to change    */
                                                 /* the magnitude of error  */

               /* Alternatively, you can create Type I Gumbel errors for    */
               /* some scaling parameter b as follows:                      */
               /* u[alt] = u[alt] + b * log(-log(1 - uniform(104)));        */
               end;

            /* at this point you have gathered u1-u6 for all 6 alts         */
            m = max(of u1-u6);              /* max util over alts           */

            /* which one had the maximum util? do fuzzy comparison          */
            if      abs(u1 - m) < 1e-4 then c = 1; /* alt 1 is chosen       */
            else if abs(u2 - m) < 1e-4 then c = 2; /* alt 2 is chosen       */
            else if abs(u3 - m) < 1e-4 then c = 3; /* alt 3 is chosen       */
            else if abs(u4 - m) < 1e-4 then c = 4; /* alt 4 is chosen       */
            else if abs(u5 - m) < 1e-4 then c = 5; /* alt 5 is chosen       */
            else                            c = 6; /* alt 6 is chosen (home)*/

            put +(-1) c @@; /* write number of chosen alt. Use '@@' to hold */
                            /* the line for the rest of the data in this    */
                            /* block for this subject.                      */
                            /* +(-1) skips forward -1 space, which is how   */
                            /* you move back one space                      */
            end;
         end;
      end;
   stop;                    /* explicitly stop since no end of file is hit  */
   run;

data results;               /* Read the input data.  List input for block   */
                            /* and subject.  Formatted input (fields of     */
                            /* size 1) for choices.                         */
   input Block Subject (choose1-choose18) (1.);
   datalines;
  1    1 416434213415311535
  2    2 115411541451441151
  1    3 132455331434113144
  2    4 313313244121311314
  1    5 451143532541411214
  2    6 311131311414411511
  1    7 113115431313311134
  2    8 415343411134441331
  1    9 133335335133331114
  2   10 513414531111451413
  1   11 241153533114313111
  2   12 343434311411344311
  1   13 153153351116313414
  2   14 411111241411111131
  1   15 135353234111411114
  2   16 313314541531311331
  1   17 141133313135411111
  2   18 316414131111241313
  1   19 113135362111411511
  2   20 113413441141315561
  1   21 131331413114413534
  2   22 113235341143341331
  1   23 111153311114151414
  2   24 314313331431411111
  1   25 554315432413113314
  2   26 311435151151311131
  1   27 311351233134311151
  2   28 431344341521411151
  1   29 141133453111411254
  2   30 311441451521411131
  1   31 531353433514311411
  2   32 414114444124441111
  1   33 141133334113111113
  2   34 313111341413441131
  1   35 311355431114313111
  2   36 443314331151441633
  1   37 341154311112413154
  2   38 311314634111311111
  1   39 511333331413111134
  2   40 321416411533441431
  1   41 511134411411445111
  2   42 311443144421511351
  1   43 431613313115111514
  2   44 333413451151144131
  1   45 131354333213313144
  2   46 115141411531411114
  1   47 533333431114413111
  2   48 313441441121341511
  1   49 144355331113411514
  2   50 113435351413415311
  1   51 134154331414311511
  2   52 113411544433411551
  1   53 144245433113111553
  2   54 315633156451541151
  1   55 311333332114313311
  2   56 534413315421414351
  1   57 151353333111411114
  2   58 111415414141441511
  1   59 311133311113411113
  2   60 312431411534331313
  1   61 144135313444331134
  2   62 346635144161411114
  1   63 441333353115414154
  2   64 311333241453115133
  1   65 311155141115331511
  2   66 533313154431451531
  1   67 151153333134311514
  2   68 111314645431431151
  1   69 151133113114311531
  2   70 314334561321345141
  1   71 151335333211113114
  2   72 314411214111411114
  1   73 511324112113311511
  2   74 313411151411541143
  1   75 331633361115111112
  2   76 115314411411341114
  1   77 331333433114111154
  2   78 311513144451111361
  1   79 361443114113311111
  2   80 311433411131411141
  1   81 351313131515311111
  2   82 313313111431441531
  1   83 541333315515313131
  2   84 413433315111353131
  1   85 311154535114111114
  2   86 315436331416511131
  1   87 335144311115116154
  2   88 311334341431341151
  1   89 131351331114451133
  2   90 111333541121461111
  1   91 511133531113313311
  2   92 341413135431415111
  1   93 131353131113111311
  2   94 311411511441131531
  1   95 331153361113313514
  2   96 511111511431311131
  1   97 111351463113411111
  2   98 113133151531311131
  1   99 431153512434411511
  2  100 311113511133431131
  1  101 143133364113111434
  2  102 111434343531411311
  1  103 351113332115111514
  2  104 315413341121161121
  1  105 143335333415311111
  2  106 115513351431261111
  1  107 511353311115333311
  2  108 313413151521313131
  1  109 515443531114113534
  2  110 314633311131231531
  1  111 341131313114311111
  2  112 313513143131411111
  1  113 111135431115113111
  2  114 515313511414351331
  1  115 131343511114313154
  2  116 311331141154311134
  1  117 131311431414311514
  2  118 313316114421541514
  1  119 141364434415411114
  2  120 111313311111341331
  1  121 133135311114313155
  2  122 413315341554441131
  1  123 141333311514161331
  2  124 311415411411411161
  1  125 351113433114131111
  2  126 111411345311341134
  1  127 131454135111143111
  2  128 413331551431443351
  1  129 131333331114353554
  2  130 414431411121431511
  1  131 111134331614111354
  2  132 113431531441443131
  1  133 541144134314311431
  2  134 113431351311511135
  1  135 561135433441411114
  2  136 115413541521311111
  1  137 341451133114411151
  2  138 113433314154341341
  1  139 451254544444313515
  2  140 113111311511513333
  1  141 544335333115411111
  2  142 164113311534111331
  1  143 151333231413311154
  2  144 313451111541313134
  1  145 114253313214311154
  2  146 313311141433311551
  1  147 411134531133114551
  2  148 113453415421231531
  1  149 241355333135115111
  2  150 313453415631111313
  1  151 111134332114313114
  2  152 311313545321351131
  1  153 551343431511311114
  2  154 411314551131451354
  1  155 144453111114343154
  2  156 312411341421541361
  1  157 111133431315314511
  2  158 313413111111411334
  1  159 161134331111315114
  2  160 313331511151311133
  1  161 315155151134311314
  2  162 414333611154151131
  1  163 211633131111311114
  2  164 313411441153341111
  1  165 141145133113411561
  2  166 311415211523311111
  1  167 134345132434311554
  2  168 111413155153341113
  1  169 141551332114411111
  2  170 111511111151311131
  1  171 341361115134111514
  2  172 414433151114111334
  1  173 344334361414311111
  2  174 111441411531541534
  1  175 141353333513411114
  2  176 431413451411141343
  1  177 151134111511314554
  2  178 315413351411511521
  1  179 111155531414313114
  2  180 315413311533633134
  1  181 351445331545311635
  2  182 313341541131441111
  1  183 311133313411313144
  2  184 313113331553241431
  1  185 161113616114115111
  2  186 213313412411451531
  1  187 141343141114113111
  2  188 314411441133363333
  1  189 131313311314113151
  2  190 113435111541241131
  1  191 141153431433311113
  2  192 313434111541151511
  1  193 531143112514311531
  2  194 313435311454513531
  1  195 145345244114311511
  2  196 443313441151463131
  1  197 331335333114313112
  2  198 111314251521211141
  1  199 151351211114311131
  2  200 311314311151143141
;

proc print; run;                       /* make sure data match input        */

%mktmerge(design=sasuser.ChoiceDesign, /* merge the design data set         */
          data=results,                /* with the results                  */
          out=res2,                    /* create output data set res2       */
          blocks=block,                /* name of blocking variable         */
          nsets=18,                    /* number of choice sets per block   */
          nalts=6,                     /* number of alternatives            */
          setvars=choose1-choose18)    /* variables with the choices        */

proc print data=res2(obs=18);          /* display some data - sanity check  */
   id block subject set;
   by block subject set;
   run;

proc transreg                          /* use proc transreg to code         */
      data=res2                        /* name of data set to code          */
      design=5000                      /* code big designs in chunks        */
                                       /* code up to 5000 obs at a time     */
      nozeroconstant                   /* don't zero constant variables     */
      norestoremissing;                /* zeros in coded vars, not missings */
   model class(place /                 /* code Place variable               */
               zero=none               /* use all nonmissing levels         */
               order=data)             /* don't sort levels                 */
         class(place * price           /* code other vars                   */
               place * scene
               place * lodge /
               zero=none               /* use all nonmissing levels         */
                                       /* including 0 reference levels      */
               order=formatted         /* do sort levels by formatted values*/
               separators='' ' ') /    /* use blank separator in interacts  */
         lprefix=0;                    /* make labels just from levels      */
   output out=coded                    /* output coded data set             */
        (drop=_type_ _name_ intercept);/* drop vars that you don't need     */
   id subject set block c;             /* add extra vars that you do need   */
   run;

%phchoice( on )                        /* customize output from PHREG for   */
                                       /* choice models                     */

proc phreg data=coded brief;           /* do analysis with a brief summary  */
                                       /* of strata (set, subject, block)   */
   model c*c(2) = &_trgind / ties=breslow; /* standard choice model         */
   strata subject set block;           /* ID variables who taken together   */
   run;                                /* identify each individual choice   */
                                       /* set                               */

data _null_;
   do s = 1 to 100;
      do BlockNum = 1 to 2;
         Subject + 1;
         put / blocknum 3. +2 subject 3. +2 @@;
         do SetNum = 1 to 18;
            c = ceil(6 * uniform(17));
            put +(-1) c @@;
            end;
         end;
      end;
   stop;
   run;

proc freq data=coded noprint;
   tables subject*set*block / list out=t1;
   run;

proc freq; tables count; run;

proc freq data=coded noprint;
   tables subject*set / list out=t1;
   run;

proc freq; tables count; run;

%phchoice(off)