Skip to content

Instantly share code, notes, and snippets.

@lanejames35
Last active October 15, 2016 02:40
Show Gist options
  • Save lanejames35/2fcaab1cc85ddfea0d950be70aa344ea to your computer and use it in GitHub Desktop.
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
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