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

 

January

The vi editor is a efficient screen-oriented text editor and can be found on most Unix and Linux systems. It has a keyboard-driven interface. If you do not know it and it is available, try it -- there is a lot of information about it on the internet.

Occassionally when a program is opened there are tabs in code which usually makes the file difficult to read. If the program is opened within the vi editor use the following command to change a tab character to two spaces:

  :%s/\t/  /g

Hope this helps.

February

Recently was working on a system running a SAS program. Some weird data was appearing after a MERGE statement and inside a datastep -- a new derived variable in a second dataset had values of 'A', 'B', and 'C' but there was an unexpected value of 'D' present after the merge. Nothing was appearing in the SAS LOG.

After some investigation it was found that the variable name existed in both datasets, the original and the newly derived dataset. It was the fact that both datasets had the same variable that was causing the weird situation.

So how do we get SAS to tell us of a possible issue where there is the same variable in both datasets using the MERGE statement and that variable is not in the BY statement? Meet the SAS option MSGLEVEL which has two values:

  • N: prints notes, warnings, and error messages only. This is the default.
  • I: prints additional notes pertaining to index usage, merge processing, and sort utilities along with standard notes, warnings, and error messages.

To give some more detail as to when MSGLEVEL equals I, see below (reference SAS documentation):

  • writes informative messages to the SAS log about index processing.
  • writes a warning to the SAS log whenever a MERGE statement would cause variables to be overwritten.
  • writes a message that indicates which sorting product was used.

It is this second part, the "writes a warning to the SAS log whenever a MERGE statement would cause variables to be overwritten." that would have shown that the variable was being overwritten but was hidden.

Here is an example:

  data one;
    input subjid $ grp $ age;
    cards;
  C2451 A 21
  C2452 B 45
  C2453 C 52
  C2454 D 64
  ;
  run;

  *Recalculated GRP variable;
  data two;
    input subjid $ grp $;
    cards;
  C2451 C
  C2452 B
  C2453 A
  ;
  run;

  options msglevel=n;
  run;
  data both;
    merge one two;
    by subjid;
  run;

When this is run there is no indication that the variable GRP is in both datasets. If we change the MSGLEVEL settion to 'I' we will get something similar to that below:

  options msglevel=i;
  run;
  data both;
    merge one two;
    by subjid;
  run;

  INFO: The variable VAR on data set WORK.ONE will be over written by data set WORK.TWO.

Hope this helps.

March

PROC MEANS and PROC SUMMARY, among others, can count the number of items in a dataset so both are available. Note I said 'items', not 'records' or 'observations'. Why the difference. Lets looks at a dataset and a PROC MEANS call:

  data one;
    input subjid $ age;
    infile cards missover;
    cards;
  M2522 16
  M2561 20
  M2562
  M2565 43
  ;
  run;

Running PROC MEANS produces the following:

  proc means data=one noprint;
    var age;
    output out=rslt (drop=_type_) n=n;
  run;

  proc print data=rslt;
  run;

  *** OUTPUT ***
  
  OBS  _FREQ_  n

    1       4  3

n=3, _FREQ_=4, why the difference? n counts the number of non-missing values while _FREQ_ gives the number of records.

Hope this helps.

April

With OPTIONS MPRINT, MLOGIC and SYMBOLGEN a lot can be sent to the SAS LOG including what SAS statements were used, what values were used in macro variables, among many other things. But what about the code if it is included in a %INCLUDE call? Come to the rescue the SOURCE2 option. This can be called two ways, either as:

  options source2;
  %include "../../macros/isodate.sas";
  run;

or

  %include "../../macros/isodate.sas" /source2;
  run;

Hope this helps.

May

How many of us use the following to print out a macro variable value to the SAS LOG:

  %put mvar=&mvar;

to print out a value to the SAS LOG? Since 9.3 there has been another way to write this so you need only print the macro variable out out once:

  %put &=mvar;

Cleaner and more easier code to write.

Hope this helps.

June

Lets look at a datastep below:

  data one;
    input subjid $ age;
    infile cards;
    cards;
  M2522 16
  M2561 20
  M2562
  M2565 43
  ;
  run;

A PROC PRINT produces the following:

  subjid  age

  M2522   16
  M2561   20
  M2562    .

Why not all data? There are two important INFILE statement options that control how data is read, MISSOVER and FLOWOVER, details of these which are:

  • FLOWOVER: causes an INPUT statement to continue to read the next input data record if it does not find values in the current input line for all the variables in the statement. This is the default behavior of the INPUT statement.
  • MISSOVER: prevents an INPUT statement from reading a new input data record if it does not find values in the current input line for all the variables in the statement. When an INPUT statement reaches the end of the current input data record, variables without any values assigned are set to missing.

If we do the following, only changing the INFILE statement as shown below:

  data one;
    input subjid $ age;
    infile cards MISSOVER;
    cards;
  M2522 16
  M2561 20
  M2562
  M2565 43
  ;
  run;

the PROC PRINT produces the following:

  subjid  age

  M2522   16
  M2561   20
  M2562    .
  
  data one;
    input subjid $ age;
    infile cards;
    cards;
  M2522 16
  M2561 20
  M2562
  M2565 43
  ;
  run;

A PROC PRINT produces the following:

  subjid  age

  M2522   16
  M2561   20
  M2562    .
  M2565   43

There are other ways of bringing data in using the CARDS statement to make help read it in correctly, but that is for another day.

Moral of the story, know your data.

Hope this helps. See you next month.

July

After much thought I am giving up writing the Tip of the Month for now. After starting this venture in 2003 my heart is just not in this. Maybe sometime in the future I will restart this.

Until then, take it easy -- every day learn something new.