Hi all,
I have written the following code to translate code values to labels in my data:
%put incident_subject_codes=&is_codes;
%put incident_subject_labels=&is_labels;
%macro get_is_label(code);
%let codeCount = %sysfunc(countw(&is_codes.,' '));
%let label_value=;
%do i=1 %to &codeCount;
%let code_value=%scan(&is_codes.,&i.,' ');
%put CODE=&code;
%put CODE_VALUE=&code_value;
%if &code_value=&code %then %do;
%let label_value=%scan(&is_labels.,&i.,' ');
%end;
%end;
&label_value
%mend;
data work.incident;
set vidata.Incident(obs=1);
incident_subject="%get_is_label(incident_subject);";
run;
Could some please advice, how I can pass the current value of the incident_subject in my macro?
The code above passes in text "incident_subject". If I remove the quotes:
incident_subject=%get_is_label(incident_subject);
the label is returned by the macro, however it is not assigned to incident_subject, but created as a new column instead the label being the column name.
Any suggestions on how I could achieve the desired result?
Many thanks in advance,
Olli
Big thanks for the pointers.
I figured the last part out.
This is the code that does what I am after:
data work.is_fmt(keep=start label fmtname);
set work.is_fmt;
fmtname='$IS_FTM';
run;
proc format library=work cntlin=work.is_fmt;
run;
data work.incident;
set vidata.Incident;
incident_subject=put(incident_subject, $IS_FTM.);
run;
Honestly, I don't understand what you are trying to do.
However, when you write
incident_subject="%get_is_label(incident_subject);";
this is meaningless because incident_subject is treated as a text string that is exactly equal to incident_subject and that's certainly not a useful thing for your macro %get_is_label to work on. Perhaps you want to use macro variable &incident_subject, but even there, the macro variable &incident_subject has never been given a value, so that won't work either.
So, please explain what you are trying to do.
Sorry for not explaining this properly.
My data includes some numeric code values such as the incident_subject column. I have two space separated multi value macro variables to contain the list of all possible code values and their correspondent human readable labels (is_codes and is_labels). The macro I have written is trying to replace the code value is the correct label in my data, hence I need to pass in the current code value.
Hope the above makes more sense.
If I use this with hard coded code values such as:
incident_subject="%get_is_label(16);";
I get the result I am after. However, I am unable to figure out how I can replace the 16 above with a dynamic value from incident_subject.
Give us specific examples, even if they are fake, so I can see what you start with, and what you want the macro to produce.
A better approach would be to create a SAS format for the lookup from code to label. That doesn't use macro at all.
It might help if showed some actual values stuff you are passing to the macro and what you expect it to return, better with an example data set in the form of data set code and what the data set should look like afterwards.
I suspect that a macro is not actually what you want if you are expecting to use data step variables anywhere.
Ok, below is a full example for what I am trying to do with some sample data:
%let is_codes=10 20 30 40;
%let is_labels=Label1 Label2 Label3 Label4;
data work.incident;
input incident_subject $;
datalines;
10
40
;
run;
%macro get_is_label(code);
%let codeCount = %sysfunc(countw(&is_codes.,' '));
%let label_value=;
%do i=1 %to &codeCount;
%let code_value=%scan(&is_codes.,&i.,' ');
%put CODE=&code;
%put CODE_VALUE=&code_value;
%if &code_value=&code %then %do;
%let label_value=%scan(&is_labels.,&i.,' ');
%end;
%end;
&label_value
%mend;
data work.incident;
set work.incident;
incident_subject="%get_is_label(incident_subject);";
run;
The outcome I am hoping from the above is the codes to be replaced with the labels for the incident_subject value within work.incident.
proc format;
value $MyLabel
'10' = 'Label'
'20' = 'Label2'
'30' = 'Label3'
'40' = 'Label4'
;
run;
data want;
incident_subject = '10';
incident_label = put(incident_subject, $MyLabel.);
put _all_;
run;
Thanks for this, looks great.
Final question.The code, label pairs are originally in a another data set. How do I populate the format structure from that data set? I was using before proc sql to read them into macro variables.
@ojaro wrote:
Thanks for this, looks great.
Final question.The code, label pairs are originally in a another data set. How do I populate the format structure from that data set? I was using before proc sql to read them into macro variables.
If you show us (a portion of) this data set where the code and labels exist, we can probably work with that. You can use the CNTLIN option of PROC FORMAT to turn your data set into formats that you can use, again without macros.
Big thanks for the pointers.
I figured the last part out.
This is the code that does what I am after:
data work.is_fmt(keep=start label fmtname);
set work.is_fmt;
fmtname='$IS_FTM';
run;
proc format library=work cntlin=work.is_fmt;
run;
data work.incident;
set vidata.Incident;
incident_subject=put(incident_subject, $IS_FTM.);
run;
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.