BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Tpham
Quartz | Level 8

So I am creating a macro to score a questionnaire. So the first part of the macro is calculating a raw score... and the second part is converting the raw score to a standardize score, where the standardize score would come from an existing table. I want this macro to be a stand alone program (called by my autoexec) so it can be moved from project to project.

 

I understand that I can't use Datalines/Cards within a macro. I am trying to figure out is there a workaround for this?

 

This is basically this is what I want, but the cards statement doesn't work in macros. I only thing I can think of is use the If/Then statement (so if rawscrore=1 then standarscore=14.5.. etc.). But I am wondering if there is an easier way to do this? Since it would be 200 lines (raw score can range from 1-200) if I were to use the if/then statement;

 

Sample code:

 

%Macro score;

*Some code to calculate the raw score variable;

Data have;
set fromscoringcodeabove (Keep=ID Rawscore);
run;

Data Standardscoretable;
input Rawscore standardscore;
cards;
1 14.5
2 17.9
3 20.5
4 24.4
;

data want;
merge have (in=a) Standardscoretable;
if a;
by Rawscore;
run;

%mend score;

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
tc
Lapis Lazuli | Level 10 tc
Lapis Lazuli | Level 10

If your'e on a platform w/PIPE support:

 

%macro testio;
Filename in pipe 'echo 1 14.5 2 17.9 3 20.5 4 24.4 ';
Data Standardscoretable; infile in; input Rawscore standardscore@@;
%mend;
%testio;
run;

 

If you go multi-line with the data, make sure each line has a trailing space!

View solution in original post

9 REPLIES 9
PGStats
Opal | Level 21

Use a format (defined with proc format) and the input function to convert raw to standardized scores.

PG
Tpham
Quartz | Level 8

Actually I didn't thikn of that. That might be easier then if/then statements

Tom
Super User Tom
Super User

If you just want to make such a simple dataset then there is no need for CARDS/DATALINES.

data standardscoretable;
  do standardscore=14.5,17.9,20.5,24.4;
    rawscore+1;
    output;
  end;
run;
Tpham
Quartz | Level 8

the dataset is just an example. there are over 200 records 🙂

Tom
Super User Tom
Super User

200 records is nothing. Copy and paste them into your program file.

If you don't want to put in the commas you can use a simple program to generate the list from an existing dataset with the commas between the values and just copy from that little file into your source code.

 

filename list temp;
data _null_;
  set mydataset ;
  file list;
  retain sep '=';
  put sep standardscore;
  sep = ',' ;
run;

Or use a macro variable in your autocall macro. Then you can copy and paste from your source file and not worry about having to insert commas to make it look like code.

%let standardscores=14.5 17.9 20.5 24.4;

data standardscoretable;
 do rawscore=1 to countw(symget('standardscores'),' ');
   standardscore=input(scan(symget('standardscores'),rawscore,' '),32.);
   output;
  end;
run;
KachiM
Rhodochrosite | Level 12

There are several ways. One quick way is given. An Array is used to lookup - giving the Rawscore and to get the corresponding standardscore. This array can hold a maximum of 200 rawscores. In case it is more, you may replace it by the maximum value. Even a million can be held in the array if you want. I have used HAVE to mimic your rawscore data set. Here goes your Macro:

data have;
input ID Rawscore;
datalines;
1 1
2 1
3 2
4 2
5 3
6 4
7 3
;
run;

Data Standardscoretable;
input Rawscore standardscore;
cards;
1 14.5
2 17.9
3 20.5
4 24.4
;
run;

%macro score;
data want;
format ID Rawscore newScore;
   if _N_ = 1 then do;
   array k[200] _temporary_;
      do until(eof);
         set Standardscoretable end = eof;
         k[Rawscore] = standardscore;
      end;
   end;
   set have;
   newScore = k[Rawscore];
drop standardscore;
run;
%mend;

%score;

proc print data = want;
run;

Enjoy the Macro. 

Ksharp
Super User
You can make a text file to contain these CARDS data.
tc
Lapis Lazuli | Level 10 tc
Lapis Lazuli | Level 10

Here's one of those should-I-be-proud-or-ashamed-of-this kludges.  🙂

 

%macro testio;

%let input=
1 14.5
2 17.9
3 20.5
4 24.4
;

filename io "%sysfunc(pathname(work))/workio.txt" lrecl=32767;

data _null_; file io; put "&input";

Data Standardscoretable; infile io; input Rawscore standardscore@@;

%mend;

%testio;
run;

 

I think many of us have at times become obsessed with trying to get the equivalent of CARDS (SAS), SYSIN (MAINFRAME), or HERE DOCUMENTS (UNIX) to play nice with SAS macros.

 

Here's my own Coders' Coder stab at a more general solution from 10+ years ago:

 

A Better SYSIN Than SYSIN: Instream Files on Any Platform

 

I had hoped the new PROC STREAM might work inside macros, but I couldn't figure out a way to get it to work (please correct me if I messed up and there's a way!).

 

Stil, even if it doesn't work inside a macro, a quick glance at some papers Google turned up by Don Henderson and Rick Langston suggests there are some insanely great (or insanely insane!) things you can do with PROC STREAM, so I'll have to check it out.

 

tc
Lapis Lazuli | Level 10 tc
Lapis Lazuli | Level 10

If your'e on a platform w/PIPE support:

 

%macro testio;
Filename in pipe 'echo 1 14.5 2 17.9 3 20.5 4 24.4 ';
Data Standardscoretable; infile in; input Rawscore standardscore@@;
%mend;
%testio;
run;

 

If you go multi-line with the data, make sure each line has a trailing space!

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

What is Bayesian Analysis?

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 9 replies
  • 4744 views
  • 5 likes
  • 6 in conversation