Moving this from below thread to avoid confusion but I am trying to add a parameter for the maximum number of unique values for a character variable. If the number of unique values for the variable is less than or equal to the parameter, a frequency analysis is included in the macro presenting data for all unique values of the variable in question. If the number of unique values is large than the parameter, then only most frequent values for the given variable should be displayed. The default value of the parameter I am setting to 5 for now. The code to deal with this is at the bottom of my macro.
The issue I am having is 1) I don't know how to set both sides of the condition (greater or less than) for my third parameter and 2) set my default number within the macro (trying to set to 5). Any help would be wonderful as I am stuck.
%macro codebook(lib=,ds=,maxVal=);
%if &lib= BLANK | &ds = BLANK %then %do;
%put &=lib;
%put &=ds;
%abort;
%end;
ods select variables;
proc contents data=&lib..&ds. out=_contents_ ; run;
proc format;
value tfmt
1 = 'NUM'
2 = 'CHAR';
run;
data _null_;
set _contents_ end=last;
call symput('vname'||strip(put(_n_,best.)), strip(name));
call symput('vtype'||strip(put(_n_,best.)), strip(put(type,tfmt.)));
call symput('vlabel'||strip(put(_n_,best.)), strip(label));
if last then call symput('nVars',strip(put(_n_,best.)));
run;
%do j = 1 %to &nVars.;
title1 "Analysis of &&vlabel&j (Variable=%upcase(&&vname&j.)) ";
%if &&vtype&j=NUM %then %do;
%PUT Condition was Met on &&vtype&j;
proc means data=&lib..&ds.;
var &&vname&j.;
run;
%end;
%else %if &&vtype&j=CHAR %then %do;
proc freq data=&lib..&ds.;
tables &&vname&j./out=freqtab;
run;
%let printALL=YES;
data _null_;
set freqtab;
if _n_ > &maxVal. then
call symput('printAll','NO');
run;
%end;
%end;
%mend;
%codebook(lib=out,ds=adsl,maxVal=4) ;
Do you know how to do it without the macro?
Show the code you would use to limit the output for the variable NAME from the SASHELP.CLASS dataset to 4 values. Then we can help you convert that into something that works inside your macro.
Maybe this:
%macro test2;
ods output nlevels=nlev;
proc freq data=sashelp.class nlevels;
tables name/out=freqtab;
run;
proc sql;
select nlevels into: max_lev from nlev;
quit;
%put &max_lev;
%if &max_lev. >= 10 %then %do;
data a;
set freqtab(obs=10);
run;
%end;
%else %if &max_lev. < 10 %then %do;
data a;
if first.count then ;
set freqtab;
run;
%end;
%mend;
%test2 ;
Something like this. I'll let you fix the titles issue.
%macro codebook(lib=,ds=,maxVal=);
%if &lib= BLANK | &ds = BLANK %then %do;
%put &=lib;
%put &=ds;
%abort;
%end;
ods select variables;
proc contents data=&lib..&ds. out=_contents_ ; run;
proc format;
value tfmt
1 = 'NUM'
2 = 'CHAR';
run;
data _null_;
set _contents_ end=last;
call symput('vname'||strip(put(_n_,best.)), strip(name));
call symput('vtype'||strip(put(_n_,best.)), strip(put(type,tfmt.)));
call symput('vlabel'||strip(put(_n_,best.)), strip(label));
if last then call symput('nVars',strip(put(_n_,best.)));
run;
%do j = 1 %to &nVars.;
title1 "Analysis of &&vlabel&j (Variable=%upcase(&&vname&j.)) ";
%if &&vtype&j=NUM %then %do;
%PUT Condition was Met on &&vtype&j;
proc means data=&lib..&ds.;
var &&vname&j.;
run;
%end;
%else %if &&vtype&j=CHAR %then %do;
ods select none;
ods output nlevels=_nlev;
proc freq data=&lib..&ds. NLEVELS;
tables &&vname&j./out=freqtab;
run;
ods select all;
proc sql noprint;
select nlevels into :nLevels from _nlev;
quit;
%if &nLevels <= &maxVal %then %do;
proc print data=freqtab label;
run;
%end;
%else %do;
ods text = "Too many levels for &&vname&j." ;
%end;
%end;
%end;
%mend;
%codebook(lib=sashelp,ds=cars,maxVal=4)
thanks! Just saw this right after I posted mine 🙂
So I've implemented and tested but for some reason the output stops with the first variable in loop (and no errors). The proc freq additions at the bottom worked outside the macro for me. I am also trying to get the number of levels to not display in each print out (only output the data so I can grab the nLevels). I tried a workaround using proc sql directly from the variable but no luck.
options mprint symbolgen mlogic;
%macro codebook(lib=,ds=,maxVal=);
%if &lib= BLANK | &ds = BLANK %then %do;
%put &=lib;
%put &=ds;
%abort;
%end;
ods select variables;
proc contents data=&lib..&ds. out=_contents_ ; run;
proc format;
value tfmt
1 = 'NUM'
2 = 'CHAR';
run;
data _null_;
set _contents_ end=last;
call symput('vname'||strip(put(_n_,best.)), strip(name));
call symput('vtype'||strip(put(_n_,best.)), strip(put(type,tfmt.)));
call symput('vlabel'||strip(put(_n_,best.)), strip(label));
if last then call symput('nVars',strip(put(_n_,best.)));
run;
%do j = 1 %to &nVars.;
title1 "Analysis of &&vlabel&j (Variable=%upcase(&&vname&j.)) ";
%if &&vtype&j=NUM %then %do;
%PUT Condition was Met on &&vtype&j;
proc means data=&lib..&ds.;
var &&vname&j.;
run;
%end;
%else %if &&vtype&j=CHAR %then %do;
ods select none;
ods output nlevels=nlev;
proc freq data=&lib..&ds. nlevels;
tables &&vname&j./out=freqtab;
run;
proc sql;
select nLevels into: nLevels from nlev;
quit;
%if &nLevels le &maxVal %then %do;
proc print data=freqtab label;
run;
%end;
%else %if &nLevels gt &maxVal %then %do;
data a;
set freqtab(obs=&maxVal);
run;
proc print data=a label;
run;
%end;
%end;
%end;
%mend;
%codebook(lib=out,ds=adsl,maxVal=10) ;
my log:
1 OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
SYMBOLGEN: Macro variable _SASWSTEMP_ resolves to /folders/myfolders/.sasstudio/.images/60e7b0e1-35b2-485f-a780-1b12d701fc85
SYMBOLGEN: Some characters in the above value which were subject to macro quoting have been unquoted for printing.
SYMBOLGEN: Macro variable GRAPHINIT resolves to
NOTE: ODS statements in the SAS Studio environment may disable some output features.
73
74 *************
75 project: BIOS 511
76
77 Name: lab-13-task-2-710929473-Task1.sas
78
79 Author: Alexandre Lockhart
80
81 Date: 2019-11-26
82
83 Purpose: Lab 13 Task 2 of BIOS 511. Implement codebook macro for ADSL and DM datasets.
84 *************;
85
86
87
88
89
90 %let root = /folders/myfolders/BIOS511;
91 %let lab = Lab-13;
92 %let dataPath = &root/Lab/&lab./Data;
SYMBOLGEN: Macro variable ROOT resolves to /folders/myfolders/BIOS511
SYMBOLGEN: Macro variable LAB resolves to Lab-13
93 %let macroPath = &root/Lab/&lab./Macros;
SYMBOLGEN: Macro variable ROOT resolves to /folders/myfolders/BIOS511
SYMBOLGEN: Macro variable LAB resolves to Lab-13
94
95
96 libname echo "&root./data/echo" access=read;
SYMBOLGEN: Macro variable ROOT resolves to /folders/myfolders/BIOS511
NOTE: Libref ECHO was successfully assigned as follows:
Engine: V9
Physical Name: /folders/myfolders/BIOS511/data/echo
97 libname out "&dataPath." ;
SYMBOLGEN: Macro variable DATAPATH resolves to /folders/myfolders/BIOS511/Lab/Lab-13/Data
NOTE: Libref OUT was successfully assigned as follows:
Engine: V9
Physical Name: /folders/myfolders/BIOS511/Lab/Lab-13/Data
SYMBOLGEN: Macro variable ROOT resolves to /folders/myfolders/BIOS511
SYMBOLGEN: Macro variable LAB resolves to Lab-13
98
99
100 %let outpath=&root/Lab/&lab./Output;
101
102
103
104
105 options mprint symbolgen mlogic;
106 %macro codebook(lib=,ds=,maxVal=);
107
108 %if &lib= BLANK | &ds = BLANK %then %do;
109 %put &=lib;
110 %put &=ds;
111 %abort;
112 %end;
113
114
115 ods select variables;
116 proc contents data=&lib..&ds. out=_contents_ ; run;
117 proc format;
118
119 value tfmt
120
121 1 = 'NUM'
122 2 = 'CHAR';
123
124 run;
125
126
127
128
129 data _null_;
130 set _contents_ end=last;
131
132 call symput('vname'||strip(put(_n_,best.)), strip(name));
133 call symput('vtype'||strip(put(_n_,best.)), strip(put(type,tfmt.)));
134 call symput('vlabel'||strip(put(_n_,best.)), strip(label));
135
136 if last then call symput('nVars',strip(put(_n_,best.)));
137 run;
138
139
140
141
142
143
144 %do j = 1 %to &nVars.;
145 title1 "Analysis of &&vlabel&j (Variable=%upcase(&&vname&j.)) ";
146 %if &&vtype&j=NUM %then %do;
147
148 %PUT Condition was Met on &&vtype&j;
149
150 proc means data=&lib..&ds.;
151
152
153 var &&vname&j.;
154 run;
155 %end;
156
157 %else %if &&vtype&j=CHAR %then %do;
158
159
160 ods select none;
161 ods output nlevels=nlev;
162 proc freq data=&lib..&ds. nlevels;
163 tables &&vname&j./out=freqtab;
164 run;
165
166
167 proc sql;
168
169 select nLevels into: nLevels from nlev;
170 quit;
171
172 %if &nLevels le &maxVal %then %do;
173
174
175 proc print data=freqtab label;
176 run;
177 %end;
178 %else %if &nLevels gt &maxVal %then %do;
179
180 data a;
181
182
183 set freqtab(obs=&maxVal);
184
185
186 run;
187
188
189 proc print data=a label;
190 run;
191
192 %end;
193
194
195 %end;
196 %end;
197
198 %mend;
199
200 %codebook(lib=out,ds=adsl,maxVal=10);
MLOGIC(CODEBOOK): Beginning execution.
MLOGIC(CODEBOOK): Parameter LIB has value out
MLOGIC(CODEBOOK): Parameter DS has value adsl
MLOGIC(CODEBOOK): Parameter MAXVAL has value 10
SYMBOLGEN: Macro variable LIB resolves to out
SYMBOLGEN: Macro variable DS resolves to adsl
MLOGIC(CODEBOOK): %IF condition &lib= BLANK | &ds = BLANK is FALSE
MPRINT(CODEBOOK): ods select variables;
SYMBOLGEN: Macro variable LIB resolves to out
SYMBOLGEN: Macro variable DS resolves to adsl
MPRINT(CODEBOOK): proc contents data=out.adsl out=_contents_ ;
MPRINT(CODEBOOK): run;
NOTE: The data set WORK._CONTENTS_ has 13 observations and 41 variables.
NOTE: PROCEDURE CONTENTS used (Total process time):
real time 0.09 seconds
cpu time 0.09 seconds
MPRINT(CODEBOOK): proc format;
MPRINT(CODEBOOK): value tfmt 1 = 'NUM' 2 = 'CHAR';
NOTE: Format TFMT is already on the library WORK.FORMATS.
NOTE: Format TFMT has been output.
MPRINT(CODEBOOK): run;
NOTE: PROCEDURE FORMAT used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
MPRINT(CODEBOOK): data _null_;
MPRINT(CODEBOOK): set _contents_ end=last;
MPRINT(CODEBOOK): call symput('vname'||strip(put(_n_,best.)), strip(name));
MPRINT(CODEBOOK): call symput('vtype'||strip(put(_n_,best.)), strip(put(type,tfmt.)));
MPRINT(CODEBOOK): call symput('vlabel'||strip(put(_n_,best.)), strip(label));
MPRINT(CODEBOOK): if last then call symput('nVars',strip(put(_n_,best.)));
MPRINT(CODEBOOK): run;
NOTE: There were 13 observations read from the data set WORK._CONTENTS_.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds
SYMBOLGEN: Macro variable NVARS resolves to 13
MLOGIC(CODEBOOK): %DO loop beginning; index variable J; start value is 1; stop value is 13; by value is 1.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 1
SYMBOLGEN: Macro variable VLABEL1 resolves to Age
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 1
SYMBOLGEN: Macro variable VNAME1 resolves to AGE
MPRINT(CODEBOOK): title1 "Analysis of Age (Variable=AGE) ";
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 1
SYMBOLGEN: Macro variable VTYPE1 resolves to NUM
MLOGIC(CODEBOOK): %IF condition &&vtype&j=NUM is TRUE
MLOGIC(CODEBOOK): %PUT Condition was Met on &&vtype&j
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 1
SYMBOLGEN: Macro variable VTYPE1 resolves to NUM
Condition was Met on NUM
SYMBOLGEN: Macro variable LIB resolves to out
SYMBOLGEN: Macro variable DS resolves to adsl
MPRINT(CODEBOOK): proc means data=out.adsl;
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 1
SYMBOLGEN: Macro variable VNAME1 resolves to AGE
MPRINT(CODEBOOK): var AGE;
MPRINT(CODEBOOK): run;
NOTE: There were 602 observations read from the data set OUT.ADSL.
NOTE: PROCEDURE MEANS used (Total process time):
real time 0.06 seconds
cpu time 0.05 seconds
MLOGIC(CODEBOOK): %DO loop index variable J is now 2; loop will iterate again.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 2
SYMBOLGEN: Macro variable VLABEL2 resolves to Description of Planned Arm
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 2
SYMBOLGEN: Macro variable VNAME2 resolves to ARM
MPRINT(CODEBOOK): title1 "Analysis of Description of Planned Arm (Variable=ARM) ";
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 2
SYMBOLGEN: Macro variable VTYPE2 resolves to CHAR
MLOGIC(CODEBOOK): %IF condition &&vtype&j=NUM is FALSE
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 2
SYMBOLGEN: Macro variable VTYPE2 resolves to CHAR
MLOGIC(CODEBOOK): %IF condition &&vtype&j=CHAR is TRUE
MPRINT(CODEBOOK): ods select none;
MPRINT(CODEBOOK): ods output nlevels=nlev;
SYMBOLGEN: Macro variable LIB resolves to out
SYMBOLGEN: Macro variable DS resolves to adsl
MPRINT(CODEBOOK): proc freq data=out.adsl nlevels;
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 2
SYMBOLGEN: Macro variable VNAME2 resolves to ARM
MPRINT(CODEBOOK): tables ARM/out=freqtab;
MPRINT(CODEBOOK): run;
NOTE: The data set WORK.NLEV has 1 observations and 5 variables.
NOTE: There were 602 observations read from the data set OUT.ADSL.
NOTE: The data set WORK.FREQTAB has 2 observations and 3 variables.
NOTE: PROCEDURE FREQ used (Total process time):
real time 0.04 seconds
cpu time 0.02 seconds
MPRINT(CODEBOOK): proc sql;
MPRINT(CODEBOOK): select nLevels into: nLevels from nlev;
MPRINT(CODEBOOK): quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds
SYMBOLGEN: Macro variable NLEVELS resolves to 2
SYMBOLGEN: Macro variable MAXVAL resolves to 10
MLOGIC(CODEBOOK): %IF condition &nLevels le &maxVal is TRUE
MPRINT(CODEBOOK): proc print data=freqtab label;
MPRINT(CODEBOOK): run;
NOTE: There were 2 observations read from the data set WORK.FREQTAB.
NOTE: PROCEDURE PRINT used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds
MLOGIC(CODEBOOK): %DO loop index variable J is now 3; loop will iterate again.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 3
SYMBOLGEN: Macro variable VLABEL3 resolves to Planned Arm Code
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 3
SYMBOLGEN: Macro variable VNAME3 resolves to ARMCD
MPRINT(CODEBOOK): title1 "Analysis of Planned Arm Code (Variable=ARMCD) ";
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 3
SYMBOLGEN: Macro variable VTYPE3 resolves to CHAR
MLOGIC(CODEBOOK): %IF condition &&vtype&j=NUM is FALSE
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 3
SYMBOLGEN: Macro variable VTYPE3 resolves to CHAR
MLOGIC(CODEBOOK): %IF condition &&vtype&j=CHAR is TRUE
MPRINT(CODEBOOK): ods select none;
MPRINT(CODEBOOK): ods output nlevels=nlev;
SYMBOLGEN: Macro variable LIB resolves to out
SYMBOLGEN: Macro variable DS resolves to adsl
MPRINT(CODEBOOK): proc freq data=out.adsl nlevels;
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 3
SYMBOLGEN: Macro variable VNAME3 resolves to ARMCD
MPRINT(CODEBOOK): tables ARMCD/out=freqtab;
MPRINT(CODEBOOK): run;
NOTE: The data set WORK.NLEV has 1 observations and 5 variables.
NOTE: There were 602 observations read from the data set OUT.ADSL.
NOTE: The data set WORK.FREQTAB has 2 observations and 3 variables.
NOTE: PROCEDURE FREQ used (Total process time):
real time 0.03 seconds
cpu time 0.02 seconds
MPRINT(CODEBOOK): proc sql;
MPRINT(CODEBOOK): select nLevels into: nLevels from nlev;
MPRINT(CODEBOOK): quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds
SYMBOLGEN: Macro variable NLEVELS resolves to 2
SYMBOLGEN: Macro variable MAXVAL resolves to 10
MLOGIC(CODEBOOK): %IF condition &nLevels le &maxVal is TRUE
MPRINT(CODEBOOK): proc print data=freqtab label;
MPRINT(CODEBOOK): run;
NOTE: There were 2 observations read from the data set WORK.FREQTAB.
NOTE: PROCEDURE PRINT used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
MLOGIC(CODEBOOK): %DO loop index variable J is now 4; loop will iterate again.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 4
SYMBOLGEN: Macro variable VLABEL4 resolves to Country
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 4
SYMBOLGEN: Macro variable VNAME4 resolves to COUNTRY
MPRINT(CODEBOOK): title1 "Analysis of Country (Variable=COUNTRY) ";
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 4
SYMBOLGEN: Macro variable VTYPE4 resolves to CHAR
MLOGIC(CODEBOOK): %IF condition &&vtype&j=NUM is FALSE
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 4
SYMBOLGEN: Macro variable VTYPE4 resolves to CHAR
MLOGIC(CODEBOOK): %IF condition &&vtype&j=CHAR is TRUE
MPRINT(CODEBOOK): ods select none;
MPRINT(CODEBOOK): ods output nlevels=nlev;
SYMBOLGEN: Macro variable LIB resolves to out
SYMBOLGEN: Macro variable DS resolves to adsl
MPRINT(CODEBOOK): proc freq data=out.adsl nlevels;
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 4
SYMBOLGEN: Macro variable VNAME4 resolves to COUNTRY
MPRINT(CODEBOOK): tables COUNTRY/out=freqtab;
MPRINT(CODEBOOK): run;
NOTE: The data set WORK.NLEV has 1 observations and 5 variables.
NOTE: There were 602 observations read from the data set OUT.ADSL.
NOTE: The data set WORK.FREQTAB has 3 observations and 3 variables.
NOTE: PROCEDURE FREQ used (Total process time):
real time 0.03 seconds
cpu time 0.03 seconds
MPRINT(CODEBOOK): proc sql;
MPRINT(CODEBOOK): select nLevels into: nLevels from nlev;
MPRINT(CODEBOOK): quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds
SYMBOLGEN: Macro variable NLEVELS resolves to 3
SYMBOLGEN: Macro variable MAXVAL resolves to 10
MLOGIC(CODEBOOK): %IF condition &nLevels le &maxVal is TRUE
MPRINT(CODEBOOK): proc print data=freqtab label;
MPRINT(CODEBOOK): run;
NOTE: There were 3 observations read from the data set WORK.FREQTAB.
NOTE: PROCEDURE PRINT used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
MLOGIC(CODEBOOK): %DO loop index variable J is now 5; loop will iterate again.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 5
SYMBOLGEN: Macro variable VLABEL5 resolves to Race
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 5
SYMBOLGEN: Macro variable VNAME5 resolves to RACE
MPRINT(CODEBOOK): title1 "Analysis of Race (Variable=RACE) ";
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 5
SYMBOLGEN: Macro variable VTYPE5 resolves to CHAR
MLOGIC(CODEBOOK): %IF condition &&vtype&j=NUM is FALSE
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 5
SYMBOLGEN: Macro variable VTYPE5 resolves to CHAR
MLOGIC(CODEBOOK): %IF condition &&vtype&j=CHAR is TRUE
MPRINT(CODEBOOK): ods select none;
MPRINT(CODEBOOK): ods output nlevels=nlev;
SYMBOLGEN: Macro variable LIB resolves to out
SYMBOLGEN: Macro variable DS resolves to adsl
MPRINT(CODEBOOK): proc freq data=out.adsl nlevels;
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 5
SYMBOLGEN: Macro variable VNAME5 resolves to RACE
MPRINT(CODEBOOK): tables RACE/out=freqtab;
MPRINT(CODEBOOK): run;
NOTE: The data set WORK.NLEV has 1 observations and 5 variables.
NOTE: There were 602 observations read from the data set OUT.ADSL.
NOTE: The data set WORK.FREQTAB has 6 observations and 3 variables.
NOTE: PROCEDURE FREQ used (Total process time):
real time 0.02 seconds
cpu time 0.02 seconds
MPRINT(CODEBOOK): proc sql;
MPRINT(CODEBOOK): select nLevels into: nLevels from nlev;
MPRINT(CODEBOOK): quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
SYMBOLGEN: Macro variable NLEVELS resolves to 6
SYMBOLGEN: Macro variable MAXVAL resolves to 10
MLOGIC(CODEBOOK): %IF condition &nLevels le &maxVal is TRUE
MPRINT(CODEBOOK): proc print data=freqtab label;
MPRINT(CODEBOOK): run;
NOTE: There were 6 observations read from the data set WORK.FREQTAB.
NOTE: PROCEDURE PRINT used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
MLOGIC(CODEBOOK): %DO loop index variable J is now 6; loop will iterate again.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 6
SYMBOLGEN: Macro variable VLABEL6 resolves to Age categorization
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 6
SYMBOLGEN: Macro variable VNAME6 resolves to agecat
MPRINT(CODEBOOK): title1 "Analysis of Age categorization (Variable=AGECAT) ";
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 6
SYMBOLGEN: Macro variable VTYPE6 resolves to CHAR
MLOGIC(CODEBOOK): %IF condition &&vtype&j=NUM is FALSE
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 6
SYMBOLGEN: Macro variable VTYPE6 resolves to CHAR
MLOGIC(CODEBOOK): %IF condition &&vtype&j=CHAR is TRUE
MPRINT(CODEBOOK): ods select none;
MPRINT(CODEBOOK): ods output nlevels=nlev;
SYMBOLGEN: Macro variable LIB resolves to out
SYMBOLGEN: Macro variable DS resolves to adsl
MPRINT(CODEBOOK): proc freq data=out.adsl nlevels;
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 6
SYMBOLGEN: Macro variable VNAME6 resolves to agecat
MPRINT(CODEBOOK): tables agecat/out=freqtab;
MPRINT(CODEBOOK): run;
NOTE: The data set WORK.NLEV has 1 observations and 5 variables.
NOTE: There were 602 observations read from the data set OUT.ADSL.
NOTE: The data set WORK.FREQTAB has 4 observations and 3 variables.
NOTE: PROCEDURE FREQ used (Total process time):
real time 0.03 seconds
cpu time 0.02 seconds
MPRINT(CODEBOOK): proc sql;
MPRINT(CODEBOOK): select nLevels into: nLevels from nlev;
MPRINT(CODEBOOK): quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds
SYMBOLGEN: Macro variable NLEVELS resolves to 4
SYMBOLGEN: Macro variable MAXVAL resolves to 10
MLOGIC(CODEBOOK): %IF condition &nLevels le &maxVal is TRUE
MPRINT(CODEBOOK): proc print data=freqtab label;
MPRINT(CODEBOOK): run;
NOTE: There were 4 observations read from the data set WORK.FREQTAB.
NOTE: PROCEDURE PRINT used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
MLOGIC(CODEBOOK): %DO loop index variable J is now 7; loop will iterate again.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 7
SYMBOLGEN: Macro variable VLABEL7 resolves to Change in diastolic bp
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 7
SYMBOLGEN: Macro variable VNAME7 resolves to diabp_change
MPRINT(CODEBOOK): title1 "Analysis of Change in diastolic bp (Variable=DIABP_CHANGE) ";
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 7
SYMBOLGEN: Macro variable VTYPE7 resolves to NUM
MLOGIC(CODEBOOK): %IF condition &&vtype&j=NUM is TRUE
MLOGIC(CODEBOOK): %PUT Condition was Met on &&vtype&j
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 7
SYMBOLGEN: Macro variable VTYPE7 resolves to NUM
Condition was Met on NUM
SYMBOLGEN: Macro variable LIB resolves to out
SYMBOLGEN: Macro variable DS resolves to adsl
MPRINT(CODEBOOK): proc means data=out.adsl;
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 7
SYMBOLGEN: Macro variable VNAME7 resolves to diabp_change
MPRINT(CODEBOOK): var diabp_change;
MPRINT(CODEBOOK): run;
NOTE: There were 602 observations read from the data set OUT.ADSL.
NOTE: PROCEDURE MEANS used (Total process time):
real time 0.03 seconds
cpu time 0.02 seconds
MLOGIC(CODEBOOK): %DO loop index variable J is now 8; loop will iterate again.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 8
SYMBOLGEN: Macro variable VLABEL8 resolves to Change in heart rate
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 8
SYMBOLGEN: Macro variable VNAME8 resolves to hr_change
MPRINT(CODEBOOK): title1 "Analysis of Change in heart rate (Variable=HR_CHANGE) ";
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 8
SYMBOLGEN: Macro variable VTYPE8 resolves to NUM
MLOGIC(CODEBOOK): %IF condition &&vtype&j=NUM is TRUE
MLOGIC(CODEBOOK): %PUT Condition was Met on &&vtype&j
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 8
SYMBOLGEN: Macro variable VTYPE8 resolves to NUM
Condition was Met on NUM
SYMBOLGEN: Macro variable LIB resolves to out
SYMBOLGEN: Macro variable DS resolves to adsl
MPRINT(CODEBOOK): proc means data=out.adsl;
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 8
SYMBOLGEN: Macro variable VNAME8 resolves to hr_change
MPRINT(CODEBOOK): var hr_change;
MPRINT(CODEBOOK): run;
NOTE: There were 602 observations read from the data set OUT.ADSL.
NOTE: PROCEDURE MEANS used (Total process time):
real time 0.03 seconds
cpu time 0.03 seconds
MLOGIC(CODEBOOK): %DO loop index variable J is now 9; loop will iterate again.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 9
SYMBOLGEN: Macro variable VLABEL9 resolves to Numeric Result/Finding in Standard Units
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 9
SYMBOLGEN: Macro variable VNAME9 resolves to pcmax
MPRINT(CODEBOOK): title1 "Analysis of Numeric Result/Finding in Standard Units (Variable=PCMAX) ";
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 9
SYMBOLGEN: Macro variable VTYPE9 resolves to NUM
MLOGIC(CODEBOOK): %IF condition &&vtype&j=NUM is TRUE
MLOGIC(CODEBOOK): %PUT Condition was Met on &&vtype&j
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 9
SYMBOLGEN: Macro variable VTYPE9 resolves to NUM
Condition was Met on NUM
SYMBOLGEN: Macro variable LIB resolves to out
SYMBOLGEN: Macro variable DS resolves to adsl
MPRINT(CODEBOOK): proc means data=out.adsl;
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 9
SYMBOLGEN: Macro variable VNAME9 resolves to pcmax
MPRINT(CODEBOOK): var pcmax;
MPRINT(CODEBOOK): run;
NOTE: There were 602 observations read from the data set OUT.ADSL.
NOTE: PROCEDURE MEANS used (Total process time):
real time 0.03 seconds
cpu time 0.02 seconds
MLOGIC(CODEBOOK): %DO loop index variable J is now 10; loop will iterate again.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 10
SYMBOLGEN: Macro variable VLABEL10 resolves to Highest Value
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 10
SYMBOLGEN: Macro variable VNAME10 resolves to pcmax2
MPRINT(CODEBOOK): title1 "Analysis of Highest Value (Variable=PCMAX2) ";
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 10
SYMBOLGEN: Macro variable VTYPE10 resolves to NUM
MLOGIC(CODEBOOK): %IF condition &&vtype&j=NUM is TRUE
MLOGIC(CODEBOOK): %PUT Condition was Met on &&vtype&j
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 10
SYMBOLGEN: Macro variable VTYPE10 resolves to NUM
Condition was Met on NUM
SYMBOLGEN: Macro variable LIB resolves to out
SYMBOLGEN: Macro variable DS resolves to adsl
MPRINT(CODEBOOK): proc means data=out.adsl;
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 10
SYMBOLGEN: Macro variable VNAME10 resolves to pcmax2
MPRINT(CODEBOOK): var pcmax2;
MPRINT(CODEBOOK): run;
NOTE: There were 602 observations read from the data set OUT.ADSL.
NOTE: PROCEDURE MEANS used (Total process time):
real time 0.03 seconds
cpu time 0.03 seconds
MLOGIC(CODEBOOK): %DO loop index variable J is now 11; loop will iterate again.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 11
SYMBOLGEN: Macro variable VLABEL11 resolves to Change in systolic bp
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 11
SYMBOLGEN: Macro variable VNAME11 resolves to sysbp_change
MPRINT(CODEBOOK): title1 "Analysis of Change in systolic bp (Variable=SYSBP_CHANGE) ";
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 11
SYMBOLGEN: Macro variable VTYPE11 resolves to NUM
MLOGIC(CODEBOOK): %IF condition &&vtype&j=NUM is TRUE
MLOGIC(CODEBOOK): %PUT Condition was Met on &&vtype&j
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 11
SYMBOLGEN: Macro variable VTYPE11 resolves to NUM
Condition was Met on NUM
SYMBOLGEN: Macro variable LIB resolves to out
SYMBOLGEN: Macro variable DS resolves to adsl
MPRINT(CODEBOOK): proc means data=out.adsl;
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 11
SYMBOLGEN: Macro variable VNAME11 resolves to sysbp_change
MPRINT(CODEBOOK): var sysbp_change;
MPRINT(CODEBOOK): run;
NOTE: There were 602 observations read from the data set OUT.ADSL.
NOTE: PROCEDURE MEANS used (Total process time):
real time 0.03 seconds
cpu time 0.02 seconds
MLOGIC(CODEBOOK): %DO loop index variable J is now 12; loop will iterate again.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 12
SYMBOLGEN: Macro variable VLABEL12 resolves to Unique Subject Identifier
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 12
SYMBOLGEN: Macro variable VNAME12 resolves to usubjid
MPRINT(CODEBOOK): title1 "Analysis of Unique Subject Identifier (Variable=USUBJID) ";
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 12
SYMBOLGEN: Macro variable VTYPE12 resolves to CHAR
MLOGIC(CODEBOOK): %IF condition &&vtype&j=NUM is FALSE
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 12
SYMBOLGEN: Macro variable VTYPE12 resolves to CHAR
MLOGIC(CODEBOOK): %IF condition &&vtype&j=CHAR is TRUE
MPRINT(CODEBOOK): ods select none;
MPRINT(CODEBOOK): ods output nlevels=nlev;
SYMBOLGEN: Macro variable LIB resolves to out
SYMBOLGEN: Macro variable DS resolves to adsl
MPRINT(CODEBOOK): proc freq data=out.adsl nlevels;
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 12
SYMBOLGEN: Macro variable VNAME12 resolves to usubjid
MPRINT(CODEBOOK): tables usubjid/out=freqtab;
MPRINT(CODEBOOK): run;
NOTE: The data set WORK.NLEV has 1 observations and 5 variables.
NOTE: There were 602 observations read from the data set OUT.ADSL.
NOTE: The data set WORK.FREQTAB has 602 observations and 3 variables.
NOTE: PROCEDURE FREQ used (Total process time):
real time 0.04 seconds
cpu time 0.03 seconds
MPRINT(CODEBOOK): proc sql;
MPRINT(CODEBOOK): select nLevels into: nLevels from nlev;
MPRINT(CODEBOOK): quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.01 seconds
cpu time 0.01 seconds
SYMBOLGEN: Macro variable NLEVELS resolves to 602
SYMBOLGEN: Macro variable MAXVAL resolves to 10
MLOGIC(CODEBOOK): %IF condition &nLevels le &maxVal is FALSE
SYMBOLGEN: Macro variable NLEVELS resolves to 602
SYMBOLGEN: Macro variable MAXVAL resolves to 10
MLOGIC(CODEBOOK): %IF condition &nLevels gt &maxVal is TRUE
MPRINT(CODEBOOK): data a;
SYMBOLGEN: Macro variable MAXVAL resolves to 10
MPRINT(CODEBOOK): set freqtab(obs=10);
MPRINT(CODEBOOK): run;
NOTE: There were 10 observations read from the data set WORK.FREQTAB.
NOTE: The data set WORK.A has 10 observations and 3 variables.
NOTE: DATA statement used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds
MPRINT(CODEBOOK): proc print data=a label;
MPRINT(CODEBOOK): run;
NOTE: There were 10 observations read from the data set WORK.A.
NOTE: PROCEDURE PRINT used (Total process time):
real time 0.00 seconds
cpu time 0.00 seconds
MLOGIC(CODEBOOK): %DO loop index variable J is now 13; loop will iterate again.
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 13
SYMBOLGEN: Macro variable VLABEL13 resolves to Change in weight
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 13
SYMBOLGEN: Macro variable VNAME13 resolves to wgt_change
MPRINT(CODEBOOK): title1 "Analysis of Change in weight (Variable=WGT_CHANGE) ";
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 13
SYMBOLGEN: Macro variable VTYPE13 resolves to NUM
MLOGIC(CODEBOOK): %IF condition &&vtype&j=NUM is TRUE
MLOGIC(CODEBOOK): %PUT Condition was Met on &&vtype&j
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 13
SYMBOLGEN: Macro variable VTYPE13 resolves to NUM
Condition was Met on NUM
SYMBOLGEN: Macro variable LIB resolves to out
SYMBOLGEN: Macro variable DS resolves to adsl
MPRINT(CODEBOOK): proc means data=out.adsl;
SYMBOLGEN: && resolves to &.
SYMBOLGEN: Macro variable J resolves to 13
SYMBOLGEN: Macro variable VNAME13 resolves to wgt_change
MPRINT(CODEBOOK): var wgt_change;
MPRINT(CODEBOOK): run;
NOTE: There were 602 observations read from the data set OUT.ADSL.
NOTE: PROCEDURE MEANS used (Total process time):
real time 0.02 seconds
cpu time 0.02 seconds
MLOGIC(CODEBOOK): %DO loop index variable J is now 14; loop will not iterate again.
MLOGIC(CODEBOOK): Ending execution.
201
202
203 OPTIONS NONOTES NOSTIMER NOSOURCE NOSYNTAXCHECK;
SYMBOLGEN: Macro variable GRAPHTERM resolves to
215
When you hit the first character variable you turn off all output.
ods select none;
You never turn it back on again. Add
ods select all;
Since you are making a dataset anyway you can just use the OBS= option
%else %if &&vtype&j=CHAR %then %do;
ods select none;
ods output nlevels=nlev;
proc freq data=&lib..&ds. nlevels;
tables &&vname&j./out=freqtab;
run;
ods select all;
options obs=&maxVal ;
proc print data=freqtab label;
run;
options obs=max;
%end;
or use PROC SQL and the OUTOBS= option.
proc sql outobs=&maxVal ;
select * from freqtab;
quit;
PS Do you want to add ORDER=FREQ to your PROC FREQ statement so that the &maxVAL most common values are printed?
Thanks for your patience, Tom. I did add the order=FREQ. One final question as I am posting the code and one small snippet of output, I am trying to suppress the levels in the output of my program. You can see the levels number (in this example '2') before and after (actually for the next variable) the proc print of the proc freq. I generate those levels via proc sql now, but for some reason they show in the output. Why are they showing and how do I suppress? They are showing for any proc print of a proc freq object.
Code:
options mprint symbolgen mlogic;
%macro codebook(lib=,ds=,maxVal=);
%let maxVal=10;
%if &lib= BLANK | &ds = BLANK %then %do;
%put &=lib;
%put &=ds;
%abort;
%end;
ods select variables;
proc contents data=&lib..&ds. out=_contents_ ; run;
proc format;
value tfmt
1 = 'NUM'
2 = 'CHAR';
run;
data _null_;
set _contents_ end=last;
call symput('vname'||strip(put(_n_,best.)), strip(name));
call symput('vtype'||strip(put(_n_,best.)), strip(put(type,tfmt.)));
call symput('vlabel'||strip(put(_n_,best.)), strip(label));
if last then call symput('nVars',strip(put(_n_,best.)));
run;
%do j = 1 %to &nVars.;
title1 "Analysis of &&vlabel&j (Variable=%upcase(&&vname&j.)) ";
%if &&vtype&j=NUM %then %do;
%PUT Condition was Met on &&vtype&j;
proc means data=&lib..&ds.;
var &&vname&j.;
run;
%end;
%else %if &&vtype&j=CHAR %then %do;
ods select none;
*ods output nlevels=nlev;
proc freq data=&lib..&ds. order=freq;
tables &&vname&j./out=freqtab;
run;
ods select all;
proc sql;
* select nLevels into: nLevels from nlev;
select count(distinct(&&vname&j.)) into: nLevels from &lib..&ds.;
quit;
%if &nLevels le &maxVal %then %do;
proc print data=freqtab label;
run;
%end;
%else %if &nLevels gt &maxVal %then %do;
/* data a;
set freqtab(obs=&maxVal);
run;
proc print data=a label;
run; */
options obs=&maxVal ;
proc print data=freqtab label;
run;
options obs=max;
%end;
%end;
%end;
%mend;
%codebook(lib=out,ds=adsl,maxVal=) ;
Output:
If you don't want PROC SQL to print then tell it so by using the NOPRINT option.
proc sql noprint
select nLevels format=32. into :nLevels trimmed from nlev;
select count(distinct &&vname&j.) format=32. into :nLevels trimmed from &lib..&ds.;
quit;
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.