SAS procedures can produce a lot of output, but you don't always want to see it all. In simulation and bootstrap studies, you might analyze 10,000 samples or resamples. Usually you are not interested in seeing the results of each analysis displayed on your computer screen. Instead, you want to write the results to an output data set so that they can be further analyzed. Thus it is useful to know how to suppress the ODS tables (and graphics!) that ordinarily appear on the screen (and other ODS destinations).
I have previously written about the importance of turning off ODS when running simulations. There are three ways to suppress ODS output in a SAS procedure: the NOPRINT option, the ODS EXCLUDE statement, and the ODS CLOSE statement. This article compares the various ways in terms of efficiency, ease of use, and portability. Some of this material is taken from Chapter 6 (p. 97-100) of Simulating Data with SAS (Wicklin, 2013).
The NOPRINT option
About 50 procedures in SAS/STAT support a NOPRINT option in the PROC statement. Additional procedures in Base SAS, SAS/ETS, and other products also support this option. The NOPRINT option is useful when the procedure supports an OUTPUT statement, an OUT= option, an OUTEST= option, or some other syntax for producing an output data set that contains statistics that you want.
The NOPRINT option is the most efficient way to suppress output because it tells SAS procedures (through the grammar) not to produce any tables or graphs. That means that the procedure can optimize—or even skip!—certain computations. The NOPRINT option tells the procedure that the only statistics needed are those that are sent to the output data set. In some cases the procedure can run faster because it can skip certain computations.
The following example uses the NOPRINT option to suppress output to any ODS destination. The OUTP= option creates an output data set that contains the correlation coefficients between all numerical variables in the Sashelp.Cars data for each of the 38 values of the categorical variable Make:
proc corr data=sashelp.cars outp=OutCorr NOPRINT; by make; /* no VAR stmt ==> use all numeric variables */ run;
For this example, the output data set does not contain any p-values for the null hypothesis that the correlation coefficient equals zero. Therefore the procedure can skip the computation of those p-values. In contrast, p-values are computed and shown by default when PROC CORR produces its usual "PearsonCorr" table, which includes the Pearson correlation coefficients.
The ODS EXCLUDE statement
Unfortunately, not all procedures support the NOPRINT option. Furthermore, data sets that are created by using the OUTPUT statement or an OUT= option do not contain all statistics that can be produced by a procedure. If the numbers that you need are only available in a table, then you cannot use the NOPRINT option.
Instead, you should use ODS to suppress output to all open destinations while also using ODS to create an output data set from the table that contains the numbers that you need. You can use the ODS EXCLUDE statement to suppress output. Then you can use the ODS OUTPUT statement to specify the name of the ODS table (or tables) that you want to capture and the name of the data set that will contain the values in the table. Notice that ODS EXCLUDE does not close a destination, it merely prevents the destination from receiving output objects.
Is ODS EXCLUDE equivalent to the NOPRINT option? No. The procedure has no idea whether any ODS destinations are open. It computes all of the tables and graphics for the analysis, and then hands them off to ODS. ODS manages the output, which in this case means "throwing away" all the tables and graphs that were excluded, and only sending the non-excluded tables to their destination.
I like to use the %ODSOff and %ODSOn macros (and sometimes OPTIONS NONOTES) to suppress the output. However, to focus the discussion on the ODS EXCLUDE statement, the following statements explicitly show the ODS statements that are used to control the output. The following call to the TTEST procedure performs 38 t tests, one for each value of the Make variable. Each test is a one-sided t test of the null hypothesis that the mean value of the MPG_City variable is greater than 20.
Prior to calling the TTEST procedure, the ODS GRAPHICS OFF statement turns off the creation of graphics for subsequent procedure calls. The ODS EXCLUDE ALL statement suppresses all output to all ODS destinations. When the TTEST procedure runs, it creates all its usual tables, but ODS throws away most of them. The exception is the "TTests" table, which ODS sends to the OUTPUT destination. The result is an output data set named OutTTest. After the procedure runs, ODS EXCLUDE NONE tells SAS that future ODS objects should be sent to all open destinations.
ods graphics off; /* or use the %ODSOff macro */ ods exclude all; /* suspend all open destinations */ /* perform one-sided t test H0: mean(MPG_City) > 20 */ proc ttest data=Sashelp.Cars h0=20 sides=u; by make; var MPG_City; ods output TTests=OutTTest; /* open the OUTPUT destination; select one table */ run; ods exclude none; /* or use the %ODSOn macro */ proc print data=OutTTest; where probt ^=. & probt < 0.05; run;
The PROC PRINT statement displays the vehicle brands for which the mean fuel efficiency is significantly greater than 20 miles per gallon at the 0.05 significance level. The brands in the list are known for producing small fuel-efficient vehicles.
An equivalent syntax is to use ODS SELECT instead of ODS EXCLUDE. To temporarily suppress ODS output, you create an "ODS sandwich": use ODS SELECT NONE before calling a procedure, and use ODS SELECT ALL when you want to resume sending output to the suspended destinations.
The ODS CLOSE statement
The ODS CLOSE statement is used to close files (HTML, PDF, RTF,...) that contain tabular and graphical output from SAS procedures. I see many programmers use ODS _ALL_ CLOSE as a way to suppress output, but I do not recommend that you use the ODS CLOSE statement for this purpose. This post is already a little long, so I will postpone the discussion of ODS CLOSE for a future article.
Can you combine NOPRINT and ODS OUTPUT?
SAS programmers crave efficiency. Upon reading that the NOPRINT option can make a procedure run faster, the ambitious programmer might attempt to run a procedure with the NOPRINT option but use the ODS OUTPUT statement to capture the results of one table. Sorry, friend, but you can't do that. The NOPRINT option means that no ODS tables are created, so there is no way to select a table and save it to a data set. For example, the following call to PROC REG uses the NOPRINT option. The ODS OUTPUT option tries to create an output data set from the "ParemeterEstimates" table, but it results in the following WARNING message:
proc reg data=sashelp.class NOPRINT; model weight = height age; ods output ParameterEstimates=PE; /* WRONG: no ODS table created */ quit;
WARNING: Output 'ParameterEstimates' 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.
The WARNING message is very instructive. It gives several possible reasons why the output data set was not created. The use of the NOPRINT option is one of those reasons.
- If a procedure supports the NOPRINT option AND can create an output data set that contains the statistic that you need, use this combination of options. Check the procedure documentation to see what statistics are supported by the OUTPUT statement, the OUT= option, the OUTEST= option, and so forth.
- If the statistic that you need is available only in an ODS table, or if the procedure does not support the NOPRINT option, use the ODS EXCLUDE ALL statement to suppress output from all open destinations. Use the ODS OUTPUT statement to specify tables that you want to save to SAS data sets. In this situation, I also recommend that you specify ODS GRAPHICS OFF or use the %ODSOff and %ODSOn macros.
- Do not use ODS _ALL_ CLOSE to close all destinations. Although this does prevent future ODS output from appearing, the ODS EXCLUDE technique is more portable and easier to implement, as I will discuss in a future article.