Here is an illustration of what I mean in my previous message:
data WORK.HAVE;
infile datalines truncover;
input Thing Day ;
datalines;
0 1
0 4
0 11
0 14
0 19
0 28
0 35
0 41
1 48
1 55
;;;;
/*Test with thing positive 1*/
proc sql;
create table want(drop=d) as
select distinct a.*,ifn((a.day<=b.day<=a.day+30)=0,d,a.day<=b.day<=a.day+30) as Early_Warning
from (select *,ifn(max(day)>day+30,0,.) as d from have) a left join have(where=(thing=1)) b
on a.day<=b.day<=a.day+30
order by thing,a.day;
quit;
/*Test with all Thing 0*/
data WORK.HAVE;
infile datalines truncover;
input Thing Day ;
datalines;
0 1
0 4
0 11
0 14
0 19
0 28
0 35
0 41
0 48
0 55
;;;;
proc sql;
create table want(drop=d) as
select distinct a.*,ifn((a.day<=b.day<=a.day+30)=0,d,a.day<=b.day<=a.day+30) as Early_Warning
from (select *,ifn(max(day)>day+30,0,.) as d from have) a left join have(where=(thing=1)) b
on a.day<=b.day<=a.day+30
order by thing,a.day;
quit;
Let's say you know
Then you could:
data WORK.HAVE;
infile datalines truncover;
input Thing Day ;
datalines;
0 1
0 4
0 11
0 14
0 19
0 28
0 35
0 41
1 48
1 55
;;;;
data want;
array possible_days {1:1000} _temporary_ (1000*0);
do until (end_of_thing_eq_1);
set have (where=(thing=1)) end=end_of_thing_eq_1;
do d=day-30 to day;
possible_days{d}=1;
end;
end;
do d=day+1 to 1000;
possible_days{d}=.;
end;
drop d;
do until (end_of_have);
set have end=end_of_have;
early_warning=possible_days{day};
output;
end;
run;
Hi @dcd , @mkeintz 's solution is full proof.
I played mine as I was bored.
Anyways, for want2 , if we can't be sure whether Thing is happening within the next 30 days,
then how come earlywarning is zero upto 0 19 0 assuming all records of thing is 0 as your want2 indicates. What and where am i missing?
data WORK.HAVE;
infile datalines truncover;
input Thing Day ;
datalines;
0 1
0 4
0 11
0 14
0 19
0 28
0 35
0 41
1 48
1 55
;;;;
proc sql;
create table want as
select distinct a.*,(a.day<=b.day<=a.day+30) as Early_Warning
from have a left join have(where=(thing=1)) b
on a.day<=b.day<=a.day+30
order by thing,a.day;
quit;
In want2 early_warning is 0 up to day 19 because we do have info up to day 55 -that is more than 30 days later- that there is no triggering event. In day 28 we don't have info for 30 days -day 55 is only 27 days away- so we can't be sure, hence I'd like a null there.
@dcd Are you aware that my program is intended to produce results satisfying BOTH of your objectives?
I was just clarifying to novinosrin. I only now got the chance to try what you suggested but I'm getting an empty table when the Thing is always 0. Any idea why is that?
Also there is an out of subscript error when Thing happens on say day 10 but that's easy to fix.
Hi @dcd Thank you for clarifying. I am afraid while proc sql syntax can be made to look simple, that condition might warrant another pass or a Cartesian for that matter which would make it inefficient in my opinion. Well I am pleased and glad you have got a datastep solution though
Here is an illustration of what I mean in my previous message:
data WORK.HAVE;
infile datalines truncover;
input Thing Day ;
datalines;
0 1
0 4
0 11
0 14
0 19
0 28
0 35
0 41
1 48
1 55
;;;;
/*Test with thing positive 1*/
proc sql;
create table want(drop=d) as
select distinct a.*,ifn((a.day<=b.day<=a.day+30)=0,d,a.day<=b.day<=a.day+30) as Early_Warning
from (select *,ifn(max(day)>day+30,0,.) as d from have) a left join have(where=(thing=1)) b
on a.day<=b.day<=a.day+30
order by thing,a.day;
quit;
/*Test with all Thing 0*/
data WORK.HAVE;
infile datalines truncover;
input Thing Day ;
datalines;
0 1
0 4
0 11
0 14
0 19
0 28
0 35
0 41
0 48
0 55
;;;;
proc sql;
create table want(drop=d) as
select distinct a.*,ifn((a.day<=b.day<=a.day+30)=0,d,a.day<=b.day<=a.day+30) as Early_Warning
from (select *,ifn(max(day)>day+30,0,.) as d from have) a left join have(where=(thing=1)) b
on a.day<=b.day<=a.day+30
order by thing,a.day;
quit;
This works perfectly, thanks!
I tried adding a counter to make it work in both cases, instead it stopped working in either one.
data want;
array possible_days {1:1000} _temporary_ (1000*0);
events=0;
do until (end_of_have);
set have end=end_of_have;
if Thing=1 then do;
events+1;
d=max(day-30, 1) to day;
possible_days{d}=1;
end;
end;
if events=0 then do;
d=day-29 to 1000;
possible_days{d}=.;
end;
drop d;
drop events;
do until (end_of_have);
set have end=end_of_have;
early_warning=possible_days{day};
output;
end;
run;
However the code seems like it should work? (more likely I'm just clueless I guess)
The log locates the errors in the
d=max(day-30, 1) to day;
d=day-29 to 1000;
lines saying 'syntax error' and 'expecting arithmetic operator' respectively.
Available on demand!
Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.
SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.
Find more tutorials on the SAS Users YouTube channel.