Search code examples
sasprocmixed-mode

Estimating the multiple input in PROC MIXED


I'm looking for something that similar to Proc score (result from proc reg) for estimating the data set.

So far I have something like this.

PROC MIXED data = maindata noclprint covtest;
Class ID;
Weight w1;
Model TIME = Age Age*Age / Solution cl residual;
Random Intercept Age Age*Age / sub=ID;
Estimate 'ID1' Intercept 1 Age 10 Age*Age 100 | Intercept 1 Age 10 Age*Age 100/ cl Subject 1;
Estimate 'ID2' Intercept 1 Age 12 Age*Age 144 | Intercept 1 Age 12 Age*Age 144/ cl Subject 0 1;
Estimate 'ID3' Intercept 1 Age 11 Age*Age 121 | Intercept 1 Age 11 Age*Age 121/ cl Subject 0 0 1;
Estimate 'ID4' Intercept 1 Age 15 Age*Age 225 | Intercept 1 Age 15 Age*Age 225/ cl Subject 0 0 0 1;
(. . . You get the point)
run; quit;

Here is my estimate data set:

ID  Age AgeSq
1   10   100
2   12   144
3   11   121
4   15   225
...
50  9    81

My question is there are any other way that is more efficiency than have 50 of these estimate statement.

I tried PROC PLM. The problem with PROC PLM (SCORE(PREDICTED)) is that it doesn't take random effect into an account.(http://support.sas.com/documentation/cdl/en/statug/63347/HTML/default/viewer.htm#statug_plm_a0000000126.htm)


Solution

  • EDIT: I hadn't properly read the end of your question regarding plm. My apologies, please see below the break for an alternative.

    This is not something I've done but I believe you can achieve what you want with proc plm which can score datasets (among other things) using models produced by proc mixed, proc glm and others.

    The basic approach is to store a binary representation of your model using the store statement:

    proc mixed;
        ...
        store sasuser.myModel;
    run;
    

    Then process your new data using proc plm:

    proc plm source = sasuser.mixed;
        ...
        score data = inData out = want;
    run;
    

    The user guide should help with the finer points.


    There is some more discussion of a similar question with input from Rick Wicklin here.


    As a quick and dirty alternative you could use a macro variable to write your estimate statements:

    proc sql;
        select 
            "estimate 'ID" || put(ID, best.) || "' intercept 1 Age " || 
            put(Age, best.) || " Age*Age " || put(Age**2, best.) || 
            " | intercept 1 Age " ||  put(Age, best.) || " Age*Age " || 
            put(Age**2, best.) || " / cl subject" || repeat(" 0", (ID - 1)) || "1;"
        into :estList separated by " " 
        from inEst
        order by ID;
    quit;
    proc mixed data = maindata noclprint covtest;
        class id;
        weight w1;
        model time = age age*age / solution cl residual;
        random intercept age age*age / sub = id;
        &estList.;
        ods output estimates = want;
    quit;
    

    Basically you create all the estimate statements as strings in an sql query and store them in a macro variable. This approach has its drawbacks:

    • The code becomes obfuscated; it's not obvious what's being done. I'd comment code like this heavily to make it very clear to any poor maintainer why you've done this and what it's doing.
    • Macro variables have have a finite length (65534 characters). If there is any risk of your variable exceeding this you should split it up (with call symput and a do loop) and call the lines from a %do loop.

    Edit: One more option you might want to explore.

    In recent releases proc mixed and proc plm have supported the code statement which can be used to output the SAS data step code required to score new observations. If necessary you could use the generated code as a basis and modify it for the analysis you wish to perform.


    call symput skeleton:

    data _NULL_;
        set inEst nobs = obs;
        length mVar $8.;
        /* Store number of lines in a macro variable */
        if _N_ = 1 then call symput("nVars", obs);
    
        mVar = "est_" || put(_N_, best.);
        value = *** Code to make estimate statement ***;
    
        /* Create a new macro variable for each line */
        call symput(mVar, value);
    run;
    
    %macro temp;
        *** Code ***;
        %do i = 1 %to &nVars.;
             &&est_&i.
        %end;
        *** Code ***;
    %mend temp;
    %temp;