I am struggling with quite a simple task.
Below is a sample of my data, I have a bunch of IDs and periods, with period_1 reflecting the value 1 week before, period_2 the value 2 weeks before and so on...
data have;
infile datalines delimiter='|' missover;
input id (period_1 period_2 period_3 period_4 period_5 period_6) (:$3.);
datalines;
1||NO|||NO|
2|NO||NO|NO||
3|YES|YES|YES|||
4|NO|YES|NO|YES|YES|NO
5|NO|YES|NO|NO|YES|YES
6||NO|YES|NO|YES|YES
7|YES|||||
8|YES||NO|NO|YES|
9|YES|YES|NO|NO|NO|
10|NO|NO|NO|YES|YES|
11|NO|YES| |NO|NO|NO
;
+----+----------+----------+----------+----------+----------+----------+
| id | period_1 | period_2 | period_3 | period_4 | period_5 | period_6 |
+----+----------+----------+----------+----------+----------+----------+
| 1 | NO | NO | | | | |
| 2 | NO | NO | NO | | | |
| 3 | YES | YES | YES | | | |
| 4 | NO | YES | NO | YES | YES | NO |
| 5 | NO | YES | NO | NO | YES | YES |
| 6 | NO | YES | NO | YES | YES | |
| 7 | YES | | | | | |
| 8 | YES | NO | NO | YES | | |
| 9 | YES | YES | NO | NO | NO | |
| 10 | NO | NO | NO | YES | YES | |
| 11 | NO | YES | | NO | NO | NO |
+----+----------+----------+----------+----------+----------+----------+
I want to compute a flag FINAL taking into account the last 6 weeks (period_) columns as such:
- If 2 consecutive periods are YES then the final flag should be Y
- If 3 consecutive periods are NO then the final flag should be N
- If both are present (2 consecutive periods are YES and 3 consecutive periods are NO) the most recent condition should be taken into account (e.g.
period_1andperiod_2are YES butperiod_3,period_4andperiod_5are NO, then final flag should be Y). - Final flag is empty if there are no consecutive periods that are YES or NO.
I have tried the following
data want;
set have;
length final $1.;
if period_1 = 'YES' then
do;
if period_2 = 'YES' then
window0= 'E';
else window0 = '';
end;
if period_2 = 'YES' then
do;
if period_3 = 'YES' then
window1 = 'E';
else window1 = '';
end;
if period_3 = 'YES' then
do;
if period_4 = 'YES' then
window2 = 'E';
else Period2 = '';
end;
if period_4 = 'YES' then
do;
if period_5 = 'YES' then
window3 = 'E';
else window3 = '';
end;
if period_5 = 'YES' then
do;
if period_6 = 'YES' then
window4 = 'E';
else window4 = '';
end;
if window0 = 'E' OR window1 = 'E' OR window2 = 'E' then final = 'Y'; /* at least 2 consecutive YES */
else if window3 = 'E' AND (period_1 = 'YES' or period_2 = 'YES' ) then final = 'Y'; /* cannot be 3 consecutive NO so flag must be Y */
else if window4 = 'E' AND (period_2 = 'YES' or period_3 = 'YES' ) then final = 'Y'; /* same as above */
else final = 'N';
if cmiss(of period_:) in (5,6) then final = ''; /* need at least 2 non-empty period in order to compute final flag */
if cmiss(of period_:) = 4 and whichc('YES', of period_:) in (0,1) then final = ''; /* need at least 2 YES if 4 periods missing to compute final */
run;
+----+----------+----------+----------+----------+----------+----------+-------+
| ID | PERIOD_1 | PERIOD_2 | PERIOD_3 | PERIOD_4 | PERIOD_5 | PERIOD_6 | FINAL |
+----+----------+----------+----------+----------+----------+----------+-------+
| 1 | NO | NO | | | | | |
| 2 | NO | NO | NO | | | | N |
| 3 | YES | YES | YES | | | | Y |
| 4 | NO | YES | NO | YES | YES | NO | Y |
| 5 | NO | YES | NO | NO | YES | YES | Y |
| 6 | NO | YES | NO | YES | YES | | Y |
| 7 | YES | | | | | | |
| 8 | YES | NO | NO | YES | | | N |
| 9 | YES | YES | NO | NO | NO | | Y |
| 10 | NO | NO | NO | YES | YES | | N |
+----+----------+----------+----------+----------+----------+----------+-------+
Not only does it not handle properly the case of id = 8, I wonder if there is a better way of tackling this problem, perhaps with window functions across columns?
