Published on :
Reporting SASHELP

Creating an ODS Tagset to Count Event Frequency

This code is also available in: Deutsch Español Français
The script uses `PROC TEMPLATE` to create a new tagset. This tagset, 'counter', is designed to intercept ODS events. It uses an internal dictionary to store and increment the counter for each event name encountered. At the end of the document (`doc finish` event), it sorts the events in descending order of frequency and prints a simple text report. The script then demonstrates the use of this tagset by applying it to the output of `PROC PRINT` on the `sashelp.class` table, redirecting the counting report to a file 'counter.txt'.
Data Analysis

Type : SASHELP


The script uses the `sashelp.class` table as an example to generate ODS events. This table is not modified; it only serves to trigger the execution of a procedure (`PROC PRINT`) whose events will be counted by the tagset.

1 Code Block
PROC TEMPLATE
Explanation :
This block uses `PROC TEMPLATE` to define a new ODS tagset called `counter`. Tagsets allow fine-grained control over SAS-generated output. This one is programmed to count the occurrences of each ODS event type. It uses dictionaries (similar to hash tables) to maintain the counts. Key events are `doc` (for initialization and finalization), `count` (to increment counters), `sort` (to sort results), and `report` (to display the final report).
Copied!
1/*
2 Tagset to count the frequency of each event and print a report.
3*/
4 
5PROC TEMPLATE;
6define tagset tagsets.counter;
7 default_event = 'count';
8 
9 /*
10 Create an event count dictionary `$events'. Each key in the
11 dictionary is an event name. The value is the number of times the
12 event occurred.
13 
14 At doc start, initialize the event dictionary and the total event
15 counter. At finish, sort the event names by decreasing occurrence
16 and print a report.
17 */
18 define event doc;
19 start:
20 eval $events[event_name] 1;
21 eval $total 0;
22 finish:
23 trigger sort;
24 trigger report;
25 END;
26 
27 define event count;
28 DO / IF $events[event_name];
29 eval $events[event_name] $events[event_name] + 1;
30 ELSE;
31 eval $events[event_name] 1;
32 done;
33 eval $total $total+1;
34 END;
35 
36 /*
37 Create an array `$evname' that contains the event names. Sort
38 `$evname' using the counts in `$events'.
39 */
40 define event sort;
41 trigger dup;
42 eval $size $events; /* $size = size of $events */
43 eval $i $size;
44 DO / while $i > 0;
45 eval $j 1;
46 DO / while $j < $i;
47 eval $jplus1 $j+1;
48 SET $evname_j $evname[$j];
49 SET $evname_jplus1 $evname[$jplus1];
50 DO / IF $events[$evname_j] < $events[$evname_jplus1];
51 SET $temp $evname[$j];
52 SET $evname[$j] $evname[$jplus1];
53 SET $evname[$jplus1] $temp;
54 done;
55 eval $j $j+1;
56 done;
57 eval $i $i-1;
58 done;
59 END;
60 
61 define event dup;
62 iterate $events;
63 DO / while _name_;
64 SET $evname[] _name_;
65 next $events;
66 done;
67 END;
68 
69 /*
70 Print the `$events' dictionary in the order specified by the
71 `$evname' array.
72 */
73 define event report;
74 put "Number of individual events: " $events nl;
75 put "Total number of events: " $total nl nl;
76 put "Count Event name" nl;
77 iterate $evname;
78 DO / while _value_;
79 eval $occur $events[_value_];
80 eval $occur putn($occur, 'F.', 5);
81 put $occur " " _value_ nl;
82 next $evname;
83 done;
84 END;
85 
86 END;
87 
88RUN;
2 Code Block
PROC PRINT
Explanation :
This block applies the previously defined `tagsets.counter` tagset. The ODS `listing` destination is closed, then the `counter` tagset is activated to write to the `counter.txt` file. The execution of `PROC PRINT` on `sashelp.class` generates events that are intercepted and counted by the tagset. Finally, the tagset is closed and the `listing` destination is reactivated.
Copied!
1ods listing close;
2ods tagsets.counter file="counter.txt";
3PROC PRINT DATA=sashelp.class;
4RUN;
5ods tagsets.counter close;
6ods listing;
This material is provided "as is" by We Are Cas. There are no warranties, expressed or implied, as to merchantability or fitness for a particular purpose regarding the materials or code contained herein. We Are Cas is not responsible for errors in this material as it now exists or will exist, nor does We Are Cas provide technical support for it.