Foundations and Fundamentals
Paper 143-2009
Don't Be a SAS® Dinosaur: Modernizing Programs with Base SAS 9.2 Enhancements Warren Repole Jr., SAS Institute Inc.
ABSTRACT
New features of the SAS® programming language often permit the replacement of complex algorithms and clunky workarounds with more elegant code. Some enhancements support the creation of more efficient solutions. Whether you are a SAS programmer with many years of experience or a novice user who is responsible for maintaining legacy programs, implementing updated approaches can allow you to streamline your SAS applications, expedite the development and debugging process, and minimize future maintenance of the code.
INTRODUCTION
This paper covers a selection of enhancements implemented in SAS 9.2, including new features of Base SAS procedures, the DATA step, functions, formats, and the macro language. Each enhancement is paired with an alternative technique available prior to SAS 9.2. This allows for comparison of older and newer approaches. The primary motivation for exploiting SAS 9.2 enhancements is the ability to create robust yet easy-to-maintain SAS programs with less programmer effort. Efficiency gains in terms of machine resources might be achieved, but they are of secondary importance in most examples.
BASE SAS PROCEDURES
PROC PRINT: BLANKLINE= OPTION
Inserting a blank line into PROC PRINT output after every n observations could enhance readability, but this was difficult to accomplish prior to SAS 9.2. Observations with missing values were inserted, the MISSING= system option was switched to a blank (then reset to its default value afterward), and the NOOBS option was required. In SAS 9.2 producing this type of report is simple using the BLANKLINE= option in the PROC PRINT statement. data class_blanks(drop=i); set sashelp.class; output; if mod(_n_,5)=0; array alln {*} _numeric_ ; array allc {*} _character_ ; do i=1 to dim(alln); alln{i}=.; end; do i=1 to dim(allc); allc{i}=" "; end; output; run; options missing=" "; proc print data=class_blanks noobs ; run; options missing=".";
proc print data=sashelp.class blankline=5 ; run;
Figure 1a. PROC PRINT code before SAS 9.2
Figure 1b. PROC PRINT code with BLANKLINE= option
1
SAS Global Forum 2009
Foundations and Fundamentals
Obs 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Name Alfred Alice Barbara Carol Henry James Jane Janet Jeffrey John Joyce Judy Louise Mary Philip Robert Ronald Thomas William
Sex M F F F M M F F M M F F F F M M M M M
Age 14 13 13 14 14 12 12 15 13 12 11 14 12 15 16 12 15 11 15
Height 69.0 56.5 65.3 62.8 63.5 57.3 59.8 62.5 62.5 59.0 51.3 64.3 56.3 66.5 72.0 64.8 67.0 57.5 66.5
Weight 112.5 84.0 98.0 102.5 102.5 83.0 84.5 112.5 84.0 99.5 50.5 90.0 77.0 112.0 150.0 128.0 133.0 85.0 112.0
Figure 1c. Output from Figure 1b program including the Obs column suppressed in Figure 1a program PROC SORT: SORTSEQ= OPTION
Sorting character data that is stored inconsistently in terms of case has been a challenge for many years. Typical solutions involved converting the data to uppercase using the UPCASE function before sorting. In SAS 9.2 the SORTSEQ= value of LINGUISTIC with the collating rule STRENGTH=PRIMARY supports sorting that is not case sensitive. Diacritical differences and punctuation are handled through other STRENGTH= settings. data french; set maps.names; where Territory contains "France"; Territory_Upper=upcase(Territory); run; proc sort data=french; by Territory_Upper Name ; run; proc sort data=maps.names out=french sortseq=linguistic (strength=primary) ; where Territory contains "France"; by Territory Name ; run;
Figure 2a. PROC SORT using uppercase values
Figure 2b. PROC SORT using SORTSEQ=LINGUISTIC option
Collating rules associated with the sorted data are exploited in subsequent BY statements.
TERRITORY Overseas Department of France TERRITORY Overseas Department of France Overseas