SAS tip: Put ODS statements inside procedures


The SAS Output Delivery System (ODS) enables you to manage and customize tables (and graphics!) that are created by SAS procedures. I like to use the ODS SELECT statement to display only part of the output of a SAS procedure. For example, the UNIVARIATE procedure produces five tables by default, but I do not always want to see all of the output, so I use an ODS SELECT statement to select a subset of tables, as shown in the following statements:

ods select BasicMeasures; /* Danger: ODS statement outside PROC statement */
proc univariate data=Sashelp.Class;
  var Height;

There is actually a subtle problem with the previous statements: if the ODS statement follows a call to an interactive procedure, the ODS statement might not work as you intended!

An interactive procedure remains active after submitting a series of statements. In Base SAS, interactive procedures include the DATASETS and SQL procedures. In SAS/STAT software, the ANOVA, GLM, and REG procedures are examples of interactive procedures. PROC IML is also an interactive procedure. For most interactive procedures, you execute statements by submitting a RUN statement. PROC IML is unusual in that you do not need a RUN statement in order to execute SAS/IML statements.

Interactive procedures remain running until you submit a QUIT statement, or until you submit a new PROC or DATA step. This can lead to the following situation, in which SAS tries to associate an ODS statement with the procedure that is currently running:

proc iml;
x = 1:10; /* generate some data */
create Temp var {x}; append; close Temp; /* write data to WORK.TEMP */
/* no QUIT statement, so PROC IML is still running */
ods select BasicMeasures; /* Wrong! ODS statement applies to PROC IML */
proc univariate data=Temp;
  var x;
WARNING: Output 'BasicMeasures' was not created.  Make sure that the output object name, label,
         or path is spelled correctly.  Also, verify that the appropriate procedure options are
         used to produce the requested output object.  For example, verify that the NOPRINT
         option is not used.

PROC IML does not exit until SAS encounters the PROC UNIVARIATE statement. Therefore, the ODS SELECT statement applies to the PROC IML step, not to PROC UNIVARIATE. SAS displays a WARNING in the Log because PROC IML never created a table named BasicMeasures.

There are two ways to ensure that SAS does what you intend. The first is to terminate interactive procedures explicitly by using a QUIT statement. The second way is to always put ODS statements inside a procedure (that is, after the PROC statement). For example, the following statements always work, regardless of whether they follow a call to an interactive procedure:

proc univariate data=Sashelp.Class;
  ods select BasicMeasures; /* Always correct: ODS statement inside PROC */
  var Height;

This is a programming tip that is easy to implement, and I recommend that you adopt this convention in your own programs.

For more examples of how interactive procedures differ from their non-interactive cousins, see the SAS usage note about interactive procedures.


About Author

Rick Wicklin

Distinguished Researcher in Computational Statistics

Rick Wicklin, PhD, is a distinguished researcher in computational statistics at SAS and is a principal developer of SAS/IML software. His areas of expertise include computational statistics, simulation, statistical graphics, and modern methods in statistical data analysis. Rick is author of the books Statistical Programming with SAS/IML Software and Simulating Data with SAS.

1 Comment

  1. Pingback: Point/Counterpoint: Where should you put ODS SELECT and ODS OUTPUT statements? - The DO Loop

Leave A Reply

Back to Top