DATA Step, Macro, Functions and more

Don't know what's wrong with my (simple) macro function

Accepted Solution Solved
Reply
Contributor gsk
Contributor
Posts: 25
Accepted Solution

Don't know what's wrong with my (simple) macro function

First, I'm creating a new dataset with new names for some variables.

Dropping unwanted variables


data q2;
set METSdata.LABA_669;
rename LABA11 = SODIUM 
LABA15 = CALCIUM 
LABA16 = PROTEIN 
LABA5 = HDL
LABA6 = LDL;
keep BID VISIT LABA11 LABA15 LABA16 LABA5 LABA6;
run;

proc print data=q2 (obs=20); run;

 

The dataset contains a lot of . values. I want to categorize numeric&. values into within a range and outside of the range, by labeling them Missing, Low, Normal (within range), and High. I'm using different categories for different variables (such as sodium (SOD), calcium(CAL), etc)


proc format;
value SOD
. = 'Missing'
Low-129 = 'Low'
130<-<150 = 'Normal'
151-High = 'High';
run;

 

proc format;
value CAL
. = 'Missing'
Low-7= 'Low'
8<-<10.5 = 'Normal'
11-High = 'High';
run;

 

proc format;
value PRO
. = 'Missing'
Low-5 = 'Low'
6<-<9 = 'Normal'
10-High = 'High';
run;

 

proc format;
value HDL
. = 'Missing'
Low-24 = 'Low'
25-High = 'Normal';
run;

 

proc format;
value LDL
. = 'Missing'
Low-200 = 'Normal'
201-High = 'High';
run;

 

Then onto macro function - I'm creating a function such that if I type Sodium, Calcium, etc, the function will create a categorical variable, which is a categorized version of the numeric&. values accordingly to the input name, then print BID VISIT &name. and valcat variables of that input name. 


%macro analyte(name=);
data &name.;
set q2;
valcat = &name.;

%if upcase(&name.) = SODIUM %then
%put %sysfunc(putn(&valcat, SOD.));

%if upcase(&name.) = CALCIUM %then
%put %sysfunc(putn(&valcat, CAL.));


%if upcase(&name.) = PROTEIN %then
%put %sysfunc(putn(&valcat, PRO.));


%if upcase(&name.) = HDL %then
%put %sysfunc(putn(&valcat, HDL.));


%else upcase(&name.) = LDL
%put %sysfunc(putn(&valcat, LDL.));


keep BID VISIT &name. valcat;
run;

proc print data = &name.; run;
%macro analyte;

%analyte(sodium);

 

I don't get any output from this macro function though. Any help please? 

 

Thank you in advance! 


Accepted Solutions
Solution
‎01-19-2018 01:50 AM
Super User
Posts: 2,061

Re: Don't know what's wrong with my (simple) macro function

Ok good. This is where you need a macro %if %then %else

 

%macro analyte(analyte=sodcat);
data want;
set q2;
where upcase(&analyte) in ('LOW','HIGH');

%if &analyte eq sodcat %then
%str(keep BID VISIT Sodium &analyte;);
%else %if &analyte eq calcat %then
%str(keep BID VISIT Calcium &analyte;);
%else %if &analyte eq procat %then 
%str(keep BID VISIT Protein &analyte;);
%else %if &analyte eq hdlcat %then 
%str(keep BID VISIT hdl &analyte;);
%else
%str(keep BID VISIT ldl &analyte;);
run;

proc print data =want;
run;
%mend analyte;

watch out for my typo based syntax errors just in case

View solution in original post


All Replies
Super User
Posts: 2,061

Re: Don't know what's wrong with my (simple) macro function

[ Edited ]

I'm afraid you have got the entire concept of macro timing vs datastep timing completely mixed up besides syntax issues such as missing double quotes in macro reference in a datastep. Simple or complex doesn't matter if it's timing issue. 

 

 

Contributor gsk
Contributor
Posts: 25

Re: Don't know what's wrong with my (simple) macro function

Posted in reply to novinosrin
Could you help identify where to start/fix?
Super User
Posts: 2,061

Re: Don't know what's wrong with my (simple) macro function

First off, You can get a super efficient code from experts here than to fix a code that may deemed not good. So, If you let the community know your needs with samples of your datasets, it's easy for them to give you the best possible solutions.

 

Anyway, since the question relates to your code, I have commented a bit to give you a heads up

%macro analyte(name=);
data &name.;
set q2;
valcat = "&name.";/* this should be in double quotes*/
/*%if is macro language statement and not a sas datastep execution statement*/
%if upcase(&name.) = SODIUM %then
%put %sysfunc(putn(&valcat, SOD.));	/*valcat is a datastep variable and not a macro variable and the same goes for all statements*/

%if upcase(&name.) = CALCIUM %then
%put %sysfunc(putn(&valcat, CAL.));


%if upcase(&name.) = PROTEIN %then
%put %sysfunc(putn(&valcat, PRO.));


%if upcase(&name.) = HDL %then
%put %sysfunc(putn(&valcat, HDL.));


%else upcase(&name.) = LDL
%put %sysfunc(putn(&valcat, LDL.));


keep BID VISIT &name. valcat;
run;

proc print data = &name.; run;
%macro analyte;

%analyte(sodium);
Contributor gsk
Contributor
Posts: 25

Re: Don't know what's wrong with my (simple) macro function

capture.JPG

My dataset looks like this. I want to make a macro function that would take in a name of an analyte and print out all the observations with "Low" or "High" for that analyte.  

Super User
Posts: 2,061

Re: Don't know what's wrong with my (simple) macro function

You wrote-"My dataset looks like this. I want to make a macro function that would take in a name of an analyte and print out all the observations with "Low" or "High" for that analyte."

Ok, Thank you. So it looks like your dataset has variables SODCAT--LDLCAT that are already formatted using the formats defined in your list of proc format statements. If this is really the case, I see no big deal:

 

 

%macro analyte(analyte=sodcat);

data want;

set have;

where upcase(&analyte)='LOW' or upcase(&analyte)='HIGH';

run;

proc print data =want;

run;

%mend analyte;

%analyte

/*macro var analyte takes the value as user assigned for each analyte such as sodcat, calcat, procat etc*/

 

 

Contributor gsk
Contributor
Posts: 25

Re: Don't know what's wrong with my (simple) macro function

Posted in reply to novinosrin

Thanks a lot, that's neat!

 

Now I've been trying to keep variables including the original values and categorical variable of the analyte by doing below;  I just added the italicized part and it doesn't work. I get errors saying that the statements are not valid or used out of proper order. Why am I getting these errors? 


%macro analyte(analyte=sodcat);
data want;
set q2;
where upcase(&analyte) in ('LOW','HIGH');

if &analyte eq sodcat then
keep BID VISIT Sodium &analyte;
else if &analyte eq calcat then
keep BID VISIT Calcium &analyte;
else if &analyte eq procat then
keep BID VISIT Protein &analyte;
else if &analyte eq hdlcat then
keep BID VISIT hdl &analyte;
else
keep BID VISIT ldl &analyte;
run;

proc print data =want;
run;
%mend analyte;

%analyte

 

 

Solution
‎01-19-2018 01:50 AM
Super User
Posts: 2,061

Re: Don't know what's wrong with my (simple) macro function

Ok good. This is where you need a macro %if %then %else

 

%macro analyte(analyte=sodcat);
data want;
set q2;
where upcase(&analyte) in ('LOW','HIGH');

%if &analyte eq sodcat %then
%str(keep BID VISIT Sodium &analyte;);
%else %if &analyte eq calcat %then
%str(keep BID VISIT Calcium &analyte;);
%else %if &analyte eq procat %then 
%str(keep BID VISIT Protein &analyte;);
%else %if &analyte eq hdlcat %then 
%str(keep BID VISIT hdl &analyte;);
%else
%str(keep BID VISIT ldl &analyte;);
run;

proc print data =want;
run;
%mend analyte;

watch out for my typo based syntax errors just in case

Contributor gsk
Contributor
Posts: 25

Re: Don't know what's wrong with my (simple) macro function

Posted in reply to novinosrin
Thank you so much!! I hope I can get better..
Super User
Super User
Posts: 9,840

Re: Don't know what's wrong with my (simple) macro function

Why not use CDISC standards on your data?  These have been carefully thought out over years to provide a simple functional model for your data.  In this instance, each of you lab parameters would become rows with result, unit etc. information on it.  Then you only need simple datasteps to process lots of observations.  Working with transposed data is always going to make your code far more complicated, harder to maintain.

☑ This topic is solved.

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

Discussion stats
  • 9 replies
  • 229 views
  • 6 likes
  • 3 in conversation