Last active
October 15, 2016 02:40
-
-
Save lanejames35/2fcaab1cc85ddfea0d950be70aa344ea to your computer and use it in GitHub Desktop.
Code used in the Introduction to the SAS Macro Language session at the APHEO Unconference
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
options nodate nonumber formdlim="-"; | |
** Change the file path to the location where the data is saved; | |
proc import datafile='C:\temp\iceCream.csv' | |
out=IceCream | |
dbms=csv | |
replace; | |
getnames=yes; | |
run; | |
/********************* | |
Macro Variables | |
*********************/ | |
title 'Student Ice Cream Survey'; | |
title2 'Crosstabs of Categorical Variables'; | |
proc surveyfreq data=IceCream; | |
weight weight; | |
tables Grade Group Flavour / nostd cl cv; | |
run; | |
title; | |
** Using a macro variable; | |
%let vars = Grade Group Flavour; | |
title2 'This procedure a macro variable'; | |
proc surveyfreq data=IceCream; | |
tables &vars / nostd cl cv; | |
run; | |
** Print a macro variable value to the log; | |
%put My first macro variable vars = &vars; | |
** SAS has several system defined macro variables; | |
%put _automatic_; | |
** Let's make use of an automatic macro variable; | |
title 'Student Ice Cream Survey'; | |
title2 'Crosstabs of Categorical Variables, Updated &sysdate'; | |
proc surveyfreq data=IceCream; | |
weight weight; | |
tables &vars / nostd cl cv; | |
run; | |
** Macro variables need double quotes when used in a string; | |
title 'Student Ice Cream Survey'; | |
title2 "Crosstabs of Categorical Variables, Updated &sysdate"; | |
proc surveyfreq data=IceCream; | |
weight weight; | |
tables &vars / nostd cl cv; | |
run; | |
title; | |
** Bouns: print all user defined macro variables; | |
%put _user_; | |
/************************* | |
Macro Functions | |
*************************/ | |
%put &vars; | |
** Turn a macro variable to upper case with %upcase; | |
%let upper = %upcase(&vars); | |
%put Look mom, all caps &upper; | |
%put; | |
** Parse whole words in a macro variable with %scan; | |
%let word2 = %scan(&vars, 2); | |
%put The second word of vars is &word2; | |
%put; | |
** Parse individual characters in a macro variable with %substr; | |
%let subword = %substr(&vars, 5, 3); | |
%put The substring of &vars is &subword; | |
%put; | |
** The macro language is purely text-based, so this will fail; | |
%let k = 1; | |
%let tot = &k + 1; | |
%put &tot; | |
%put; | |
** Use %eval to evaluate expressions; | |
%let tot = %eval(&k + 1); | |
%put &tot; | |
%put; | |
** %eval is only for integer evalution; | |
** Use %sysevalf for floating point precision; | |
%let tot = %eval(&k + 1.234); | |
%let tot = %sysevalf(&k + 1.234); | |
%put &tot; | |
%put; | |
/******************************************** | |
symput and symget function | |
********************************************/ | |
*symput to pull values from data step to macro variable; | |
proc freq data=IceCream; | |
table Grade / out=gr7; | |
where Grade=7; | |
run; | |
proc print data=gr7; | |
run; | |
data _null_; | |
set gr7; | |
call symput('nGr7', COUNT); | |
run; | |
%put &nGr7 observations are from respondents in grade 7; | |
*example on symget; | |
data IceCream_Gr7; | |
set IceCream; | |
Gr7 = symget('nGr7')+0; | |
run; | |
proc print data=IceCream_Gr7; | |
var Grade Gr7; | |
run; | |
/********************************************* | |
Creating macro variables using proc sql | |
**********************************************/ | |
proc sql noprint; | |
select sum(Spending>=10) into :spend10 | |
from IceCream; | |
quit; | |
%put spend10 is &spend10; | |
proc sql noprint; | |
select mean(Spending) into :spend7 - :spend9 | |
from IceCream | |
group by Grade; | |
quit; | |
%put Average spending was &spend7, &spend8, and &spend9 for grade 7, 8, and 9, respectively; | |
/*********************************** | |
Macro for a repeated process | |
***********************************/ | |
** First set-up for a list of crosstabulation variables; | |
%macro myCrosstab(demographics=); | |
/*Initalize a counter to track each variable*/ | |
%let k=1; | |
%let var=%scan(&demographics,&k); | |
/*Loop around until all variables are analyzed*/ | |
%do %while("&var" NE ""); | |
proc surveyfreq data=IceCream; | |
weight weight; | |
tables &var*Group / row nocellpct nototal nowt nostd cl cv chisq(secondorder); | |
run; | |
/*Increment the counter*/ | |
%let k = %eval(&k + 1); | |
/*Select the next variable in the input list*/ | |
%let var=%scan(&demographics,&k); | |
%end; | |
%mend; | |
/* Run the macro with the demographics in the dataset */ | |
%myCrosstab(demographics=Age Sex Education) | |
** Modify the macro to create an output dataset for each analysis | |
and combine them into a master results dataset; | |
%macro myCrosstab(demographics=,excelFilePath=); | |
/*Initalize a counter to track each variable*/ | |
%let k=1; | |
%let var=%scan(&demographics,&k); | |
/*Loop around until all variables are analyzed*/ | |
%do %while("&var" NE ""); | |
proc surveyfreq data=IceCream; | |
weight weight; | |
tables PHU*&var*Group / row nocellpct nototal nowt nostd cl cv chisq(secondorder); | |
ods output Crosstabs=_result&k; | |
run; | |
data _result&k; | |
set _result&k; | |
rename &var=Demographic; | |
label &var="&var"; | |
label phu="Location"; | |
labelpos=5; | |
labeldata=cat(round(RowPercent,0.1),"%"); | |
if Group="More"; | |
drop Table Frequency LowerCL UpperCL CV _SkipLine F_:; | |
run; | |
/*Increment the counter*/ | |
%let k = %eval(&k + 1); | |
/*Select the next variable in the input list*/ | |
%let var=%scan(&demographics,&k); | |
%end; | |
/* Create a dataset of the results if requested */ | |
%if "&excelFilePath" NE "" %then %do; | |
ods excel file="&excelFilePath" options(sheet_interval='none' sheet_name='Analysis'); | |
%do x=1 %to &k-1; | |
%let var=%scan(&demographics,&x); | |
ods noproctitle; | |
ods text="Analysis of heavy ice cream spenders by &var."; | |
proc print data=_result&x noobs label; | |
var phu Demographic Group Row:; | |
run; | |
ods graphics / height=10cm width=20cm noborder; | |
proc sgplot data=_result&x noborder; | |
vbarparm category=Demographic response=RowPercent / group=PHU groupdisplay=cluster name="bars"; | |
scatter x=Demographic y=RowPercent / group=PHU groupdisplay=cluster yerrorlower=RowLowerCL yerrorupper=RowUpperCL errorbarattrs=(color=black) markerattrs=(size=0); | |
text x=Demographic y=labelpos text=labeldata / group=PHU groupdisplay=cluster textattrs=(color=black); | |
xaxis display=(noticks nolabel); | |
yaxis display=(noticks nolabel noline) grid gridattrs=(thickness=2) offsetmin=0; | |
keylegend "bars" / title="Location" noborder; | |
run; | |
%end; | |
ods excel close; | |
%end; | |
%else %do; | |
%put ================================================; | |
%put No file name was provided, files not combined; | |
%put ================================================; | |
%end; | |
%mend; | |
** Run the macro without requesting output data; | |
%myCrosstab(demographics=Age Sex Education) | |
** Run the macro and create a results dataset called "analysis"; | |
%myCrosstab(demographics=Age Sex Education | |
,excelFilePath=c:\users\lane_j\documents\analysis.xlsx | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment