BookmarkSubscribeRSS Feed
tbanh
Fluorite | Level 6

Hi all,

I have created a macro called Simulation that outputs a longitudinal dataset with repeated measures for each subject. One problem that I'm having is that I cannot figure out how to loop through different sample sizes. As of right now, the macro can take one sample size and output the dataset. However, what I want to do is give the macro several sample size conditions and have the macro loop through each one and create a dataset. Is this possible? The code is below:

%macro Simulation;

    proc iml;

        beta = &Beta.;

        Cov_Random_Effects = &CovRandom.;

        Cov_Errors = &CovError.;

        SampSize = &SampSize.;

        TimeVec = {0, 2, 4, 6};

        TimePoints = nrow(TimeVec);

        NumItemPer = &NumItemPer.;

        Mean_Errors = 0;

        Mean_Random_Effects = j(1, nrow(Cov_Random_Effects), 0);

       

        Random_Effects = shape(

                            repeat(

                                randnormal(

                                            SampSize*NumItemPer,

                                            Mean_Random_Effects,

                                            Cov_Random_Effects

                                               ),

                                    1,

                                    TimePoints

                                    ),

                                SampSize*TimePoints*NumItemPer,

                                nrow(Cov_Random_Effects)

                                );

        Random_Errors = randnormal(SampSize*NumItemPer*TimePoints, Mean_Errors, Cov_Errors);

        Intercept = J(SampSize*NumItemPer*TimePoints, 1, 1);

        Time = repeat(TimeVec,SampSize*NumItemPer, 1);

        XDesign = Intercept||Time;

        Response = XDesign*Beta + Intercept#Random_Effects[,1] + Time#Random_Effects[,2] + Random_Errors;

        Subject = repeat(colvec(repeat(T(1:SampSize), 1, TimePoints)), NumItemPer, 1);

        Iter = repeat(colvec(repeat(T(1:NumItemPer), 1, SampSize*TimePoints)), 1, 1);

        Data = Subject||Response||Time||Iter;

        Cname = {"Subject" "Response" "Time" "Iter"};

        create SimulatedData

        from Data[c=Cname];

        append from Data;

        close SimulatedData;

    quit;

    proc mixed data = SimulatedData;

    by Iter;

    class Subject;

    ods output CovParms = cp SolutionF = fixed_effects;

    model Response = Time / s ddfm = &ddfm.;

    repeated / subject = Subject;

    random int Time / subject = subject type = &CovStructure.;

    run;

    proc means data = fixed_effects noprint;

    var Estimate StdErr;

    class Effect;

    output out = Means mean(Estimate StdErr) = MeanFE MeanSE;

     run;

%mend Simulation;

%let Beta = {16.7611, 0.6602};

%let CovRandom = {1.9211 0,

                   0 .0228};

%let CovError = 1.8787;

%let SampSize = 5;

%let NumItemPer = 50;

%let ddfm = KR;

%let CovStructure = vc;

%Simulation;

5 REPLIES 5
Rick_SAS
SAS Super FREQ

Your simulation is excellent! Very efficient. No loops. Well done!

You have two parameters that determine the sample size: the number of subjects and the number of time points for each subject.  Based on the names of your variables, it looks like you want to vary the number of subjects, which appears to be controlled by the SampSize macro variable.  Is that correct?

Are you trying to run a series of simulations to see how the number of subjects affects the results, maybe as part of a power and sample size study?

If you are doing a sample size study, I suggest that you add an iteration loop in the PROC IML step:

do SampSize = 5 to 40 by 5;

...

end;

and add an extra BY group variable to your PROC MIXED and PROC MEANS calls:

PROC MIXED;

by SampSize Iter;

...

run;

PROC MEANS;

by SampSize;

...

run.

tbanh
Fluorite | Level 6

Hi Rick,

Thanks for the response and the compliment. Yes, I am running a sample size study and the SampSize macro variable controls the number of Level-2 subjects. One question I have is whether the "do SampSize = 5 to 40 by 5" step is before the proc iml step or within the proc iml step? Secondly, must I create a SampSize variable for my dataset? The log in SAS is telling me that there is no "SampSize" variable to group the analyses by. Also, it seems that when somewhere in the code, the condition for SampSize = 5 is created, then for SampSize = 10, but the SampSize = 10 condition is overwriting the SampSize = 5 dataset. Any ideas as to what is going on?

Thanks,

Tim

Rick_SAS
SAS Super FREQ

Inside the loop. You can use the DO statement to replace

SampSize = &SampSize.;

Put the END statement before the CLOSE statement.

Yes, you need to construct a vector that contains the sample size and append it to the DATA variable and add the variable name to CName.

tbanh
Fluorite | Level 6

Hi Rick,

So I have modified the original code. I have appended the SampSize condition to the original dataset. The problem is, the code is still not looping through the different sample sizes. Could you look at the code below and see if there's still something I should be doing. Thanks!

%macro Simulation;

    proc iml;

        beta = &Beta.;

        Cov_Random_Effects = &CovRandom.;

        Cov_Errors = &CovError.;

        %do SampSize = 5 %to 10 %by 5;

        SampSize = &SampSize.;

        TimeVec = {0, 2, 4, 6};

        TimePoints = nrow(TimeVec);

        NumItemPer = &NumItemPer.;

        Mean_Errors = 0;

        Mean_Random_Effects = j(1, nrow(Cov_Random_Effects), 0);

       

        Random_Effects = shape(

                            repeat(

                                randnormal(

                                            SampSize*NumItemPer,

                                            Mean_Random_Effects,

                                            Cov_Random_Effects

                                               ),

                                    1,

                                    TimePoints

                                    ),

                                SampSize*TimePoints*NumItemPer,

                                nrow(Cov_Random_Effects)

                                );

        Random_Errors = randnormal(SampSize*NumItemPer*TimePoints, Mean_Errors, Cov_Errors);

        Intercept = J(SampSize*NumItemPer*TimePoints, 1, 1);

        Time = repeat(TimeVec,SampSize*NumItemPer, 1);

        XDesign = Intercept||Time;

        Response = XDesign*Beta + Intercept#Random_Effects[,1] + Time#Random_Effects[,2] + Random_Errors;

        Subject = repeat(colvec(repeat(T(1:SampSize), 1, TimePoints)), NumItemPer, 1);

        Iter = repeat(colvec(repeat(T(1:NumItemPer), 1, SampSize*TimePoints)), 1, 1);

        SampSize = repeat(colvec(repeat(T(SampSize), 1, SampSize*TimePoints*NumItemPer)), 1, 1);

        Data = Subject||Response||Time||Iter||SampSize;

        Cname = {"Subject" "Response" "Time" "Iter" "SampSize"};

        create SimulatedData

        from Data[c=Cname];

        append from Data;

    %end;

        close SimulatedData;

    quit;

    proc mixed data = SimulatedData;

    by SampSize Iter;

    class Subject;

    ods output CovParms = cp SolutionF = fixed_effects;

    model Response = Time / s ddfm = &ddfm.;

    repeated / subject = Subject;

    random int Time / subject = subject type = &CovStructure.;

    run;

    proc means data = fixed_effects noprint;

    by SampSize;

    var Estimate StdErr;

    class Effect;

    output out = Means mean(Estimate StdErr) = MeanFE MeanSE;

     run;

%mend Simulation;

%let Beta = {16.7611, 0.6602};

%let CovRandom = {1.9211 0,

                   0 .0228};

%let SampSize = 10;

%let CovError = 1.8787;

%let NumItemPer = 50;

%let ddfm = KR;

%let CovStructure = vc;

%Simulation;

Rick_SAS
SAS Super FREQ

1) You do not need a macro %DO loop. An ordinary IML DO loop will suffice.

2) You need to move the CREATE statement outside the DO loop because you only want to create the data set one time, but append to it many times.

Here's the shell:

proc iml;
    beta = &Beta.;
    Cov_Random_Effects = &CovRandom.;
    Cov_Errors = &CovError.;

    Cname = {"Subject" "Response" "Time" "Iter" "SampSize"};
    Data = j(1, ncol(CName), .); /* specify that data are numerical vars */
    create SimulatedData from Data[c=Cname];
    do SampSize = 5 to 10 by 5;   /* for each sample size ... */
       /* ...simulate multiple samples for this sample size... */

       Size = SampSize + 0*Iter;
       Data = Subject||Response||Time||Iter||Size;
       append from Data;               /* ...and write this simulation to disk *.
   end;
close SimulatedData;
quit;

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

Multiple Linear Regression in SAS

Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.

Find more tutorials on the SAS Users YouTube channel.

From The DO Loop
Want more? Visit our blog for more articles like these.
Discussion stats
  • 5 replies
  • 1225 views
  • 6 likes
  • 2 in conversation