- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I've been struggling with a do loop in SAS and would be grateful for any assistance. This is the data I have:
data have;
input Parameter $ COL1 $ COL2 $;
cards;
Intercept AGE DRINKPATTERN
DRINKPATTERN AGE DRINKPATTERN
DRINKPATTERN AGE DRINKPATTERN
DRINKPATTERN AGE DRINKPATTERN
DRINKPATTERN AGE DRINKPATTERN
FISHLASTWEEK AGE DRINKPATTERN
AGE AGE DRINKPATTERN AGE DRINKPATTERN
AGE AGE DRINKPATTERN AGE DRINKPATTERN
AGE AGE DRINKPATTERN AGE DRINKPATTERN
FISHLASTWEEK*AGE AGE DRINKPATTERN
FISHLASTWEEK*AGE AGE DRINKPATTERN
FISHLASTWEEK*AGE AGE DRINKPATTERN
;
run;
I want to assess whether the string values contained in the variables COL1 or COL2 are evident in the field Parameter and if so assign a value of 2 to the variable TYPE.
The macro I created is below. The problem I am having is that the if statement does not seem to generate and the mprint option highlights this. Any assistance
is greatly appreaciated,
thanks,
%macro ClassIdentifier(value);
data want;
set have;
TYPE = 1;
%do i=1 %to &Value;
%let Varname = COL&i;
%if %index(Parameter, &Varname ) NE 0 %then TYPE = 2;
run;
%end;
%mend;
options mprint;
%ClassIdentifier(2)
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
An alternative;
%macro ClassIdentifier(value);
data want (Drop=i);
set have;
Type=1;
Array C{*} $30. COL:;
Do i=1 To Dim(C);
If Index(Parameter,C{i}) Then Type=2;
Else Type=Min(Type,2);
End;
Run;
%mend;
%ClassIdentifier(value=2)
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Why do you need a macro? You could just create a flag in you read:
data have;
input Parameter $ COL1 $ COL2 $;
flag1=index(parameter,col1); /* Flag for first one */
flag2=index(parameter,col2); /* Flag for second */
cards;
Intercept AGE DRINKPATTERN
DRINKPATTERN AGE DRINKPATTERN
DRINKPATTERN AGE DRINKPATTERN
DRINKPATTERN AGE DRINKPATTERN
DRINKPATTERN AGE DRINKPATTERN
FISHLASTWEEK AGE DRINKPATTERN
AGE AGE DRINKPATTERN AGE DRINKPATTERN
AGE AGE DRINKPATTERN AGE DRINKPATTERN
AGE AGE DRINKPATTERN AGE DRINKPATTERN
FISHLASTWEEK*AGE AGE DRINKPATTERN
FISHLASTWEEK*AGE AGE DRINKPATTERN
FISHLASTWEEK*AGE AGE DRINKPATTERN
;
run;
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Hi, thanks for the responses. I need a loop, (maybe not a macro) as there will be multiple fields all with COL at the beginning.
data have;
input Parameter $ COL1 $ COL2 $;
cards;
Intercept AGE DRINKPATTERN
DRINKPATTERN AGE DRINKPATTERN
DRINKPATTERN AGE DRINKPATTERN
DRINKPATTERN AGE DRINKPATTERN
DRINKPATTERN AGE DRINKPATTERN
FISHLASTWEEK AGE DRINKPATTERN
AGE AGE DRINKPATTERN
AGE AGE DRINKPATTERN
AGE AGE DRINKPATTERN
FISHLASTWEEK*AGE AGE DRINKPATTERN
FISHLASTWEEK*AGE AGE DRINKPATTERN
FISHLASTWEEK*AGE AGE DRINKPATTERN
;
run;
Using the data above, I can create a new field using a data step with the following:
data want;
set have;
Type = 1;
if index(Parameter, col1 ) NE 0 then Type = 2;
run;
I would like this to run in a loop and replace the col1 with col2 etc
the output should have an additional field TYPE that has a value of 2 if the strings in col1 or col2 are found in the field parameter:
Parameter Col1 Col2 Type
Intercept AGE DRINKPATTERN 1
DRINKPATTERN AGE DRINKPATTERN 2
DRINKPATTERN AGE DRINKPATTERN 2
DRINKPATTERN AGE DRINKPATTERN 2
DRINKPATTERN AGE DRINKPATTERN 2
FISHLASTWEEK AGE DRINKPATTERN 1
AGE AGE DRINKPATTERN 2
apologies for omissions previously, I will try the macro with the array, thank you
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
thanks for the responses. I used the array and it works great, thank you. I'm still a bit miffed about the IF statement not functioning in the loop however ... maybe for another day!
Regards,
Michael
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
" I'm still a bit miffed about the IF statement not functioning in the loop however "
are you referring to the line:
%if %index(Parameter, &Varname ) NE 0 %then TYPE = 2;
or the line:
If index(Parameter, col1 ) NE 0 then Type = 2;
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Hi, the line:
%if %index(Parameter, &Varname ) NE 0 %then TYPE = 2;
I managed to get a little help with this and found it was an easy fix, just remove the % symbols as:
if index(Parameter, &Varname ) NE 0 then TYPE = 2;
Works great now. I also implemented the array version as an alternative.
thanks for the response
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Yes, the line
%if %index(Parameter, &Varname ) NE 0 %then TYPE = 2;
was working correctly, your expectations were wrong
You were using macro statements where you should have used data step statements. A common problem when trying to learn and apply macro.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
It will help if you provide an example of what you expect for output.
Did you create a basic data step that provided the desired output before attempting the macro approach? If so, please post that.
If you want to see if the variable Parameter in have contains the text COL1 you want:
if index(Parameter,"COL&I") , no need to create the additional macro variable. You are getting false for the result as the string
Parameter does not contain COL1 or COL2. The macro processor not the data step evaluates the %index function and %if / %then.
Also, the index function is case sensitive so you may want index (upcase(Parameter),"COL&I").
%do I=1 to &value;
if index(Parameter,"COL&I") ne 0 then type=2;
%end;
run;
The if loop should then generate:
if index(Parameter,"COL1") ne 0 then type=2;
if index(Parameter,"COL2") ne 0 then type=2;
Also having the %do %end enclose the Run statement you could be generating at least one Run without a data step associated.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
An alternative;
%macro ClassIdentifier(value);
data want (Drop=i);
set have;
Type=1;
Array C{*} $30. COL:;
Do i=1 To Dim(C);
If Index(Parameter,C{i}) Then Type=2;
Else Type=Min(Type,2);
End;
Run;
%mend;
%ClassIdentifier(value=2)