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

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! 

1 ACCEPTED SOLUTION

Accepted Solutions
novinosrin
Tourmaline | Level 20

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

9 REPLIES 9
novinosrin
Tourmaline | Level 20

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. 

 

 

gsk
Obsidian | Level 7 gsk
Obsidian | Level 7
Could you help identify where to start/fix?
novinosrin
Tourmaline | Level 20

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);
gsk
Obsidian | Level 7 gsk
Obsidian | Level 7

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.  

novinosrin
Tourmaline | Level 20

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*/

 

 

gsk
Obsidian | Level 7 gsk
Obsidian | Level 7

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

 

 

novinosrin
Tourmaline | Level 20

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

gsk
Obsidian | Level 7 gsk
Obsidian | Level 7
Thank you so much!! I hope I can get better..
RW9
Diamond | Level 26 RW9
Diamond | Level 26

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.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

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