I use the following macro to count certain events within observations. The data structure is:
ID
Index_date
Event_1_type
Event_1_date
Event_1_drug
--
Event_4_type
Event_4_date
Event_4_drug
ep denotes certain (combined) endpoints: A, B and C.
End point A corresponds to event type 1
End point B corresondes to event type 2 and 3
End point C corresponds to event type 1,2, 3 and 4.
%macro count1(all_eps);
%let k=1;
%let ep = %scan(&all_eps, &k);
%do %while("&ep" NE "");
*/ I assume I have to put some code here to get it working */
EP_&ep._nr = 0;
EP_&ep._ondrug =0;
EP_&ep._offdrug = 0;
%do i=4 %to 1 %by -1;
If Event_&i._type IN(&eventtype.) then
do;
EP_&ep._nr = EP_&ep._nr+1;
if Event_&i._drug = 1 then
do;
EP_&ep._ondrug = EP_&ep._ondrug +1;
end;
Else
do;
EP_&ep._offdrug = EP_&ep._offdrug +1;
end;
end;
If (EP_&ep._ondrug+EP_&ep._offdrug) ne EP_&ep._nr then
do;
Put 'WARNING: missing drug use information'/ ID=//;
end;
%let k = %eval(&k + 1);
%let ep = %scan(&all_eps, &k);
%end;
%mend count1;
%count1(A B C);
run;
What I can't seem to get working is to let '&eventtype.' that is used as the arguments for the IN expression be either '1', '2,3' or ; '1,2,3,4; ; pending on the current value of ep. It has to be something like, but I can't get in working within the macro;
If ep = A then do;
eventtype = 1
end;
else if ep = B then do;
eventtype = %str(2,3);
end;
else if ep = C then do;
eventtype = %str(1,2,3,4);
end;
Thank you for your help!
I've found it myself. I've added the code
%if %sysevalf(&ep = A) %then
%do;
%let eventtype = 1;
%end;
%ELSE %if %sysevalf(&ep = B) %then
%do;
%let eventtype = %str(2,3);
%end;
%ELSE %if %sysevalf(&ep = C) %then
%do;
%let eventtype = %str(1,2,3,4);
%end;
Limit your scenario to minimum together with the MLOGIC SYMBOLGEN MPRINT options.
I'm sorry, I don't quite understand. Why do you want me to run with these options? Do you mean as a debug technique? Or do you want to see the logs with these options?
If this is used as part of a datastep I'd look very closely if I need some of this macro coding.
The loop with seems to be very tied to some fixed variables Event_1_type,Event_2_type,Event_3_type and Event_4_type which makes me think that loop is a likely candidate for an array process.
Is your data structure actually a single column (variable) with those types of values or are those just the variable names?
Can you provide a few rows of data, a description of what your are attempting and an example of what the output for those rows of data would look like.
It is very hard to make much suggestion regarding &eventtype as you don't show where it is assigned or created.
Thanks.
What actually happens in each of the 4 do loops is a bit more elaborate than the sample I provided (but that works). Below a few rows of data (limited to Event_3 and Endpoint B, for brevity)
OBS | Event_1_type | Event_1_drug | Event_2_type | Event_2_drug | Event_3_type | Event_3_drug |
1 | 2 | . | . | . | . | . |
2 | 2 | 0 | 1 | 1 | 1 | 0 |
3 | 3 | 0 | 2 | 0 | 3 | 0 |
4 | 4 | 0 | . | . | . | . |
5 | 1 | 0 | . | . | . | . |
What I want is:
OBS | Event_1_type | Event_1_drug | Event_2_type | Event_2_drug | Event_3_type | Event_3_drug | EP_A | EP_A_ondrug | EP_A_offdrug | EP_B | EP_B_ondrug | EP_B_offdrug |
1 | 2 | 0 | . | . | . | . | 0 | 0 | 0 | 1 | 0 | 1 |
2 | 1 | 0 | 1 | 1 | 1 | 0 | 3 | 1 | 2 | 0 | 0 | 0 |
3 | 3 | 0 | 2 | 0 | 3 | 0 | 0 | 0 | 0 | 3 | 0 | 0 |
4 | 4 | 0 | . | . | . | . | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 1 | 0 | 3 | 0 | . | . | 1 | 0 | 1 | 1 | 0 | 0 |
The first event for case 1 was 'type 2', which is part of endpoint B. It was not while using the drug; so EP_B_offdrug = 1 and EP_B_ondrug = 0.
Case 2 had 3 events, all from 'type 1'. Type 1 is part of endpoint A. The second one was while using the drug, the other two not, hence EP_A_ondrug = 1 and EP_A_offdrug = 2
Case 4 had a type 4 event, which is not part of endpoint A or B, hence the zero's.
It is very hard to make much suggestion regarding &eventtype as you don't show where it is assigned or created.
Sorry about that. I've removed the syntax in which I tried to assign it, since it didn't work. You can see my comment on where it was. I want to link a certain endpoint with a string(?) of numbers to be put in as arguments for the IN in line If Event_&i._type IN(&eventtype.) then.
To put it differently, I want this (very much shortened, there are more endpoints and more eventtypes) to happen:
while ep = | eventtype = | submitted code |
---|---|---|
A | 1 | ... If Event_&i._type IN(1) then .... |
B | 2,3 | ... If Event_&i._type IN(2,3) then ... |
C | 1,2,3,4 | ... If Event_&i._type IN(1,2,3,4) then ... |
Where the value of the eventtype macro variable are used to see if Event_&i._type corresponds to the event types I'm looking for.
I've found it myself. I've added the code
%if %sysevalf(&ep = A) %then
%do;
%let eventtype = 1;
%end;
%ELSE %if %sysevalf(&ep = B) %then
%do;
%let eventtype = %str(2,3);
%end;
%ELSE %if %sysevalf(&ep = C) %then
%do;
%let eventtype = %str(1,2,3,4);
%end;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.