Question: is there a way to just get the ODS table names from a PROC without running the program up to that point with ods trace on?
Background: I often need to output an ODS data set from a PROC, but the only method I know of to get the list of available data sets is to insert
ods trace on;
before the PROC, then run the program, then review the log file to find the appropriate data set name, then insert my ods output statement, and re-run.
In a time-consuming program, that process can take a lot of time, and it just seems inefficient to have to run a program in order to figure out how to continue programming.
I can't find any SAS documentation that lists the available ODS tables by PROC, but if something like that exists, that would be a great answer to this question. I know the ODS output tables vary depending on which options are specified, but it still seems like a comprehensive list could be compiled, with notes about whether each table is dependent on PROC-specific options.
I'd also love it if there were something like a meta-PROC where a PROC name could be specified, and the ODS table names are returned, without running any other code.
There is a compilation in the SAS doc. This is for 9.4, but there is one in all the versions.
http://support.sas.com/documentation/cdl/en/odsug/66611/HTML/default/viewer.htm#p0mnbijm0t6w1cn1dpf3q5suxk4u.htm
You can run it with options obs=1; (just reset to obs=max later) if the output procedure is capable of running with zero observations (in general, if you're not doing any programmatic code generation, this is probably the case). You can also likely create a test procedure run that does not use your actual data (although that depends on what you're doing). (You cannot use obs=0, as that would produce no output.)
For example:
options obs=1;
ods trace on;
proc freq data=sashelp.class;
run;
ods trace off;
options obs=max;
You also may be able to determine the names from the installed templates, if it is a procedure that uses templates. For example, PROC FREQ does.
Bring up the Results explorer, and right click on the "Results" node up at the top. Select "Templates". That opens the Template explorer. Then look about for your procedure. Most of the statistical procedures are in Sashelp.Tmplstat. FREQ is not, however; it is in Sashelp.Tmplbase, under Base.Freq. Each of the PROC FREQ entries that starts with define table ... is a separate ODS table; the primary ones for PROC FREQ are Onewayfreqs and CrosstabFreqs, but generally all of the ones with a similar icon to those are tables (the blue ones are dynamic variables).
For PROC REG, for example, it is in the SASHELP.tmplstat folder (SASHELP.tmplstat.Reg), and has a few dozen tables available to see, generally with logical names. Not every table is produced from every run (it depends on what you ask for and what the PROC decides is needed), and I'm not sure every single one is available to intercept via ODS, but most of them are.
Related
I have a problem with the legend not being visible at cross tabulation in porc freq in SAS. How can I show it?
I see only a table:
But I want to also see a legend:
PROC FREQ does not have a legend per se, but you can use the title statement to put some information there, or footer.
If you want better control, use PROC TABULATE which has substantial ability to customize the output, including the box option which places whatever information you want in the top-left corner of the table.
If you run the following:
proc template;
source Base.Freq.CrossTabFreqs;
run;
Then check your log, you should see:
define crosstabs Base.Freq.CrossTabFreqs;
notes "Crosstabulation table";
cellvalue Frequency Expected Deviation CellChiSquare TotalPercent Percent RowPercent ColPercent CumColPercent;
header TableOf ControllingFor;
footer NoObs Missing;
If you do not, that means that someone has modified your PROC FREQ base template and that's why it's not showing. In this case you would need to replace your default SAS installation templates by obtaining clean copies from a different source. It may also need to align with your SAS version.
If you have a colleague or different SAS installation that is operating as expected, you can run the PROC TEMPLATE above, then copy the code from the log and re-create the template as:
proc template;
<insert copied code from log>;
run;
And you probably realize, but this is why modifying templates is generally a last resort for customizing data/output and usually you should never modify the default templates.
SAS has several forms it uses to create output data sets from within a procedure. It is not always clear whether or not a particular procedure can generate a data set and, if it seems to be able to, it's not always clear how.
Off the top of my head, here are some examples of how widely the syntax can differ.
Example 1
proc sort data = sashelp.baseball out = baseball_sorted;
by
league
division
;
run;
Example 2
proc means noprint data = baseball_sorted;
by
league
division
;
var nHits;
output
out = baseball_avg_hits (drop = _TYPE_ _FREQ_)
mean = mean_hits
;
run;
Example 3
ods exclude all;
ods output
statistics = baseball_statistics
equality = baseball_ftest
;
proc ttest data = baseball_sorted;
class league;
var nHits;
run;
ods exclude none;
Example 4
The PROC ANOVA OUTSTAT= option.
It seems almost as if SAS has implemented each of these willy-nilly. Is the SAS syntax dictating how to create a data set directed by some consistent approach I am not seeing or is it truly capricious and arbitrary?
For PROC code, the syntax for outputting data is often specific to that procedure, which often feels willy-nilly. (Your examples 1, 2, 4) I think PROC developers are given a lot of freedom, and remember that many of these PROCS are 30+ years old.
The great thing about the Output Delivery System (ODS, your example 3) is it provides a single syntax for outputting data, regardless of the procedure. So you can use the ODS OUTPUT statement with (almost?) any PROC. The names and structures of the output objects will of course vary between PROCs. So if you are looking for a consistent approach, I would focus on using ODS OUTPUT. ODS was added in V7 (I think).
It would be interesting to try to find an example of an output dataset which could be made by a PROC but could not be made by ODS OUTPUT. I hope there aren't any. If that is the case, you could consider the range of OUTPUT statements/options within PROCs as legacy code.
Agree with Quentin. You have to remember that there are SAS systems out there running code written in the 80s. SAS would have a huge headache if they forced every team to rewrite all the procedures and then forced their customers to change all their code. SAS has been around since the 60s and the organic growth of the syntax is to be expected.
FWIW, having an OUT= statement makes sense on things with no graphical output. I.E. PROC SORT or PROC TRANSPOSE.
The way I see it there are four main ways to specify the output data sets.
In the PROC statement you may be able to specify some type of output statements or options, such as OUT= OUTEST=.
In the main statement of the procedure, ie MODEL/TABLE can have options that allow for output. ie PROC FREQ has an OUT= on the TABLE statement.
An explicit OUTPUT statement within a procedure. These are typically from older procedures. ie PROC MEANS
ODS tables which are relatively newer method, more frequently used these days since the format aligns with what you'd expect to see.
Yes, there are multiple places to check, but fortunately the SAS documentation for procedures is relatively clear with the options and how to use/specify the outputs.
If I've missed anything that seems different post in the comments and I can update this.
PS. Although SAS is definitely bad, trying to navigate different packages/modules in Python to export an XLSX file isn't straight forward either. Some packages support some options others don't. I've given up on asking why these days and just accept it as peculiarities of the different languages at this point.
Good day!
I need a list of libraries-tables on a SAS server with a size of each table and last time, when it was open/used.
I'm not very familiar with SAS, so I don't even know where would I start searching :(
I assume, that there is some simple solution, maybe a proc of some sort, that may help...
You can use proc contents to access metadata about a library in SAS, for example using the sashelp library:
proc contents data = sashelp._ALL_ NODS;
run;
sashelp is the library you are refencing. By specifying _ALL_ you ask SAS for data about all the files in this library (by choosing a singular file such as sashelp.ztc you can get information on jut one file).
This will give you a lot of information, so by using the NODS statement you can suppress the output to give you less detail. The above code will give you the number of files, their type, the level, the file size, and the data they were last modified.
If you want to output this information to a dataset, you have to use the ODS output system with the correct ods table name, in this case it is Members. Furthermore, if you're looking for datasets in particular then you can filter the output with a where= statement:
ods output Members = test (where = (memtype = "DATA"));
proc contents data = work._ALL_ NODS noprint;
run;
ods listing; /* change back to listing output*/
In R I could just write something like model$deviance and model$df.residual, but I can't seem to find any way of doing this in SAS.
Whereas R functions produce an object that has sub-objects that you can extract into a variable, SAS procedures create tables. If you see a statistic in some table that you want to use in another part of your program, you can use the Output Delivery System (ODS) to write that table to a data set, as follows:
1) Use the ODS TRACE ON statement to discover the name of the table (or look it up in the documentation)
2) Use the ODS OUTPUT statement to write the table to a data set.
For example, if you are interested in the many goodness-of-fit diagnostic statistics (including the statistics for deviance and chi-square residuals), you can discover that the "Criteria for Assessing Goodness of Fit" table has the name ModelFit. Therefore, putting
ODS OUTPUT ModelFit=FitStatistics;
inside your PROC GENMOD call will create a data set called "FitStatistics" that contains the statistics you want.
I found this piece of code online
data _null_;
set sashelp.class;
if mod(_n_,5)=0 then
rc = dosubl(cats('SYSECHO "OBS N=',_n_,'";'));
s = sleep(1); /* contrived delay - 1 second on Windows */
run;
I would like to know if you had any idea of how to adapt this piece to a proc sql statement, so I could track the progress of a long query...
For example
proc sql;
create table test as
select * from work.mytable
where mycolumn="thisvalue";
quit;
and somewhere in the statement above we would include the
rc = dosubl(cats('SYSECHO "OBS N=',_n_,'";'));
You wouldn't be able to directly check the progress of a SQL query, unfortunately (if it's operating on SAS datasets, anyway), except by monitoring the physical size of the table (you can do a directory listing of your WORK directory, or depending on how it's building the table, the Utility directory). However, it may or may not be linear; SQL might, for example, use a hash strategy which would not necessarily take up disk space until it was fairly close to being done.
For SQL, you're best off looking at the query plan to tell how long something's going to take. There are several guides out there, such as The SQL Optimizer Project, which explains the _METHOD and _TREE options among other things.