/*
/ Program : unipvals.sas
/ Version : 1.19
/ Author : Roland Rashleigh-Berry
/ Date : 12-May-2008
/ Purpose : Clinical reporting macro to calculate p-values for the
/ %unistats macro.
/ SubMacros : %words %dequote
/ Notes : This macro has no way of knowing if the p-values it gives you
/ are relevant or useful. It is up to the statistician to decide
/ upon this matter.
/
/ Calculates Chi-square or Fisher's exact for categorical data,
/ the ANOVA for parametric numeric data and Kruskal-Wallis
/ or Wilcoxon rank sum test for non-parametric numeric data.
/
/ For categorical data, unless you override the test selection
/ using usetest=, Chi-square statistics are the default but if
/ for 2x2 tables the expected cell count for any cell is less
/ than 5 or for larger tables a single expected cell count is
/ less than one or more than 20% of the expected cell counts are
/ less than 5, then the Fisher exact test is used (this rule
/ might be called "Cochran's Recommendation" but please check
/ in "Siegel, S. (1956) Non-parametric Statistics for the
/ Behavioral Sciences" for confirmation).
/
/ For numeric data then the ANOVA is used by default but if
/ usetest=N then the non-parametric Kruskal-Wallis test is used
/ (but that will effectively be the Wilcoxon rank sum test if
/ there are only two treatment arms).
/
/ You should make sure that data for the total of all treatment
/ arms is not present in the input data or the p-values will be
/ incorrect. It is up to you to exclude observations you do not
/ want to include in the analysis.
/
/ The variables kept in the output dataset are the by variables
/ (if any), _pvalue and _test which will be set to "CHISQ" or
/ "FISHER" for categorical analysis, "ANOVA" for continuous
/ numeric analysis or "NPAR1WAY" which applies to the
/ Kruskal-Wallis test and the Wilcoxon rank sum test (for only
/ two treatment arms). "ANOVA" will be replaced by "WELCH" if
/ the Welch test is used.
/
/ Usage : %unipvals(dsin=means,dsout=out,trtvar=tmt,respvar=val,type=N)
/
/===============================================================================
/ PARAMETERS:
/-------name------- -------------------------description------------------------
/ dsin Input dataset
/ usetest For categorical data, set to C (Chi-square) or F (Fisher's
/ exact) to override decision of macro to select Chi-square or
/ Fisher's exact test based on expected cell counts. For
/ numeric data, set to N (non-parametric) to override
/ the ANOVA parametric test. Setting this for categorical
/ variables will overrride use of CMH if adjcntrvar= is set.
/ exact=no By default, do not use an exact test for variables that
/ require a non-parametric test (setting it to yes can
/ consume a very large amount of processing time).
/ dsout Output dataset
/ trtvar Treatment variable (make sure "total treatment" is not
/ present in the input data).
/ respvar Response variable
/ byvars By variable(s) if used
/ byvars2 Extra by variables kept for convenience
/ type Should be C for categorical or N for continuous-numeric
/ adjcntrvar Variable representing the centre to be used in adjustment
/ for centre effects in PROC GLM call. Only one variable
/ allowed. Terms will be generated in the model statement
/ for modelform=short as:
/ model response=trtcd centre /ss1 ss2 ss3 ss4;
/ or for modelform=long as:
/ model response=trtcd centre trtcd*centre /ss1 ss2 ss3 ss4;
/ You can use this parameter for a variable other than a
/ centre but note that whatever variable you choose, if it is
/ not a categorical or dichotomous variable suitable for use
/ in the CLASS statement of a PROC GLM call then you will need
/ to use the glmclass= parameter to supply the correct call.
/ cntrwarn=yes By default, warn if a centre effect and/or centre-by-
/ treatment effect is significant. For the short model as
/ described for the adjcntrvar= parameter, use the centre term.
/ For the long model, use the centre and centre-by-treatment
/ effect term.
/ cntrcond=LE 0.05 Condition for significance to apply to the centre effect
/ intercond=LE 0.1 Condition for significance to apply to the treatment*centre
/ interaction.
/ statsopdest Default is not to write the glm output to any destination.
/ You can set this to PRINT or a file such that PROC PRINTTO
/ understands it. Note that setting it to LOG will not work.
/ errortype=3 Default is to select the error type 3 (Hypothesis type)
/ treatment arm p-value from the ModelANOVA ODS dataset that
/ is output from the GLM procedure.
/ modelform=short Default is to generate the short form of the model statement
/ as described in the adjcntrvar= parameter description.
/ dsmodelanova Dataset to append the ModelANOVA datasets to generated by
/ PROC GLM.
/ hovwarn=yes Issue a warning message where the homogeneity of variances
/ shows a significant difference. This will only be done for
/ one-way ANOVA so if adjcntrvar= is set then the hov*=
/ parameters will be ignored. A NOTE statement will be
/ generated where appropriate if a warning is not issued.
/ hovcond=LE 0.05 Condition for meeting HoV significance
/ hovtest=Levene HoV test to use. You can choose between OBRIEN, BF, Levene,
/ Levene(type=square) and Levene(type=abs). Levene and
/ Levene(type=square) are the same. The Bartlett test is not
/ supported.
/ welch=no By default, do not calculate ANOVA p-values using the Welch
/ test for one-way ANOVA where the HoV condition for
/ significance is met. If Welch is used then the hovtest
/ defined to hovtest= will be employed in the MEANS statement.
/ ---------------------------------------------------------
/ For the following glm*= parameters it is possible to enclose
/ your code in single quotes and then you can use &respvar
/ (the response variable) and &trtvar (the treatment variable)
/ in your code without causing syntax errors.
/ glmclass GLM CLASS statement used to override the generated form.
/ The start word CLASS and ending semicolon will be generated.
/ glmmodel GLM MODEL statement used to override the generated form.
/ The start word MODEL and ending semicolon will be generated.
/ glmmeans GLM MEANS statement used to override the generated form.
/ The start word MEANS and ending semicolon will be generated.
/ glmweight GLM WEIGHT statement that can be added as an extra. The
/ start word WEIGHT and ending semicolon will be generated.
/===============================================================================
/ AMENDMENT HISTORY:
/ init --date-- mod-id ----------------------description------------------------
/ rrb 10Jul06 "missing" option added to tables statements in proc freq
/ calls so it can act on missing values passed to it by
/ the %unistats macro.
/ rrb 14Jul06 Header tidy
/ rrb 23Sep06 Dummy datasets are created to avoid "dataset not found"
/ messages when a stats procedure can not calculate a
/ p-value.
/ rrb 13Feb07 "macro called" message added
/ rrb 21Mar07 Cancel format on _pvalue variable throughout (v1.2)
/ rrb 28Mar07 Header tidy regarding "Cochran's Recommendation"
/ rrb 30Jul07 Header tidy
/ rrb 06Jan08 New parameters adjcntrvar= and statsopdest= added for
/ adjustment for centre effects.
/ rrb 06Jan08 Added errortype= , modelform= and dsmodelanova= for
/ adjustment for centre effects.
/ rrb 07Jan08 hovwarn=, hovcond=, hovtest= amd welch= added to test and
/ warn for homogeneity of variances significant difference
/ for one-way ANOVA and to calculate using Welch test.
/ rrb 08Jan08 Added cntrwarn=, cntrcond= and cntrerrtype= for centre
/ effect warning.
/ rrb 08Jan08 cntrerrtype= removed. cntrcond= value changed and
/ intercond=0.1 added.
/ rrb 13Jan08 cntrwarn= processing changed.
/ rrb 13Jan08 CMH test added so that adjcntrvar= can be used with
/ categorical variables.
/ rrb 14Jan08 glmclass=, glmmodel=, glmmeans= and glmweight= added so
/ the user can override the statements generated by the
/ macro for the main glm call.
/ rrb 19Jan08 %dequote macro used for glm* parameters to allow the user
/ to put code in single quotes and thereby reference macro
/ variables &respvar and &trtvar.
/ rrb 19Jan08 Keep all variables in input dataset
/ rrb 26Jan08 Fixed bug with wrong p-value displayed in log
/ rrb 26Jan08 Choosing Fisher or Chi-square now overrides adjcntrvar=
/ rrb 06Apr08 Fixed bug where "Source" variable in _ANOVA dataset was
/ not in the expected lower case form.
/ rrb 07Apr08 Response variable name given for center effect warning.
/ rrb 13Apr08 glmopdest= replaced by statsopdest= plus made effective
/ for CMH output.
/ rrb 12May08 byvars2= parameter added
/ rrb 12May08 ods listing close syntax fixed
/===============================================================================
/ This is public domain software. No guarantee as to suitability or accuracy is
/ given or implied. User uses this code entirely at their own risk.
/=============================================================================*/
%put MACRO CALLED: unipvals v1.19;
%macro unipvals(dsin=,
usetest=,
exact=no,
dsout=,
trtvar=,
respvar=,
byvars=,
byvars2=,
type=,
adjcntrvar=,
cntrwarn=yes,
cntrcond=LE 0.05,
intercond=LE 0.1,
statsopdest=,
errortype=3,
modelform=short,
dsmodelanova=,
hovwarn=yes,
hovcond=LE 0.05,
hovtest=Levene,
welch=no,
glmclass=,
glmmodel=,
glmmeans=,
glmweight=
);
%local error dofisher testsel trtcount name1str hovpvalue hovsig;
%let error=0;
/*-------------------------------------------------*
Check we have enough parameters set
*-------------------------------------------------*/
%if not %length(&dsin) %then %do;
%let error=1;
%put ERROR: (unipvals) No input dataset specified to dsin=;
%end;
%if not %length(&dsout) %then %do;
%let error=1;
%put ERROR: (unipvals) No output dataset specified to dsout=;
%end;
%if not %length(&trtvar) %then %do;
%let error=1;
%put ERROR: (unipvals) No treatment variable specified to trtvar=;
%end;
%if not %length(&respvar) %then %do;
%let error=1;
%put ERROR: (unipvals) No response variable specified to respvar=;
%end;
%if not %length(&type) %then %do;
%let error=1;
%put ERROR: (unipvals) No type (C)ategorical/(N)umeric specified to type=;
%end;
%if %length(&adjcntrvar) %then %do;
%if %words(&adjcntrvar) GT 1 %then %do;
%let error=1;
%put ERROR: (unipvals) Only one variable allowed. You specified adjcntrvar=&adjcntrvar;
%end;
%end;
%if &error %then %goto error;
%let type=%substr(%upcase(&type),1,1);
%if "&type" NE "C" and "&type" NE "N" %then %do;
%let error=1;
%put ERROR: (unipvals) Type= must be (C)ategorical or (N)umeric;
%end;
%if %length(&usetest) %then %do;
%let usetest=%upcase(%substr(&usetest,1,1));
%if "&usetest" NE "C"
and "&usetest" NE "F"
and "&usetest" NE "N" %then %do;
%let error=1;
%put ERROR: (unipvals) usetest= must be (C)hi-square, (F)isher or
(N)on-parametric;
%end;
%end;
%if not %length(&exact) %then %let exact=no;
%let exact=%upcase(%substr(&exact,1,1));
%if not %length(&errortype) %then %let errortype=3;
%if not %length(&modelform) %then %let modelform=short;
%let modelform=%upcase(%substr(&modelform,1,1));
%if not %length(&hovwarn) %then %let hovwarn=yes;
%let hovwarn=%upcase(%substr(&hovwarn,1,1));
%if not %length(&hovcond) %then %let hovcond=LE 0.05;
%if not %length(&hovtest) %then %let hovtest=Levene;
%if not %length(&welch) %then %let welch=no;
%let welch=%upcase(%substr(&welch,1,1));
%if not %length(&cntrwarn) %then %let cntrwarn=yes;
%let cntrwarn=%upcase(%substr(&cntrwarn,1,1));
%if not %length(&cntrcond) %then %let cntrcond=LE 0.05;
%if not %length(&intercond) %then %let intercond=LE 0.1;
%if &error %then %goto error;
/*--------------------------------*
Define CMH test macro
*--------------------------------*/
%macro cmh(dsin=,dsout=);
ods listing close;
ods output close;
*- create dummy p-value dataset -;
data &dsout;
length Statistic 8 _test $ 8;
retain Prob . _test "CMH";
Statistic=2;
run;
*- merge with by values if any -;
data &dsout;
set _unibyvars;
do ptr=1 to nobsdummy;
set &dsout point=ptr nobs=nobsdummy;
output;
end;
run;
%if %length(&statsopdest) %then %do;
ods listing;
run;
proc printto print=&statsopdest;
run;
%end;
ods output CMH=&dsout;
proc freq data=&dsin;
by &byvars &byvars2 _test;
tables &adjcntrvar*&trtvar*&respvar / cmh;
format &trtvar;
run;
%if %length(&statsopdest) %then %do;
proc printto;
run;
%end;
data &dsout;
set &dsout(keep=&byvars &byvars2 _test Statistic Prob
where=(Statistic=2));
drop Statistic;
format Prob;
rename Prob=_pvalue;
run;
%mend cmh;
/*--------------------------------*
Define Chi-square test macro
*--------------------------------*/
%macro chisq(dsin=,dsout=);
ods output close;
*- create dummy p-value dataset -;
data &dsout;
length Statistic $ 12 _test $ 8;
retain Prob . _test "CHISQ";
Statistic="Chi-Square";
run;
*- merge with by values if any -;
data &dsout;
set _unibyvars;
do ptr=1 to nobsdummy;
set &dsout point=ptr nobs=nobsdummy;
output;
end;
run;
ods output ChiSq=&dsout;
proc freq data=&dsin;
by &byvars &byvars2 _test;
tables &trtvar*&respvar / missing chisq;
format &trtvar;
run;
data &dsout;
set &dsout(keep=&byvars &byvars2 _test Statistic Prob
where=(Statistic="Chi-Square"));
drop Statistic;
format Prob;
rename Prob=_pvalue;
run;
%mend chisq;
/*--------------------------------*
Define Fisher exact test macro
*--------------------------------*/
%macro fisher(dsin=,dsout=);
ods output close;
*- create dummy p-value dataset -;
data &dsout;
length Name1 _test $ 8 Label1 $ 15 cValue1 $ 6;
retain nValue1 . cValue1 Label1 " " _test "FISHER";
Name1="XP2_FISH";
run;
*- merge with by values if any -;
data &dsout;
set _unibyvars;
do ptr=1 to nobsdummy;
set &dsout point=ptr nobs=nobsdummy;
output;
end;
run;
ods output FishersExact=&dsout;
proc freq data=&dsin;
by &byvars &byvars2 _test;
tables &trtvar*&respvar / missing fisher;
format &trtvar;
run;
data &dsout;
set &dsout(keep=&byvars &byvars2 _test Name1 nValue1
where=(Name1="XP2_FISH"));
drop Name1;
format nValue1;
rename nValue1=_pvalue;
run;
%mend fisher;
/*-------------------------------------------------*
Process data
*-------------------------------------------------*/
*- in case input dataset has modifiers -;
data _pvaldsin;
set &dsin;
run;
*- sort by by variables -;
%if %length(&byvars.&byvars2) %then %do;
proc sort data=_pvaldsin;
by &byvars &byvars2;
run;
%end;
*- count how many treatment arms -;
proc sql noprint;
select count(distinct(&trtvar)) into :trtcount
separated by " " from _pvaldsin;
quit;
*- Create a dataset with just the by values in -;
*- so that it can be merged in with the p-value -;
*- dummy datasets. -;
%if %length(&byvars.&byvars2) %then %do;
proc summary nway missing data=_pvaldsin;
class &byvars &byvars2;
output out=_unibyvars(drop=_type_ _freq_);
run;
%end;
%if "&type" EQ "N"
and "&usetest" EQ "N"
and &trtcount GT 2
and "&exact" EQ "Y" %then %do;
%let exact=N;
%put WARNING: (unipvals) Exact test requested but is not available for
&trtcount treatment;
%put WARNING: (unipvals) arms (only 2 allowed) so exact test will not be
used.;
%end;
/*-------------------------------------------------*
Categorical data
*-------------------------------------------------*/
%if "&type" EQ "C" %then %do;
%if not %length(&usetest) and not %length(&adjcntrvar) %then %do;
ods listing close;
/*--------------------------------*
Get expected cell counts
*--------------------------------*/
proc freq data=_pvaldsin noprint;
by &byvars &byvars2;
tables &trtvar*&respvar / missing sparse outexpect out=_expected(drop=percent);
format &trtvar;
run;
/*--------------------------------*
Determine test to be used
*--------------------------------*/
data _whichtest(keep=&byvars &byvars2 _test);
length _test $ 8;
retain _below1 _below5 _cells 0;
set _expected;
by &byvars &byvars2;
if first.%scan(&byvars &byvars2,-1,%str( )) then do;
_below1=0;
_below5=0;
_cells=0;
end;
_cells=_cells+1;
if expected < 1 then _below1=_below1+1;
if expected < 5 then _below5=_below5+1;
if last.%scan(&byvars &byvars2,-1,%str( )) then do;
_test="CHISQ";
if _cells<5 and _below5>0 then _test="FISHER";
else if _cells>4 and (_below1>0 or _below5>(_cells/5)) then
_test="FISHER";
output;
end;
run;
/*--------------------------------*
Find out what tests selected
*--------------------------------*/
proc sql noprint;
select distinct(_test) into :testsel
separated by " " from _whichtest;
quit;
/*--------------------------------*
Split data according to test
*--------------------------------*/
%if "&testsel" EQ "FISHER" %then %do;
%let dodsets=_dofisher;
%let pvaldsets=_fisher;
data _dofisher;
merge _whichtest &dsin;
by &byvars &byvars2;
run;
%fisher(dsin=_dofisher,dsout=_fisher)
%end;
%else %if "&testsel" EQ "CHISQ" %then %do;
%let dodsets=_dochisq;
%let pvaldsets=_chisq;
data _dochisq;
merge _whichtest &dsin;
by &byvars &byvars2;
run;
%chisq(dsin=_dochisq,dsout=_chisq)
%end;
%else %do;
%let dodsets=_dofisher _dochisq;
%let pvaldsets=_fisher _chisq;
data _dofisher _dochisq;
merge _whichtest &dsin;
by &byvars &byvars2;
if _test="FISHER" then output _dofisher;
else if _test="CHISQ" then output _dochisq;
run;
%fisher(dsin=_dofisher,dsout=_fisher)
%chisq(dsin=_dochisq,dsout=_chisq)
%end;
/*--------------------------------*
Bring p-value datasets together
*--------------------------------*/
ods listing;
data &dsout;
set &pvaldsets;
%if %length(&byvars.&byvars2) %then %do;
by &byvars &byvars2;
%end;
run;
proc datasets nolist;
delete _expected _whichtest &pvaldsets &dodsets;
run;
quit;
%end; %*- of if not length(usetest) -;
%else %if "&usetest" EQ "F" %then %do; %*- Fisher exact -;
ods listing close;
data _pvaldsin;
retain _test "FISHER ";
set _pvaldsin;
run;
%fisher(dsin=_pvaldsin,dsout=&dsout);
ods listing;
proc datasets nolist;
delete _pvaldsin;
run;
quit;
%end; %*- of if usetest eq F -;
%else %if "&usetest" EQ "C" %then %do; %*- Chi-square -;
ods listing close;
data _pvaldsin;
retain _test "CHISQ ";
set _pvaldsin;
run;
%chisq(dsin=_pvaldsin,dsout=&dsout);
ods listing;
proc datasets nolist;
delete _pvaldsin;
run;
quit;
%end; %*- of if usetest eq C -;
%else %if %length(&adjcntrvar) %then %do; %*- CMH test -;
ods listing close;
data _pvaldsin;
retain _test "CMH ";
set _pvaldsin;
run;
%cmh(dsin=_pvaldsin,dsout=&dsout);
ods listing;
proc datasets nolist;
delete _pvaldsin;
run;
quit;
%end; %*- end of CMH test -;
%end; %*- of if type eq C -;
/*-------------------------------------------------*
Numeric non-categorical data
*-------------------------------------------------*/
%else %if "&type" EQ "N" %then %do;
%if "&usetest" EQ "N" %then %do; %*- non-parametric test -;
ods listing close;
ods output close;
*- create dummy p-value dataset -;
data _WILC;
length Name1 $ 8 Label1 $ 15 cValue1 $ 6;
retain nValue1 . cValue1 Label1 " ";
Name1="P_KW";
output;
Name1="XP2_WIL";
output;
Name1="P2_WIL";
output;
run;
*- merge with by values if any -;
data _WILC;
set _unibyvars;
do ptr=1 to nobswilc;
set _WILC point=ptr nobs=nobswilc;
output;
end;
run;
%if &trtcount GT 2 %then %do;
ods output KruskalWallisTest=_WILC;
%end;
%else %do;
ods output WilcoxonTest=_WILC;
%end;
proc npar1way data=_pvaldsin wilcoxon;
%if %length(&byvars.&byvars2) %then %do;
by &byvars &byvars2;
%end;
class &trtvar;
var &respvar;
%if "&exact" EQ "Y" %then %do;
exact;
%end;
format &trtvar ;
run;
ods listing;
data &dsout;
retain _test "NPAR1WAY";
set _WILC;
if Name1=
%if &trtcount GT 2 %then %do;
"P_KW"
%end;
%else %do;
%if "&exact" EQ "Y" %then %do;
"XP2_WIL"
%end;
%else %do;
"P2_WIL"
%end;
%end;
;
format nValue1;
rename nValue1=_pvalue;
drop Name1 Label1 cValue1;
run;
proc datasets nolist;
delete _pvaldsin _WILC;
run;
quit;
%end;
%else %do;
/*----------------------------------------*
Parameteric ANOVA
*----------------------------------------*/
/*-------------------*
HoV test and warn
*-------------------*/
ods listing close;
ods output close;
%let hovpvalue=99.0;
%let hovsig=0;
%if not %length(&adjcntrvar) %then %do;
ods output HOVFTest=_hovftest;
proc glm data=_pvaldsin;
%if %length(&byvars.&byvars2) %then %do;
by &byvars &byvars2;
%end;
class &trtvar;
model &respvar=&trtvar;
means &trtvar / hovtest=&hovtest;
format &trtvar ;
run;
data _null_;
set _hovftest(where=(upcase(Source)="%upcase(&trtvar)"));
call symput('hovpvalue',put(ProbF,6.3));
run;
%if %sysevalf(&hovpvalue &hovcond) %then %let hovsig=1;
%if "&hovwarn" EQ "Y" and &hovsig %then %do;
%put WARNING: (unipvals) p-value=&hovpvalue &hovcond for hovtest=&hovtest;
%end;
%else %put NOTE: (unipvals) p-value=&hovpvalue for hovtest=&hovtest;
proc datasets nolist;
delete _hovftest;
run;
quit;
%end;
*- create dummy _anova p-value dataset -;
data _anova;
retain HypothesisType 3 ProbF . Source "%lowcase(&trtvar)" ;
run;
*- merge with by values if any -;
data _anova;
set _unibyvars;
do ptr=1 to nobsdummy;
set _anova point=ptr nobs=nobsdummy;
output;
end;
run;
*- create dummy _welch p-value dataset -;
data _welch;
retain ProbF . Source "%lowcase(&trtvar)" ;
run;
*- merge with by values if any -;
data _welch;
set _unibyvars;
do ptr=1 to nobsdummy;
set _welch point=ptr nobs=nobsdummy;
output;
end;
run;
%if %length(&statsopdest) %then %do;
ods listing;
run;
proc printto print=&statsopdest;
run;
%end;
ods output ModelANOVA=_anova;
%if not %length(&adjcntrvar) and "&welch" EQ "Y" and &hovsig %then %do;
ods output Welch=_welch;
%end;
proc glm data=_pvaldsin;
%if %length(&byvars.&byvars2) %then %do;
by &byvars &byvars2;
%end;
%if %length(&glmclass) %then %do;
CLASS %unquote(%dequote(&glmclass)) ;
%end;
%else %do;
CLASS &trtvar &adjcntrvar;
%end;
%if %length(&adjcntrvar) %then %do;
%if "&modelform" EQ "L" %then %do;
%if %length(&glmmodel) %then %do;
MODEL %unquote(%dequote(&glmmodel)) ;
%end;
%else %do;
MODEL &respvar=&trtvar &adjcntrvar &trtvar*&adjcntrvar / ss1 ss2 ss3 ss4;
%end;
%end;
%else %do;
%if %length(&glmmodel) %then %do;
MODEL %unquote(%dequote(&glmmodel)) ;
%end;
%else %do;
MODEL &respvar=&trtvar &adjcntrvar / ss1 ss2 ss3 ss4;
%end;
%end;
%if %length(&glmmeans) %then %do;
MEANS %unquote(%dequote(&glmmeans)) ;
%end;
%else %do;
MEANS &trtvar ;
%end;
%end;
%else %do;
%if %length(&glmmodel) %then %do;
MODEL %unquote(%dequote(&glmmodel)) ;
%end;
%else %do;
MODEL &respvar=&trtvar ;
%end;
%if %length(&glmmeans) %then %do;
MEANS %unquote(%dequote(&glmmeans)) ;
%end;
%else %do;
%if "&welch" EQ "Y" and &hovsig %then %do;
%put NOTE: (unipvals) PROC GLM will use means statement "means &trtvar / hovtest=&hovtest welch;" %eqsuff(&byvars);
MEANS &trtvar / hovtest=&hovtest welch;
%end;
%else %do;
MEANS &trtvar;
%end;
%end;
%end;
%if %length(&glmweight) %then %do;
WEIGHT %unquote(%dequote(&glmweight)) ;
%end;
format &trtvar ;
run;
ods listing;
run;
%if %length(&statsopdest) %then %do;
proc printto;
run;
%end;
%if %length(&dsmodelanova) %then %do;
proc append force base=&dsmodelanova data=_anova;
run;
%end;
%if not %length(&adjcntrvar) and "&welch" EQ "Y" and &hovsig %then %do;
data &dsout;
retain _test "WELCH ";
set _welch(keep=&byvars &byvars2 ProbF Source
where=(upcase(Source)="%upcase(&trtvar)")
rename=(ProbF=_pvalue));
drop Source;
format _pvalue;
run;
%end;
%else %do;
data &dsout;
retain _test "ANOVA ";
set _anova(keep=&byvars &byvars2 HypothesisType ProbF Source
where=(HypothesisType=&errortype and upcase(Source)="%upcase(&trtvar)")
rename=(ProbF=_pvalue));
drop HypothesisType Source;
format _pvalue;
run;
%if "&cntrwarn" EQ "Y" and %length(&adjcntrvar) %then %do;
%if "&modelform" EQ "L" %then %do;
data _null_;
set _anova(where=(HypothesisType=&errortype));
if upcase(Source) EQ "%upcase(&trtvar*&adjcntrvar)" and ProbF &intercond then
put "WARNING: (unipvals) ANOVA p-value for %upcase(&adjcntrvar*&trtvar) = " ProbF "&intercond for %upcase(&respvar) " %eqsuff(&byvars);
else if upcase(Source) EQ "%upcase(&adjcntrvar)" and ProbF &cntrcond then
put "WARNING: (unipvals) ANOVA p-value for %upcase(&adjcntrvar) = " ProbF "&cntrcond for %upcase(&respvar) " %eqsuff(&byvars) ;
run;
%end;
%else %do;
data _null_;
set _anova(where=(HypothesisType=&errortype
and upcase(Source) EQ "%upcase(&adjcntrvar)"));
if ProbF &cntrcond then
put "WARNING: (unipvals) ANOVA p-value for %upcase(&adjcntrvar) = " ProbF "&cntrcond for %upcase(&respvar) " %eqsuff(&byvars);
run;
%end;
%end;
%end;
proc datasets nolist;
delete _pvaldsin _anova _welch;
run;
quit;
%end;
%end; %*- end of if type is N -;
%if %length(&byvars.&byvars2) %then %do;
proc datasets nolist;
delete _unibyvars;
run;
quit;
%end;
%goto skip;
%error:
%put ERROR: (unipvals) Leaving macro due to error(s) listed;
%skip:
%mend;