SAS Certification Handout #12: Adv. Prog. Ch. 11-12 /************ Ch. 11
Total Page:16
File Type:pdf, Size:1020Kb
SAS Certification Handout #12: Adv. Prog. Ch. 11-12 /************ Ch. 11 ******************/ %let HOnum=12; libname cert 'C:/jrstevens/Teaching/SAS_Cert/AdvNotes'; /* In SAS Studio, after creating SAS_Cert folder with username jrstevens: */ * libname cert '/home/jrstevens/SAS_Cert'; /* sales */ data cert.sales&HOnum; format LastName $9. Sales dollar8.; input LastName $ FirstName $ EmplID Division $ Contracts Volume Sales; label EmplID = "Employee ID"; cards; Smith B 315 A 45 10015 553312 Nelson E 333 A 23 32162 555827 Riley X 125 B 61 32631 748391 Uribe R 612 C 22 43221 867159 Larson A 331 B 61 12553 521592 Larsen L 216 B 62 12632 123513 Rasmussen K 217 A 33 43336 125321 Butikofer J 338 A 62 33921 332521 Knecht P 861 B 11 43111 983152 Larson A 331 C 62 6123 381592 ; /* pp. 400-406 Different ways for macros to be set up: 1. positional parameters 2. keyword parameters 3. mixed parameter lists (positional [first] and keyword) 4. varying number of parameters (PARMBUFF) */ /* 1. positional parameters */ %macro getAve(setname, varname); proc means data=&setname mean; var &varname; run; Analysis Variable : Sales %mend; Mean getAve % (cert.sales&HOnum, Sales) 519238.00 /* Note no semicolon after call (p. 394) */ 1 /* 2. keyword parameters */ %macro getExpAve(setname=&syslast, varname=X, power=1); data &setname; set &setname; new&varname = &varname**&power; label new&varname = "Power &power of &varname"; proc means data=&setname mean; var new&varname; run; Analysis Variable : newSales Power %mend; 1 of Sales Mean %getExpAve(setname=cert.sales&HOnum, varname=Sales, 519238.00 power=1) Analysis Variable : newSales Power %getExpAve(setname=cert.sales&HOnum, 2 of Sales varname=Sales, power=2) Mean 345294119712 %getExpAve() Analysis Variable LOG: NOTE: Variable X is uninitialized. : newX Power 1 of X Mean . /* 3. mixed parameter lists */ %macro getNewExpAve(setname, varname, power=1); data &setname; set &setname; new&varname = &varname**&power; label new&varname = "Power &power of &varname"; proc means data=&setname mean; var new&varname; Analysis Variable run; : newSales Power 2 of Sales %mend; Mean %getnewExpAve(cert.sales&HOnum, Sales, power=2) 345294119712 2 /* 4. varying number of parameters (PARMBUFF) -- usually involve automatic macro variable SYSPBUFF and a DO loop */ %macro tempCall / parmbuff; %put SYSPBUFF contains: &SYSPBUFF; %local i; %do i=1 %to %sysfunc(countw(&SYSPBUFF)); %let data_i = %scan(&SYSPBUFF,&i); proc corr data=&data_i nosimple; var Y X; run; %end; %mend; data temp1; set cert.sales&HOnum; Y = Sales; X = Volume; data temp2; set cert.sales&HOnum; Y = Sales; X = Contracts; data temp3; set cert.sales&HOnum; Y = Volume; X = Contracts; %tempCall(temp1, temp2) Pearson Correlation Coefficients, N = 10 Prob > |r| under H0: Rho=0 Y X Y 1.00000 0.37750 tempCall 0.2822 % (temp3) Pearson Correlation Coefficients, N = 10 X 0.37750 1.00000 Prob > |r| under H0: Rho=0 0.2822 Y X Y 1.00000 -0.67666 0.0317 X -0.67666 1.00000 Pearson Correlation Coefficients, N = 10 Prob > |r| under H0: Rho=0 0.0317 Y X Y 1.00000 -0.53754 0.1090 X -0.53754 1.00000 0.1090 3 /* tools for debugging macros: (p. 393) MCOMPILENOTE - LOG message when macro is compiled (p. 397) MPRINT - text to be compiled is sent to LOG (p. 398) MLOGIC - LOG message for each step of macro execution (p. 399) %* comments [why not /* ... ?] (p. 412-415) MPRINTNEST & MLOGICNEST [specifically for nested macros] %PUT at various steps to see what current macro values are pp. 426-430 DO loops */ options mcompilenote=all; %macro showNesting(maxI); %do i=2 %to &maxI %by 2; /* %BY default is 1 */ %* p. 399 says can comment this way inside a macro ; * but this works too [both up to semicolon] ; %getnewExpAve(cert.sales&HOnum, Contracts, power=&i) %end; LOG: NOTE: The macro SHOWNESTING completed compilation %mend; without errors. 15 instructions 312 bytes. options mprint mlogic mprintnest mlogicnest; %showNesting(7) LOG: 369 370 options mprint mlogic mprintnest mlogicnest; 371 %showNesting(7) MLOGIC(SHOWNESTING): Beginning execution. MLOGIC(SHOWNESTING): Parameter MAXI has value 7 MLOGIC(SHOWNESTING): %DO loop beginning; index variable I; start value is 2; stop value is 7; by value is 2. MPRINT(SHOWNESTING): * but this works too [both up to semicolon] ; MLOGIC(SHOWNESTING.GETNEWEXPAVE): Beginning execution. MLOGIC(SHOWNESTING.GETNEWEXPAVE): Parameter SETNAME has value cert.sales12 MLOGIC(SHOWNESTING.GETNEWEXPAVE): Parameter VARNAME has value Contracts MLOGIC(SHOWNESTING.GETNEWEXPAVE): Parameter POWER has value 2 MPRINT(SHOWNESTING.GETNEWEXPAVE): data cert.sales12; MPRINT(SHOWNESTING.GETNEWEXPAVE): set cert.sales12; MPRINT(SHOWNESTING.GETNEWEXPAVE): newContracts = Contracts**2; MPRINT(SHOWNESTING.GETNEWEXPAVE): label newContracts = "Power 2 of Contracts"; ... 4 options mcompilenote=none nomprint nomlogic Analysis Variable nomprintnest nomlogicnest; : newContracts Power 2 of Contracts Mean 2322.20 Analysis Variable : newContracts Power 4 of Contracts /* pp. 406-415: Mean %GLOBAL identifies macro variable as 7783597.40 existing both outside and inside macros. %LOCAL identifies macro variable as only Analysis Variable exisiting inside macro itself (precedence : newContracts Power over same-named global variables). 6 of Contracts Mean %LET assigns macro variable value (inside or outside macro definition) 28329987642 */ data cert.sales&HOnum; set cert.sales&HOnum; row=_n_; run; %let A=3; %macro tryThis(b); %local A; %let A=1; proc print data=cert.sales&HOnum; where row <= &a; var LastName Sales Row; title1 &b ; run; Note %local precedence %mend; Obs LastName Sales row %tryThis("Note %local precedence"); 1 Smith $553,312 1 Now with global A=3 proc print data=cert.sales&HOnum; Obs LastName Sales row where row <= &a; var LastName Sales Row; 1 Smith $553,312 1 title1 "Now with global A=&a" ; 2 Nelson $555,827 2 run; title1; 3 Riley $748,391 3 5 /* pp. 415-426 %IF ... %THEN ... <%ELSE> ... -- only works inside macro, and only refers to macro variables -- case-sensitive condition checks (so maybe use %UPCASE, p. 425) -- evaluated to determine text for input stack */ %macro trial(X); %if %upcase(&x) = GLM %then %do; proc glm data=cert.sales&HOnum; class division; model Sales = Division; run; %end; %else %if %upcase(&x) = REG %then %do; proc reg data=cert.sales&HOnum; model Sales = Contracts; run; %end; %else %do; %put <ATTN>; %put <ATTN> X=&X option resulted in no output; %put <ATTN>; %end; %mend; The GLM Procedure Dependent Variable: Sales Source DF Sum of Squares Mean Square F Value Pr > F %trial(glm) Model 2 109579816127 54789908063 0.59 0.5785 Error 7 647280374551 92468624936 Corrected Total 9 756860190678 ... The REG Procedure Analysis of Variance trial % (Reg) Source DF Sum of Mean F Value Pr > F Squares Square Model 1 2.18696E11 2.18696E11 3.25 0.1090 Error 8 5.381642E11 67270523142 Corrected Total 9 7.568602E11 ... 6 LOG: %trial(something) <ATTN> <ATTN> X=something option resulted in no output <ATTN> /* p. 420 WHERE ALSO -- not a macro thing, just to add multiple WHERE statements (AND) */ proc print data=cert.sales&HOnum; where division="A"; Obs LastName Sales Division where also Sales > 500000; 1 Smith $553,312 A var lastname sales division; title1; 2 Nelson $555,827 A run; /* LOG: NOTE: WHERE clause has been augmented. */ /* p. 430: %EVAL for simple integer arithmetic & logical p. 432: %SYSEVALF for floating-point arithmetic ( incl. non-integer) */ %let a = 7; %let b = 8; %let c = &a + &b; %put C = &C; LOG: C = 7 + 8 %let a = 7; %let b = 8; %let c = %eval(&a + &b); %put C = &C; LOG: C = 15 %let a = 7.3; %let b = -8.13; %let c = %eval(&a + &b); LOG: ERROR: A character operand was found in the %EVAL function or %IF condition where a numeric operand is required. The condition was: 7.3 + -8.13 %let a = 7.3; %let b = -8.13; %let c = %sysevalf(&a + &b); %put C = &C; /* LOG: C = -0.83 */ LOG: C = -0.83 /* pp. 395-397: how macros are processed */ 7 /************ Ch. 12 ******************/ /* Four main ways to store macro definitions in external files: 1. (p. 443) %INCLUDE (calls full .sas files, not just macros) 2. (p. 446) store macro as SOURCE in CATALOG 3. (p. 450) autocall (with OPTIONS MAUTOSOURCE SASAUTOS= ) 4. (p. 454) stored compiled macro using STORE option (with OPTIONS MSTORED SASMSTORE= ) The 'source' program is the original .sas file defining the macro. */ /* 1. (p. 443) %INCLUDE (calls full .sas files, not just macros) */ %include "C:/jrstevens/Teaching/SAS_Cert/AdvNotes/getAve1.sas"; %getAve1(cert.sales&HOnum, Sales) Source Program (getAve1.sas) SAS Output Using %include %macro getAve1(setname, varname); proc means data=&setname mean; The MEANS Procedure var &varname; Analysis Variable title1 "Using %include"; : Sales run; Mean %mend; 519238.00 /* 2. (p. 446) store macro as SOURCE in CATALOG; with getAve2.sas open: File --> Save As Object --> (make new Mymacs folder in CERT library) --> enter name as getAve2 and description as "Macro to get average of a given variable in given data set", then Save */ /* See summary (value here is seeing description) */ proc catalog cat=cert.Mymacs; contents; quit; Contents of Catalog CERT.MYMACS # Name Type Create Date Modified Date Description 1 GETAVE2 SOURCE 02/18/2015 02/18/2015 Macro to get average of a given 12:57:25 12:57:25 variable in given data set 8 /* Call it -- still need %include */ filename getAve2 catalog "cert.mymacs.getAve2.source"; %include getAve2; %getAve2(cert.sales&HOnum, Sales) Source Program (getAve2.sas) SAS Output Using CATALOG Source %macro getAve2(setname, varname); proc means data=&setname mean; The MEANS Procedure var &varname; Analysis Variable title1 "Using CATALOG Source "; : Sales run; Mean %mend; 519238.00 /* 3. (p. 450) autocall (with OPTIONS MAUTOSOURCE SASAUTOS= ) - First save getAve3.sas (same name as defined macro) in specified folder - This approach essentially makes all .sas files in the referenced Folder available for macro calls (so SAS will look in all of them to find called macros not already available to it (first in currently-defined, then in permanent, and then in autocall).