BookmarkSubscribeRSS Feed
pmdci
Fluorite | Level 6

Hello,

I am currently working on a Macro to run two-sample T-Tests, and it is working well as expected. Here is the code:

/* This is a macro for running two-sample T-Tests */

%MACRO twot(dataSrc, depVar, factVar);

TITLE "Hypothesis Test - H0: Mean &depVar by factor &factVar are equal";

PROC TTEST DATA=&dataSrc;

VAR &depVar;

CLASS &factVar;

RUN;

/* blank line */

/* blank line */

TITLE "Verifying the assumption of normality - &depVar by &factVar";

PROC UNIVARIATE DATA=&dataSrc;

VAR &depVar;

CLASS &factVar;

QQPLOT /NORMAL (MU=EST SIGMA=EST);

HISTOGRAM /NORMAL;

RUN;

/* blank line */

/* blank line */

TITLE "Hypothesis Test - H0: Mean &depVar by factor &factVar are equal";

PROC GCHART DATA=&dataSrc;

HBAR &factVar / TYPE=MEAN SUMVAR=&depVar ERRORBAR=BARS CLM=95 NOFRAME;

RUN;

TITLE;

%MEND twot;

Basically this Macro will take the datasource name and the dependent variable and the factor variable to be used to run the two-sample T-Test. If you look at the code from lines 10 to 16 however, this is a test to check the assumption of normality with a QQ PLOT and the bell curve plotted over a histogram.

This code is required if any of the groups in the T-Test have less than 30 observations. However, the way the code is now, this assumption of normality code will run with any T-Test, regardless of how many obs there is.

What I would like to do is modify this macro so the assumption of normality code (lines 10 to 16) would only run if there is less than 30 observations in a given group. Is that possible?

Thanks in advance for the help!

Regards,

P.

5 REPLIES 5
esjackso
Quartz | Level 8

The first thing that came to mind was to add a sql step to put the class group cnts (you can combine the two and eliminate the creation of the dataset, but I left them separate steps just for clarity):

proc sql;

     /*Create dataset with the group cnts*/

     create table grpcnt as

     select &factVar, count(*) as cnt

     from &factVar

      group by &factVar

     ;

     /*put minimum cnt in macro variable*/

     select min(cnt)

     into :mcnt

     from grpcnt

     ;

quit;

then add macro code to control the lines you want to run conditionally:

%if &mcnt < 30 %then %do;

**CODE LINES**

%end;

I dont have a dataset to test this on, but I believe it will work. If not hopefully it points you down a good path.

Eric

pmdci
Fluorite | Level 6

Hi,

Thanks for trying to hep but I am quite confused by the code.

Do I really need to create the temporary dataset (e.g.: grpcnt as per your example)? I was hoping that I could save the count value in a macro variable that I could then refer to in my macro in an IF-THEN statement.

I'm also a bit confused with the proposed code %if &mcnt < 30 %then %do

I was under the impression that macros start with %MACRO [name] and end with %MEND [name]. Also, not sure how to interpret the %then and %do syntax. Is that part of the same macro?

Regards,

P.

esjackso
Quartz | Level 8

No problem,

Since I didnt have a convenient test dataset I kept the code broken up to keep simple. I believe the following would eliminate the temp dataset I proposed:

proc sql;

     select min(cnt)

     into :mcnt

     from (

           select &factVar, count(*) as cnt

           from &factVar

              group by &factVar

               )

     ;

quit;


The code you proved was already in a macro. The code I suggested is just part of that macro that you supplied.  Put %if line above line 10 (ie the start of the code that you want to run conditionally) then you need a %end at the end of the code that you want to run conditionally (after line 16 in code above).


The macro conditional code is similar to a conditional logic in a standard data step. All the lines after the do (up until the end) are run if the condition is met.


Hope this helps!


EJ

AncaTilea
Pyrite | Level 9

Hi.

Here is a similar option:

In your PROC TTEST I would add an ODS OUTPUT statement:

proc ttest data = ;

class;

var;

ODS OUTPUT Statistics = number(keep = n);*THIS GIVES YOU THE NUMBER OF RECs PER CLASS;

run;

proc sql noprint;

     select min(n) into :cnt

     from number;

quit;

&if &cnt. > 30 %then %do;

*------THE REST OF YOUR CODE;

%end;

Good luck!

Anca.

esjackso
Quartz | Level 8

Another good option.

sas-innovate-wordmark-2025-midnight.png

Register Today!

Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.


Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 5 replies
  • 1176 views
  • 4 likes
  • 3 in conversation