Help using Base SAS procedures

Is there a workaround to set cards statement in macro?

Accepted Solution Solved
Reply
Contributor
Posts: 58
Accepted Solution

Is there a workaround to set cards statement in macro?

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;

 

 


Accepted Solutions
Solution
‎07-19-2016 11:42 AM
Frequent Contributor
Frequent Contributor
Posts: 75

Re: Is there a workaround to set cards statement in macro? (Here's My Kludge!)

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


All Replies
Respected Advisor
Posts: 4,651

Re: Is there a workaround to set cards statement in macro?

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

PG
Contributor
Posts: 58

Re: Is there a workaround to set cards statement in macro?

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

Super User
Super User
Posts: 6,500

Re: Is there a workaround to set cards statement in macro?

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;
Contributor
Posts: 58

Re: Is there a workaround to set cards statement in macro?

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

Super User
Super User
Posts: 6,500

Re: Is there a workaround to set cards statement in macro?

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;
Super Contributor
Posts: 254

Re: Is there a workaround to set cards statement in macro?

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. 

Super User
Posts: 9,681

Re: Is there a workaround to set cards statement in macro?

You can make a text file to contain these CARDS data.
Frequent Contributor
Frequent Contributor
Posts: 75

Re: Is there a workaround to set cards statement in macro? (Here's My Kludge!)

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.

 

Solution
‎07-19-2016 11:42 AM
Frequent Contributor
Frequent Contributor
Posts: 75

Re: Is there a workaround to set cards statement in macro? (Here's My Kludge!)

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!

☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

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