Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • translate SAS proc mixed code to Stata mixed code

    A client has performed an analysis using SAS proc mixed and wants me to check the analysis and, more importantly, to do some post-hoc estimates and checks on the analysis; I am asking for help re: what the Stata command should look like as I have never used SAS proc mixed.

    First, their brief description of the analysis goal:

    Code:
    a repeated measures mixed model on reported sedentary activities hours. Sedentary activities hours were reported
    over 3 days and so this was used as outcome as a repeated measures.
    
    
    Outcome variable, sedentaryhrs.
    
    The model that was landed on included predictors:
    
       *  Sex: 1=male, 2=female (reference)
       *  Status, for marital status: 1=single (reference), 2=married, 3=widowed, 4=separated/divorced
       *  Employment2cat: 1=working (full/part, student), 0=not working due to disability, retired, others (reference)
       *  Caregiveq1: 1=yes caregiver, 2=no caregiver (reference)
       *  Skinulcer: 1=yes current skin ulcer, 0=no current skin ulcer (reference)
       *  Active_diuretic: 1=active diuretic user, 0=non active diuretic user (reference)
       *  Pfat_total: continuous variable for % total fat
       *  Smoker: 1=current smoker, 0=non smoker (reference)
    Second, the SAS command:

    Code:
    proc mixed data=mixsedentary;
        class day sex status (ref='1') employment2cat (ref='0') caregiveq1 skinulcer (ref='0')
                active_diuretic (ref='0') smoker (ref='0');
        model sedentaryhrs=sex status employment2cat caregiveq1 skinulcer active_diuretic pfat_total smoker /s;
        repeated day /type=un subject=id;
        lsmeans sex status employment2cat caregiveq1 skinulcer active_diuretic smoker;
    run;
    I believe, but am not sure, that "lsmeans" part is similar to Stata's -margins- command and ask whether that is the case?

    third, a dataex example (100 out of an N of 1038):
    Code:
    * Example generated by -dataex-. For more info, type help dataex
    clear
    input str5 id double sedentaryhrs byte(day sex status employment2cat caregiveq1 skinulcer active_diuretic) double pfat_total byte smoker
    "1019"    7 1 1 2 0 2 0 1 44.4 0
    "1019"   15 2 1 2 0 2 0 1 44.4 0
    "1019"    2 3 1 2 0 2 0 1 44.4 0
    "1039"    3 1 1 4 0 2 0 0 25.6 1
    "1039"    3 2 1 4 0 2 0 0 25.6 1
    "1039"    3 3 1 4 0 2 0 0 25.6 1
    "1041"    7 1 1 2 0 2 0 0 40.3 0
    "1041"    6 2 1 2 0 2 0 0 40.3 0
    "1041"  5.5 3 1 2 0 2 0 0 40.3 0
    "1048"    6 1 1 1 0 2 0 0 53.5 1
    "1048"    5 2 1 1 0 2 0 0 53.5 1
    "1048"    5 3 1 1 0 2 0 0 53.5 1
    "1066"   12 1 1 2 0 1 0 0 23.9 0
    "1066"    9 2 1 2 0 1 0 0 23.9 0
    "1066"    8 3 1 2 0 1 0 0 23.9 0
    "1127"  4.5 1 1 1 0 2 0 1 31.8 0
    "1127"    0 2 1 1 0 2 0 1 31.8 0
    "1127"    0 3 1 1 0 2 0 1 31.8 0
    "1133"    8 1 1 2 1 2 0 0 47.5 0
    "1133"    2 2 1 2 1 2 0 0 47.5 0
    "1133"  8.5 3 1 2 1 2 0 0 47.5 0
    "1140"   14 1 1 2 0 2 0 1 34.3 0
    "1140"   14 2 1 2 0 2 0 1 34.3 0
    "1140"   12 3 1 2 0 2 0 1 34.3 0
    "1144"    9 1 1 2 0 2 0 1 45.4 0
    "1144"   10 2 1 2 0 2 0 1 45.4 0
    "1144" 13.5 3 1 2 0 2 0 1 45.4 0
    "1166"    6 1 1 2 1 2 0 0 45.4 0
    "1166"    3 2 1 2 1 2 0 0 45.4 0
    "1166"    0 3 1 2 1 2 0 0 45.4 0
    "1180"    4 1 1 2 1 2 0 0 30.3 0
    "1180"  1.5 2 1 2 1 2 0 0 30.3 0
    "1180"    2 3 1 2 1 2 0 0 30.3 0
    "1200"    3 1 1 4 1 2 0 0 46.2 0
    "1200"    3 2 1 4 1 2 0 0 46.2 0
    "1200"    3 3 1 4 1 2 0 0 46.2 0
    "1323"   19 1 1 2 0 2 1 0 23.7 1
    "1323"   19 2 1 2 0 2 1 0 23.7 1
    "1323"   19 3 1 2 0 2 1 0 23.7 1
    "1339"    2 1 1 1 1 2 0 0 34.6 0
    "1339"    2 2 1 1 1 2 0 0 34.6 0
    "1339"    2 3 1 1 1 2 0 0 34.6 0
    "1424"    9 1 1 1 0 1 0 0 43.9 0
    "1424"    9 2 1 1 0 1 0 0 43.9 0
    "1424"    9 3 1 1 0 1 0 0 43.9 0
    "1475"    6 1 1 1 0 2 0 1 34.1 0
    "1475"    6 2 1 1 0 2 0 1 34.1 0
    "1475"    6 3 1 1 0 2 0 1 34.1 0
    "1532" 2.75 1 1 2 0 2 0 1 26.2 0
    "1532"    1 2 1 2 0 2 0 1 26.2 0
    "1532"  1.5 3 1 2 0 2 0 1 26.2 0
    "1610"    3 1 1 2 0 2 0 0 31.6 1
    "1610"    2 2 1 2 0 2 0 0 31.6 1
    "1610"    1 3 1 2 0 2 0 0 31.6 1
    "1707"   .5 1 1 4 0 2 1 0 43.1 0
    "1707"    8 2 1 4 0 2 1 0 43.1 0
    "1707"    3 3 1 4 0 2 1 0 43.1 0
    "1715"    2 1 1 1 1 1 0 0 47.1 0
    "1715"    2 2 1 1 1 1 0 0 47.1 0
    "1715"    4 3 1 1 1 1 0 0 47.1 0
    "2090"  4.5 1 1 2 0 2 0 0 53.6 0
    "2090"  3.5 2 1 2 0 2 0 0 53.6 0
    "2090"  4.5 3 1 2 0 2 0 0 53.6 0
    "2244"    2 1 2 2 1 2 1 0 44.6 0
    "2244"    2 2 2 2 1 2 1 0 44.6 0
    "2244"    2 3 2 2 1 2 1 0 44.6 0
    "2323"  2.5 1 1 2 1 2 0 0 40.2 0
    "2323"    6 2 1 2 1 2 0 0 40.2 0
    "2323"    3 3 1 2 1 2 0 0 40.2 0
    "3012"    5 1 1 2 0 1 0 1 45.6 0
    "3012"    5 2 1 2 0 1 0 1 45.6 0
    "3012" 10.5 3 1 2 0 1 0 1 45.6 0
    "3033"    2 1 1 2 0 1 0 0 53.2 0
    "3033"    2 2 1 2 0 1 0 0 53.2 0
    "3033"    2 3 1 2 0 1 0 0 53.2 0
    "3043"    8 1 1 2 0 1 0 0 36.6 0
    "3043"    2 2 1 2 0 1 0 0 36.6 0
    "3043"    2 3 1 2 0 1 0 0 36.6 0
    "3046"    0 1 1 3 0 2 0 0 28.8 0
    "3046"    2 2 1 3 0 2 0 0 28.8 0
    "3046"    2 3 1 3 0 2 0 0 28.8 0
    "3056"    4 1 1 2 0 2 0 1 36.9 0
    "3056"    3 2 1 2 0 2 0 1 36.9 0
    "3056"    2 3 1 2 0 2 0 1 36.9 0
    "3057"    0 1 1 2 0 2 0 0   27 1
    "3057"    0 2 1 2 0 2 0 0   27 1
    "3057"    0 3 1 2 0 2 0 0   27 1
    "3058"    1 1 1 2 1 2 0 0 29.3 0
    "3058"    8 2 1 2 1 2 0 0 29.3 0
    "3058"    0 3 1 2 1 2 0 0 29.3 0
    "3065"   15 1 1 1 0 1 0 0 39.7 0
    "3065"    9 2 1 1 0 1 0 0 39.7 0
    "3065"    8 3 1 1 0 1 0 0 39.7 0
    "3070"   11 1 1 4 0 1 0 0   41 0
    "3070"    3 2 1 4 0 1 0 0   41 0
    "3070"    4 3 1 4 0 1 0 0   41 0
    "3076"  1.5 1 1 1 1 1 0 0 30.6 0
    "3076"  1.5 2 1 1 1 1 0 0 30.6 0
    "3076"    1 3 1 1 1 1 0 0 30.6 0
    "3081"   .5 1 1 1 1 2 1 0   16 0
    end

  • #2
    Hi Rich, the model is straightforward to replicate in SAS, thankfully. The following model and example margins command will reproduce what SAS estimates. I can send you the full SAS output from the example data and model if you like (it's quite verbose), just send me a private message.

    Some things to note about the default behaviour in SAS:
    • CLASS refers to categorical variables, and the default level is the last one when sorted by raw values
    • REML is the default estimation method
    • LSMEANS in this case is the equivalent to -margins, asbalanced atmeans-
    • the residual covariance structure implies no additional subject-level error variance

    Code:
    mixed sedentaryhrs b2.sex b1.status b0.employment2cat b2.caregiveq1 b0.skinulcer ///
          b0.active_diuretic pfat_total b0.smoker ///
          || id : , nocons resid(un, t(day)) reml nolog nolrtest
    
    margins i.sex , asbal atmeans

    Comment


    • #3
      Hi Leonardo Guizzetti - thank you very much; the client sent me the full output from the full data set, so no need to send the output for the sample data

      added: just checked with the full data and all results matched except (1) AIC and BIC which were very slightly different and (2) the margins command as your code did not include all the variables (but I checked some of the others and the results did match (but weirdly, SAS does not give them in the "obvious" order (e.g., the SAS order for "status" is 2,3,4,1 rather than 1,2,3,4)) - thanks again

      forgot to note that since I am only dealing with one model, AIC and BIC are of no interest anyway <grin>
      Last edited by Rich Goldstein; 01 Nov 2025, 11:54.

      Comment

      Working...
      X