Instead of performing multiple separate PROC FREQ
procedures on a very large data set, I'd like to improve efficiency by performing a single PROC FREQ
with multiple TABLE
statements. Our QA process requires table titles which is simple with a single TABLE
statement using a single TITLE
statement, but is this possible with multiple TABLE
statements?
Take the example data and code below:
DATA TEST;
INPUT TEMPERATURE HUMIDITY PLATE FORM $12.;
DATALINES;
25 75 1 HOT
30 75 2 COLD
25 45 3 HOT
30 45 4 COLD
25 55 5 HOT
30 55 6 COLD
25 15 7 HOT
30 15 8 COLD
;
RUN;
** SINGLE PASS ON PROC FREQ **;
PROC FREQ DATA = TEST;
TITLE1 "TEMPERATURE FREQS";
TABLE TEMPERATURE / LIST OUT=FREQS_TEMP;
TITLE2 "HUMIDITY FREQS";
TABLE HUMIDITY / LIST OUT=FREQS_HUM;
TITLE3 "PLATE FREQS";
TABLE PLATE / LIST OUT=FREQS_PLATE;
TITLE4 "FORM FREQS";
TABLE FORM / LIST OUT=FREQS_FORM;
RUN;TITLE1;TITLE2;TITLE3;TITLE4;
The titles stack on top of one another at the very top of the output rather than each table, so is something like this possible in the data step or does a custom template have to be created? Could PROC REPORT
be a more viable option for custom frequencies?
One option, which is a bit of work but could be worth it if the dataset is very large, is to use proc document
. I figure this is around the same amount of work that would go into outputting frequencies into separate tables and then doing a report or freq on those separately, and a bit less messy.
PROC DOCUMENT
lets you edit the output object and then replay it. In your case, what you're missing in the freq is page breaks between tables - SAS only puts a title
on the page header, so you don't get it between tables. I think PROC FREQ also doesn't create any tables until run
, so the first three title statements don't do anything (yours do only because you use titel1/2/3/4 - if you used title
each time, only the fourth would take effect).
You need to first add page breaks, then add the titles (you don't keep them unfortunately from the PROC FREQ, so you can take them out of that). So:
*ODS DOCUMENT creates the DOCUMENT object you will later modify;
ods document name=freqs(write);
** SINGLE PASS ON PROC FREQ **;
PROC FREQ DATA = TEST;
TITLE "TEMPERATURE FREQS";
TABLE TEMPERATURE / LIST OUT=FREQS_TEMP;
TITLE "HUMIDITY FREQS";
TABLE HUMIDITY / LIST OUT=FREQS_HUM;
TITLE "PLATE FREQS";
TABLE PLATE / LIST OUT=FREQS_PLATE;
TITLE "FORM FREQS";
TABLE FORM / LIST OUT=FREQS_FORM;
RUN;
title;
ods document close;
*PROC DOCUMENT is an interactive proc, so it stays active until QUIT;
proc document name=freqs;
*Just a look at what it looks like under the hood - can be removed in production;
list/levels=all;
run;
*Here we create page breaks (OBPAGE command) after each table.;
obpage \Freq#1\Table1#1\OneWayFreqs#1 /after;
obpage \Freq#1\Table2#1\OneWayFreqs#1 /after;
obpage \Freq#1\Table3#1\OneWayFreqs#1 /after;
*Here we add the titles.;
obtitle \Freq#1\Table1#1\OneWayFreqs#1 "TEMPERATURE FREQS";
obtitle \Freq#1\Table2#1\OneWayFreqs#1 "HUMIDITY FREQS";
obtitle \Freq#1\Table3#1\OneWayFreqs#1 "PLATE FREQS";
obtitle \Freq#1\Table4#1\OneWayFreqs#1 "FORM FREQS";
*And here we replay the document with the changes;
replay ^;
run;
quit;