Wednesday, July 14, 2010

Delete observations when all variabls are missing

It is a common question.

With the new function CMISS in 9.2, we can perform the task in ONLY one DATA step.
Please see the sample code at below:

data raw;
output; * obs with missing values;
a=1; b='2'; c=.;
output;
run;

data output;
set raw;
array aa {*} $ _character_;
array nn {*} _numeric_;

if cmiss(of _all_) = (dim(aa)+dim(nn)) then delete;
run;

Monday, July 5, 2010

Quick tip: %EVAL

Essentially, the value of all macro variables is character string.

Sometimes, we do need that macro variable has only numeric value.
We can use %EVAL to judge if the string is numeric value.


* Sample;
%let mv=1+a;

%let a=%eval(%scan(&mv, 1, +));
%let b=%eval(%scan(&mv, 2, +)); * Error occurs;

Thursday, June 3, 2010

How to identify the header of ACROSS columns in PROC Report

When one across item is used with >1 analysis items, the header text of the across item will affect all. To use different header text, we have to specify an alias for the across item.
Below are the sample codes:

* Default;
proc report data=sashelp.class nowd;
column sex,height sex,weight;
define sex / across;
define height / analysis mean;
define weight / analysis mean;
run;

* To use alias for the across item;
proc report data=sashelp.class nowd;
column sex,height (sex=sex_alias),weight;
define sex / across "Height";
define sex_alias / across "Weight";
define height / analysis mean " ";
define weight / analysis mean " ";
run;

Monday, May 10, 2010

How to compare two strings?

Are you still using LEFT(UPCASE(...)) =: "XXXX"?

Stop it.
In SAS 9, we can use the function COMPARE. With the modifiers ("i", "l", ":"), we can handle the string comparison easily.

* COMPARE function Demo;
data _null_;
var = " This is test";
if left(upcase(var)) =: 'THIS' then put "Matched (1)";
if compare(var, 'THIS', 'il:') = 0 then put "Matched (2)";
run;

Wednesday, April 21, 2010

Re: Resolve a macro variable within single quotes

Frankly, it is a dup with new SAS sample code at http://support.sas.com/kb/25/076.html.
However, the sample looks not good. It seems that the author do not know exactly the macro quoting functions (%str, %nrbquote, and etc.).

With the code at below, the reader can get the meaning of macro quoting better.

%let name=Fred;

/* resolve the MV at compilation time */
%put %str(%'&name%');

/* resolve the MV at execution time */
/* Please use %nrbquote or %bquote, NOT %quote. */
%put %unquote(%nrbquote('&a'));

Thursday, April 1, 2010

Special permanent libraries: USER/LIBRARY

We all know that SAS has two kinds of library: permanent library and temporary WORK library. However, do you know that there are still two special permanent libraries?

USER:
When it exists, all datasets reference with a one level name will be written to the the permanent USER library instead of the temporary WORK library.

For the convenience of debugging, I suggest we can miss "WORK." when reference dataset.

Note: system option USER has the same effect.

LIBRARY:
In FMTSEARCH, there are ALWAYS two implicit format catalogs: WORK.FORMATS and LIBRARY.FORMATS. If they do not appear in FMTSEARCH= list, they will be searched at first.

Friday, March 19, 2010

Regex search in enhanced editor

Every one has its own habit.

I always edit text in Ultraedit. I like the Regex search/replace functionality in Ultraedit so much as I maintain a list of common Ultraedit-style Regex string.

I know that SAS enhanced editor must have this functionality. However, I got no information for Regex grammar from SAS online doc.

Today, I find the Regex magic box incidentally. :)

Wednesday, March 17, 2010

NOTE: MERGE statement has more than one data set with repeats of BY values

First, the message reminds the user that it is MANY-to-MANY merge in DATA step.

Most SAS progammers are used to ONE-to-ONE or ONE-to-MANY merge since it is easy to understand. When MANY-to-MANY merge occur, the programmer should pay more attention on the data itself.

To perform MANY-to-MANY merge, there are two popular SAS techniques: DATA step and PROC SQL. It should be noted that PROC SQL do not issue the reminder message in MANY-to-MANY merge. Furthermore, it will create a different dataset with the result of DATA step.

Therefore, I suggest that we should perform merge using DATA step.

Sunday, March 14, 2010

To export dataset to excel with label

When we export SAS dataset to excel, we mostly do not like the actual variable name as column name in excel. Alternatively, variable label is more popular.
To export the label before SAS 9.2, we have to use LIBNAME with excel engine since it have many fine options to tune the output, e.g. DBLABEL, DBTYPE etc.

However, when the sheet is existing at that time, they can not be replaced automatically. That means you have to clean the file in advance.

In SAS 9.2, a new options is introduced: LABEL option in PROC EXPORT. The new option allow the output excel take label. Furthermore, PROC EXPORT support REPLACE functionality, that means we may avoid the code to clean the file.

Thursday, February 4, 2010

Scheduler for asynchronous script processing

As a IT programmer, we have to handle scripts on many platforms, e.g. DOS, ksh.
Due to limited functionality of script language, it is not easy to schedule many scripts to let them run step by step.

With SAS, we can take it easily.
I strongly recommended SAS programmer should use SYSTASK and WAITFOR to control the script processing.
By contrast, X is suitable for interactive task.

Below are codes from SAS online doc:

systask command "sas myprog1.sas" taskname=sas1;
systask command "sas myprog2.sas" taskname=sas2;
systask command "sas myprog3.sas" taskname=sas3;
waitfor _all_ sas1 sas2 sas3;

Tuesday, January 19, 2010

PIPE mode in external file functions

To get the output of shell command within SAS, we have to resort to PIPE.
Generally the job is using DATA step input/output.
We can also use external file funcitons to handle it, although it is more complex.


%let command = hostname;

data _null_;
length value $ 20;
rc = filename('myfile', "&command", 'PIPE');
fid = fopen('myfile', 'S');
rc = fread(fid);
rc = fget(fid, value, 20);
rc = fclose(fid);
rc = filename('myfile');

put "Command output:" value;
run;

%let filerf=myfile;
%let rc = %sysfunc(filename(filerf, &command, pipe));
%let fid = %sysfunc(fopen(&filerf, S));
%let rc = %sysfunc(fread(&fid));
%let rc = %sysfunc(fget(&fid, value, 20));
%let rc = %sysfunc(fclose(&fid));
%let rc = %sysfunc(filename(filerf));

%put Command output: &value;