David Franklin, Blog
2003 Archive
Back dfranklinnh@gmail.com

 

January

Welcome to this page, the first of hopefully many pages with a SAS related tip of the month. At present there are no plans to have an archive of the tips, but that may change if people ask for it -- at present this page will be updated every month with a new tip. Some of the tips will be short, some will be long, and others will be in-between.

To lead this new series, there will be just a simple tip, one that has been around since I started programming and cannot be stressed enough for the serious programmer.

When you are coding, there will be pieces of code that you will see or use and think "that is interesting". Don't be afraid to copy, or print and paste, that code into a notebook and keep it handy -- you don't know when you are going to need it. You will be amazed at the number of times you will refer to it for that 'little trick'.

February

When creating a variable it is important to tell SAS what the variable type, length and optionally what its label is and any formats applied to it. The ATTRIB statement is useful for doing this although a combination of the LENGTH, LABEL, FORMAT and INFORMAT statements is also okay.

March

When using the SORT procedure try to restrict the number of variables that are in the dataset being sorted. This can be done by making liberal use of the KEEP= or DROP= data set options in the DATA= call of the SORT procedure.

April

Do you want to delete a dataset from a particular library, or possibly all datasets in a library? One way to do it is with the use of the DATASETS procedure, as shown in the following examples:

   *** Delete the single dataset CLASS in the library WORK;
   proc datasets library=work nolist nodetails nowarn;
      delete class /mt=data; *** Delete a single dataset;
      quit;
   run;
   
   *** Delete all the datasets in the library WORK;
   proc datasets library=work nolist nodetails nowarn kill mt=data;
      quit;
   run;

Note that in the first example, the DELETE statement will only work on datasets in the library specified by the LIBRARY option in the top line of the procedure call. The KILL option on the first line of the second example deletes all members of the library WORK, restricted to datasets by using the MT= option in the first line of the procedure call.

May

The INDEX functions are very useful in finding out if a character or word exists in the string. The documentation gives these functions with the following definition:

INDEX -- Searches a character expression for a string of characters
INDEXC -- Searches a character expression for specific characters
INDEXW -- Searches a character expression for a specified string as a word

Now lets see how them in use with the following examples:

   252 data _null_;
   253 TextStr='Apt 56B, Whitehaven Mansions, Sandhurst Sq, London';
   254
   255 *** The location of the first string '6B';
   256 FindINDEX=index(TextStr,'6B');
   257
   258 *** The location of first 's' or 'a' (regardless of order)';
   259 FindINDEXC=indexc(TextStr,'sa');
   260
   261 *** The location of first word 'Whitehaven';
   262 FindINDEXW=indexw(TextStr,'Whitehaven');
   263
   264 put TextStr= /
   265 FindINDEX= FindINDEXC= FindINDEXW=;
   266 run;

   TextStr=Apt 56B, Whitehaven Mansions, Sandhurst Sq, London
   FindINDEX=6 FindINDEXC=16 FindINDEXW=10

June

Want to share your datasets with your colleagues who don't have SAS? Consider asking them to install the free SASViewer available from the SAS Web Site at http://www.sas.com.

July

If it is necessary to convert a unique list of values, separated by a space, within a variable to a macro parameter here is a piece of SAS code that will do this using SQL:

   PROC SQL;
      SELECT DISTINCT var
         INTO :macrovar SEPARATED BY ' '
         FROM dset1
         WHERE var1 IS NOT MISSING;
      QUIT;
   RUN;

August

In their basic form, the COMPRESS and COMPBL functions manipulate the blanks or spaces in a text string.

The COMPBL function will remove multiple blanks in a string and replace them with a single blank – it will also remove trailing and leading blanks from a string.

The COMPRESS function will remove all blank spaces from a string, including the leading and trailing blanks. The COMPRESS function was enhances a few years ago to include characters that a used specified – it was no longer restricted to blanks.

Refer to the following examples of the functions use:

   297 data _null_;
   298 TextStr='1049 Park Avenue, New York, NY';
   299 TextCOMPBL = compbl(TextStr);
   300 TextCOMPRESS = compress(TextStr);
   301 TextCOMPRESS_withoutNumbers = compress(TextStr,'0123456789');
   302 put TextStr= /
   303 TextCOMPBL = /
   304 TextCOMPRESS = /
   305 TextCOMPRESS_withoutNumbers =;
   306 run;

   TextStr=1049 Park Avenue, New York, NY
   TextCOMPBL=1049 Park Avenue, New York, NY
   TextCOMPRESS=1049ParkAvenue,NewYork,NY
   TextCOMPRESS_withoutNumbers=Park Avenue, New York, NY

September

Occasionally SAS will not action a Windows operating system command when using the SYSTEM, CALL SYSTEM, X or macro equivalent statements. In order to circumvent this SAS suggests creating a DOS .BAT file with that command then having SAS call the .BAT file. The following example demonstrates the fix where what the program is asking for a list of .TXT files in a directory which will later be read it:

   rc=SYSTEM("DIR "||dirloc||"\*.txt /b>||"dirlist");  	   

would be rewritten as

   rc=SYSTEM("DIRLSTX dirloc dirlist"); 	   

with the accompanying DIRLSTX.BAT file containing the text

   DIR %1\*.txt /b>%2
         	   

In the example dirloc is the directory location of the files that are of interest, and dirlist is the output file containing the list of .TXT files it found. From what I have read SAS has fixed this problem is the latest SAS version 9 release.

October

Sometimes a missing value needs to be coded, often for some form of frequency analysis. In the example below the missing value for gender is going to be set to '9' while male will remain '1' and female '2'. To make the change there are several solutions, three of which are given below:

   gender = min(gender,9);
   if gender = . then gender = 9;
   if missing(gender) then gender = 9;              

SAS provides many solutions to a single challenge, it is just selecting which is the best for the job on hand that is the most difficult part.

November

Here is an oldie, but a good example of SAS code that I find useful.

Using the following data find the Number of Observations, Mean, Standard Deviation, Median, Minimum and Maximum values for the following data, grouping by Gender and age groups 18-64 and 65-75:

   ** DATA **
   SUBJECT  AGE  GENDER
     001     35    M
     002     70    M
     003     65    M
     004     40    F
     005     66    F
     006     36    F

   ** SAS PROGRAM **
   PROC FORMAT;
      VALUE agex
        18-64='18-64'
        65-75='65-75'
        other='Unexpected';
   RUN;
   PROC MEANS DATA=demog N MEAN STD MEDIAN MIN MAX;
      CLASS gender age;
      VAR age;
      FORMAT age agex.;
   RUN;

Using the AGE variable both in the CLASS and VAR statements it is treated both as a category and analysis variable. Note that the median calculation came into the MEANS procedure in SAS version 7 - prior to that the median could be calculated using the UNIVARIATE procedure.

December

The way a statistic is calculated may be more important than the result it produces. Recently an example showed up when some statistics were being checked using Excel on results produced with SAS, specifically with the calculation of a first and third quartile, also known as the 25th and 75th percentile.

For the data 1, 2, 3, 4, 5, 6, 7 and 8 the following results are calculated for the 25th percentile:

  SAS Method 5 (default) = 2.5
SAS Method 4 = 2.25
Excel = 2.75

Why the difference? There actually is no standard for the calculation of percentile and it does depend on what a statistician is looking for. SAS has six methods of calculating the percentile, the two common ones being:

  Method 5: y = (xj - xj+1)/2 if g=0 or y = xj+1 if g>0, where n*p=j+g
Method 4: y = (1-g)*xj + g*xj+1, where (n+1)*p=j+g and xn+1 is taken to be xn

Excel, S-Plus and StarOffice Calc by comparison uses a different method, specifically:

  y = (1-g)*xj+1+g*xj+2 where (n-1)*p=j+g, and both xn+1 and xn+2 is taken to be xn

Among the major statistical software packages only Excel, S-Plus and StarOffice Calc use this method. For those using Minitab or SPSS they use the SAS Method 4 for their calculation.

The moral of this example is that you should know how your software calculates a statistic before blindly reporting the result.