Monday, February 29, 2016

Hack 2.5 Obtaining the Computer Memory Available to SAS


SAS Programming Professionals, 

Did you know that you can easily obtain the amount of computer memory available to SAS? 

 You can do so by using the undocumented XMRLMEM option.  XMRLMEM is an undocumented diagnostic option that can come in handy when you are considering allocating a bushel-full of buffers or considering doing some big-time hashing. 

Here is how it might look in action:

            data _null_;
      
      format available_memory 
             available_memory_K 
             available_memory_M 
             available_memory_G comma20.;

      available_memory = input(getoption('xmrlmem'),20.);
      available_memory_K = available_memory/1024;
      available_memory_M = available_memory_K/1024;
      available_memory_G = available_memory_m/1024;

      put "available_memory = " available_memory;
      put "available_memory_K = " available_memory_K;
      put "available_memory_M = " available_memory_M;
      put "available_memory_G = " available_memory_G;

      run;

The code, above, will give you the total number of bytes of real memory available.  (It does not count the operating system's virtual memory; only real memory).  You can simply divide this number by 1024 to get it into K's... or whatever to get it into Megs or Gigs as per the example.  The log from executing this program on the author’s PC looks like this:

       1    data _null_;
       2
       3    format available_memory
       4           available_memory_K
       5           available_memory_M
       6           available_memory_G comma20.;
       7
       8    available_memory = input(getoption('xmrlmem'),20.);
       9
       10   available_memory_K = available_memory/1024;
       11   available_memory_M = available_memory_K/1024;
       12   available_memory_G = available_memory_m/1024;
       13
       14   put "available_memory = " available_memory;
       15   put "available_memory_K = " available_memory_K;
       16   put "available_memory_M = " available_memory_M;
       17   put "available_memory_G = " available_memory_G;
       18
       19   run;

available_memory = 1,713,319,936
available_memory_K = 1,673,164
available_memory_M = 1,634
available_memory_G = 2

Is that all I've got?  It looks like a computer memory upgrade is in order!

Best of luck in all of your SAS endeavors!

----MMMMIIIIKKKKEEEE

(aka Michael A. Raithel)

Excerpt from the book:  Did You Know That?  Essential Hacks for Clever SAS Programmers



I plan to post each and every one of the hacks in the book to social media on a weekly basis.  Please pass them along to colleagues who you know would benefit.

Friday, February 26, 2016

Hack 2.4 Creating Your Own Custom ERROR Messages


SAS Programming Professionals,

Did you know that you can create your own custom error messages and have them written to the SAS log? 

The ERROR statement provides a convenient facility for flagging data issues that you uncover while processing SAS data sets.  The format of the ERROR statement is: 

                ERROR <message>;

 …where message is optional; though what’s the point of not using it?

Here is an example:

             data vetted_class;
      set  sashelp.class; 

if sex = "M" and age > 14 then do;
      ERROR "ERROR: MALE SUBJECT ERROR: Subject too old for
             study";
      delete;
end;
      else if sex = "F" and age < 12 then do;
            ERROR "ERROR: FEMALE SUBJECT ERROR: Subject too
                   young for  study";
            delete;
      end;
run;
In this example, observations for males who are older than 14 are flagged as errors and not written to the output SAS data set.  Instead, a custom error message is written to the SAS log.  Observations for females who are younger than 12 are also flagged as errors and not written to the output SAS data set.  A message specifying that particular error is written to the SAS log.

 The log looks, in part, like this: 

ERROR: FEMALE SUBJECT ERROR: Subject too young for study
Name=Joyce Sex=F Age=11 Height=51.3 Weight=50.5 _ERROR_=1 _N_=11
ERROR: MALE SUBJECT ERROR: Subject too old for study
Name=Philip Sex=M Age=16 Height=72 Weight=150 _ERROR_=1 _N_=15
ERROR: MALE SUBJECT ERROR: Subject too old for study
Name=Ronald Sex=M Age=15 Height=67 Weight=133 _ERROR_=1 _N_=17
ERROR: MALE SUBJECT ERROR: Subject too old for study
Name=William Sex=M Age=15 Height=66.5 Weight=112 _ERROR_=1 _N_=19
NOTE: There were 19 observations read from the data set SASHELP.CLASS.
NOTE: The data set WORK.VETTED_CLASS has 15 observations and 5 variables.

When you execute the ERROR statement, SAS sets the _ERROR_ automatic variable to 1, causing it to dump the contents of the Program Data Vector to the SAS log.  That is why you see the values of the “errant” observation in the SAS log.

Note that you do not have to delete “errant” observations as per the example.  (Without the DELETE statement, those “erroneous” observations would be written to the output SAS data set).  Maybe you simply wanted to flag certain conditions and have a custom message written to the log.  You would still use the ERROR statement, but maybe soften the text of the message that follows.  Perhaps something like “NOTE: ….”, or “WARNING:…”, or “DID YOU KNOW THAT:…” would suffice.  Perhaps…
Best of luck in all of your SAS endeavors!

----MMMMIIIIKKKKEEEE

(aka Michael A. Raithel)
Excerpt from the book:  Did You Know That?  Essential Hacks for Clever SAS Programmers


I plan to post each and every one of the hacks in the book to social media on a weekly basis.  Please pass them along to colleagues who you know would benefit.

Monday, February 22, 2016

Hack 2.3 Creating Custom Log Messages with the PUTLOG Statement


SAS Programming Professionals, 

Did you know that you can create your own custom messages and have them written to the SAS log? 

Custom messages can be written to the log in a DATA step via the PUTLOG statement.  The PUTLOG statement comes in handy when you want to flag specific issues with the values of variables within an observation.  For example, consider this program: 

data vetted_class;
set  sashelp.class; 

if age < 12 then do; 

      putlog 'MY_WARNING: This subject too young for study: '
              name 'age= ' age '.';
      putlog 'MY_WARNING: Subject deleted from vetted data set.';
      putlog ' ';
      delete;
end; 

run;

In this example, we want the VETTED_CLASS data set to contain only subjects who are 12 years of age or older.  The IF statement is used to delete observations that do not meet that criteria.  However, without a warning message in the log, there is no audit trail of the subjects that were deleted and the age that disqualified them. 

The first PUTLOG statement prints a warning message along with the name and age.  The second PUTLOG statement simply prints a warning message.  The third PUTLOG message prints a blank line for better readability in cases where there are many rejected subjects. 

The SAS log for this program looks like this: 

1    data vetted_class;
2    set  sashelp.class;
3
4    if age < 12 then do;
5
6        putlog 'MY_WARNING: This subject too young for study: ' name 'age= ' age '.';
7        putlog 'MY_WARNING: Subject deleted from vetted data set.';
8        putlog ' ';
9        delete;
10
11   end;
12
13   run; 

MY_WARNING: This subject too young for study: Joyce age= 11 .
MY_WARNING: Subject deleted from vetted data set.

MY_WARNING: This subject too young for study: Thomas age= 11 .
MY_WARNING: Subject deleted from vetted data set.

NOTE: There were 19 observations read from the data set SASHELP.CLASS.
NOTE: The data set WORK.VETTED_CLASS has 17 observations and 5 variables.
NOTE: DATA statement used (Total process time):
      real time           0.01 seconds
      cpu time            0.01 seconds

Judicious use of the PUTLOG statement can add that extra layer of QC that helps to make you one of your organization's top SAS programmers!
Best of luck in all of your SAS endeavors! 

----MMMMIIIIKKKKEEEE

(aka Michael A. Raithel)
Excerpt from the book:  Did You Know That?  Essential Hacks for Clever SAS Programmers

I plan to post each and every one of the hacks in the book to social media on a weekly basis.  Please pass them along to colleagues who you know would benefit.

Thursday, February 18, 2016

Hack 2.2 Creating a Subset of a SAS Data Set for Testing


SAS Programming Professionals,

Did you know that you can effortlessly create a small subset from a large SAS data set for testing purposes?

The FIRSTOBS and OBS SAS data set options can be used to slice-n-dice a group of observations from within a SAS data set so they are the only ones written to an output data set.  The FIRSTOBS option specifies the first observation that SAS is to process.  The default is 1.  The OBS option specifies the last observation that SAS is to process.  The default is MAX, which means all observations in a SAS data set are to be processed.

When you specify OBS, SAS performs the following algorithm to return observations:  (OBS – FIRSTOBS) + 1 = the observations returned.

Let’s look at an example:

data cars;
set  sashelp.cars(obs=200 firstobs=151);
run;

In the example, we need an extract of the CARS data set, which contains 428 observations,  to test our new program.  So, we create the CARS data set in the SAS WORK library with 50 observations in it.  We specified that all of the observations in SASHELP.CARS between 151 and 200, inclusive, be written to our new CARS data set.  The log looks like this:

1    data cars;
2    set  sashelp.cars(obs=200 firstobs=151);
3    run;

NOTE: There were 50 observations read from the data set SASHELP.CARS.
NOTE: The data set WORK.CARS has 50 observations and 15 variables.
NOTE: DATA statement used (Total process time):
      real time           0.01 seconds
      cpu time            0.01 seconds

So we now have a happy, healthy extract data set that we can use to develop our new program!

Best of luck in all of your SAS endeavors!

----MMMMIIIIKKKKEEEE
(aka Michael A. Raithel)

Excerpt from the book:  Did You Know That?  Essential Hacks for Clever SAS Programmers

I plan to post each and every one of the hacks in the book to social media on a weekly basis.  Please pass them along to colleagues who you know would benefit.

Monday, February 15, 2016

Hack 2.1 Calculating a Person’s Age in Years

SAS Programming Professionals,

Did you know that you can easily calculate a person’s age in years?

The optional AGE argument for the YRDIF function allows you to calculate a person’s age in years.  The AGE argument takes all of the leap years into account as it determines the number of years between a birthdate and another date.  Here is an example:

data mikeage;

bdate = "27APR1975"D;

CurrentAge = int(yrdif(bdate, today(), 'AGE'));

put "Michael's current aqe is:  " CurrentAge;

run;

In the example, we obtain the subject’s birthdate in the BDATE variable.  Then, we use the YRDIF function with the AGE argument to calculate how old the subject is as of today.  The log looks like this:

1    data mikeage;
2
3    bdate = "27APR1975"D;
4
5    CurrentAge = int(yrdif(bdate, today(), 'AGE'));
6
7    put "Michael's current aqe is:  " CurrentAge;
8
9    run;

Michael's current age is:  40

Note that we used the INT function to return an integer representation of the subject’s age.  Not doing so would have resulted in an age of 40.78630137 which, I am sure you will agree, is not quite so meaningful.

Best of luck in all your SAS endeavors!

----MMMMIIIIKKKKEEEE
(aka Michael A. Raithel)

Excerpt from the book:  Did You Know That?  Essential Hacks for Clever SAS Programmers

I plan to post each and every one of the hacks in the book to social media on a weekly basis.  Please pass them along to colleagues who you know would benefit.