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 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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
  • 1011 views
  • 4 likes
  • 3 in conversation