Hi All,
Our Testing Center has a SAS program written probably 30 years ago, it shows the key answers of an exam on the first row, then lists all the student responses as the second observations and so on. However, if the class is too big and the printout will last for several pages. Then there are no more key answers showed as first row from second page on. The professor would like to see the key answers on every page of the listing of student responses when he meets with the students to discuss.
ID | Q1 | Q2 | Q3 | Q4 | Q5 | Q6 | Q7 | Q8 | Q9 | Q10 |
key | C | D | A | C | C | B | D | C | D | C |
X024406 | C | D | A | C | C | B | D | E | D | A |
X024894 | C | E | A | C | B | A | D | E | E | C |
X102308 | C | D | A | C | C | B | C | C | D | C |
X106252 | C | D | A | D | C | B | D | A | D | C |
X112442 | C | E | A | C | C | B | D | E | D | C |
Is there an option in PROC PRINT to do that?
I was thinking to combine the info of the keys and question items, i.e., Q1=C, Q2=D, etc. But not successful!
I appreciate any help you can provide.
Thanks.
And if you want it to be totally data driven, you can read observation 1, construct the LABEL statement, and write it to a temporary file for subsequent inclusion in a proc print:
data have;
input ID $ Q1 $ Q2 $;
cards;
key C D
X12345 C B
X23456 A D
run;
filename tmp temp;
data _null_;
set have (obs=1);
file tmp;
put 'LABEL';
do until (VNAM='VNAM');
call vnext(vnam);
if vnam='VNAM' then leave;
labl=cats('"',vnam,'^',vvaluex(vnam),'"');
put vnam '=' labl;
end;
run;
options source2;
proc print data=have(firstobs=2) split='^' noobs;
%include tmp ;;
run;
Why not just put the key into a header row then, something like:
proc report data=have nowd split="*"; columns _all_; define id / "ID*key"; define q1 / "Q1*C"; ... run;
Note the split="*" - this indicates where to put a new line. In this way the key row would appear on every page. Also note, I use report rather than print as its far more advanced and powerful.
The other way I could see is a compute before page block, and having the key in a string , but thats messy and long winded.
Same technique as suggested by RW9 works with PROC PRINT.
Example:
data have;
input ID $ Q1 $ Q2 $;
cards;
key C D
X12345 C B
X23456 A D
;
proc print data=have(firstobs=2) split='^' noobs;
label ID='ID^key'
Q1='Q1^C'
Q2='Q2^D';
run;
Thanks!
However, I don't know how to label the key that is changing from exam to exam. The instructor puts the keys in a separate form for scanning in.
Please see attachment for a simplified version of the program.
Then you need to generate the code from that dataset:
data _null_;
set keys;
call execute('proc report data=have nowd split="*"; columns _all_; define id / "ID*key";'); call execute(cat(' define q1 / "Q1*',strip(key1),'";')); call execute(cat(' define q2 / "Q2*',strip(key2),'";'));
call execute(cat(' define q3 / "Q3*',strip(key3),'";'));
call execute(';run;'); run;
And if you want it to be totally data driven, you can read observation 1, construct the LABEL statement, and write it to a temporary file for subsequent inclusion in a proc print:
data have;
input ID $ Q1 $ Q2 $;
cards;
key C D
X12345 C B
X23456 A D
run;
filename tmp temp;
data _null_;
set have (obs=1);
file tmp;
put 'LABEL';
do until (VNAM='VNAM');
call vnext(vnam);
if vnam='VNAM' then leave;
labl=cats('"',vnam,'^',vvaluex(vnam),'"');
put vnam '=' labl;
end;
run;
options source2;
proc print data=have(firstobs=2) split='^' noobs;
%include tmp ;;
run;
Thanks so much for everyone taking your time in answering my question!
mkeintz, "Construct the LABEL statement, and write it to a temporary file for subsequent inclusion in a proc print" works on my simplified version! Thanks for the suggestion!
RW9, I will try the proc report later to see how it works.
@mkeintz wrote:
And if you want it to be totally data driven, you can read observation 1, construct the LABEL statement, and write it to a temporary file for subsequent inclusion in a proc print:
In keeping with @mkeintz data driven approach you can also use PROC TRANSPOSE (my second favorite) procedure to create the labels. PROC TRANSPOSE can create meta data from data and the other way round.
data response;
input ID:$4. (q1-q3)(:$1.);
cards;
X213 E A B
X907 E A C
X526 D A B
;
Run;
data keys;
input ID:$4. (key1-key3)(:$1.);
cards;
9999 E A B
;
run;
proc transpose data=keys out=keys2;
by id;
var key:;
run;
data keys2;
set keys2;
_name_ = transtrn(_name_,'key','Q');
_label_ = catx('~',_name_,col1);
run;
proc transpose data=keys2 out=keys3;
by id;
var col1;
run;
proc contents varnum;
run;
proc print;
run;
data response;
input ID:$4. (q1-q3)(:$1.);
cards;
X213 E A B
X907 E A C
X526 D A B
;
Run;
data responseV / view=responseV;
set keys3(obs=0) response;
label id='Question~Key';
run;
proc report list split='~';
columns id q:;
define id / order;
define q: / display;
run;
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.