May I know how can we simplify this step? Multiple IF blocks are confusing and also the retain statement. If we cant simplify this step, can someone explain this code in simple terms? I understand the SAS functions but I'm not getting the whole picture here.
DATA WORK.BASELINE; SET WORK.BASELINE_; BASSTRTM2 = INPUT(substr(BSSTRTM,1,2)||':'||substr(BSSTRTM,4,2)||':'||SUBSTR(BSSTRTM,7,2),TIME5.); BASFINTM2 = INPUT(substr(BASFINTM,1,2)||':'||substr(BASFINTM,4,2)||':'||SUBSTR(BASFINTM,7,2),TIME5.); BASSTRTDTTM = DHMS(BAS_STRT_DT,0,0,BASSTRTM2); BASFINDTTM = DHMS(BAS_FINISH_DT,0,0,BASFINTM2); POSTDTTM = DHMS(POSTNG_DT,0,0,0); BASEHRS = INTCK('HOURS',BASSTRTDTTM,BASFINDTTM,'continuous'); IF BASEHRS < 1 THEN BASEHRS = 1; IF BAS_STRT_DT = POSTNG_DT THEN DO; IF DAYS_OF_PO = 1 THEN DO; INITIALHRS = BASEHRS; NEWBASEHRS=INITIALHRS; DAYHRS = INITIALHRS; END; ELSE DO; INITIALHRS = INTCK('HOURS',BASSTRTDTTM,DHMS(bas_strt_dt,24,0,0),'CONTINUOUS'); DAYHRS = INTCK('HOURS',BASSTRTDTTM,DHMS(bas_strt_dt,24,0,0),'CONTINUOUS'); NEWBASEHRS=BASEHRS-INITIALHRS; END; END; ELSE IF BAS_FINISH_DT = POSTNG_DT THEN DO; DAYHRS = NEWBASEHRS; END; ELSE DO; DAYHRS = 24; NEWBASEHRS=NEWBASEHRS-DAYHRS; END; RETAIN INITIALHRS; RETAIN NEWBASEHRS; RUN;
A question: why use
ELSE IF BAS_FINISH_DT = POSTNG_DT THEN
DO;
DAYHRS = NEWBASEHRS;
END;
instead of
ELSE IF BAS_FINISH_DT = POSTNG_DT THEN DAYHRS = NEWBASEHRS;
You apparently can't drop the RETAIN statements, because there are some conditions in which a new value for INITIALHRS or NEWBASEHRS will not be calculated, and you apparently want to carry forward the previous values instead of resetting them to missing..
Now, if you're really just trying to reduce lines of code, you could change
IF BAS_STRT_DT = POSTNG_DT THEN
DO;
IF DAYS_OF_PO = 1 THEN
DO;
INITIALHRS = BASEHRS;
NEWBASEHRS=INITIALHRS;
DAYHRS = INITIALHRS;
END;
ELSE
DO;
INITIALHRS = INTCK('HOURS',BASSTRTDTTM,DHMS(bas_strt_dt,24,0,0),'CONTINUOUS');
DAYHRS = INTCK('HOURS',BASSTRTDTTM,DHMS(bas_strt_dt,24,0,0),'CONTINUOUS');
NEWBASEHRS=BASEHRS-INITIALHRS;
END;
END;
to
IF BAS_STRT_DT = POSTNG_DT THEN DO;
INITIALHRS= ifn(days_of_po=1,BASEHRS ,INTCK('HOURS',BASSTRTDTTM,DHMS(bas_strt_dt,24,0,0),'CONTINUOUS'));
DAYHRS = ifn(days_of_po=1,INITIALHRS,INTCK('HOURS',BASSTRTDTTM,DHMS(bas_strt_dt,24,0,0),'CONTINUOUS'));
NEWBASEHRS= ifn(days_of_po=1,INITIALHRS,BASEHRS-INITIALHRS);
END;
But it would take a little longer to run. I wouldn't recommend it.
Note: This comment was intended to be a response to the OP (@pink_poodle), but was erroneously issued as a reply to @David_Billa
Example data. Source and expected result and possibly a description of the problem to really provide any meaningful difference in the code.
This stuff looks like it would like to read a time value that was written with something other than : as the original delimiter.
Without an example of the source value not much that can be suggested.
BASSTRTM2 = INPUT(substr(BSSTRTM,1,2)||':'||substr(BSSTRTM,4,2)||':'||SUBSTR(BSSTRTM,7,2),TIME5.); BASFINTM2 = INPUT(substr(BASFINTM,1,2)||':'||substr(BASFINTM,4,2)||':'||SUBSTR(BASFINTM,7,2),TIME5.);
I don't see much way to address your "ifs". Your "multiple" are pretty much 2 at each point. So not much to reduce.
This code apparently is calculating some sort of offset from some date condition that is reset when one of the values reaches 1. The RETAIN means values available from the first reset are available until reset. Not much of any other way if you need those variables for calculations on the right side of the =. I am not sure that the Initialhrs needs to be retained from the code I see but the Newbasehrs is used to set Dayhrs.
It would help a lot if you could not only provide some sample input and output data, but also explain in plain English the process this DATA step is part of. Where is this data being sourced and what is it being used for? Not having any business context makes it even harder to figure out what it is doing.
A question: why use
ELSE IF BAS_FINISH_DT = POSTNG_DT THEN
DO;
DAYHRS = NEWBASEHRS;
END;
instead of
ELSE IF BAS_FINISH_DT = POSTNG_DT THEN DAYHRS = NEWBASEHRS;
You apparently can't drop the RETAIN statements, because there are some conditions in which a new value for INITIALHRS or NEWBASEHRS will not be calculated, and you apparently want to carry forward the previous values instead of resetting them to missing..
Now, if you're really just trying to reduce lines of code, you could change
IF BAS_STRT_DT = POSTNG_DT THEN
DO;
IF DAYS_OF_PO = 1 THEN
DO;
INITIALHRS = BASEHRS;
NEWBASEHRS=INITIALHRS;
DAYHRS = INITIALHRS;
END;
ELSE
DO;
INITIALHRS = INTCK('HOURS',BASSTRTDTTM,DHMS(bas_strt_dt,24,0,0),'CONTINUOUS');
DAYHRS = INTCK('HOURS',BASSTRTDTTM,DHMS(bas_strt_dt,24,0,0),'CONTINUOUS');
NEWBASEHRS=BASEHRS-INITIALHRS;
END;
END;
to
IF BAS_STRT_DT = POSTNG_DT THEN DO;
INITIALHRS= ifn(days_of_po=1,BASEHRS ,INTCK('HOURS',BASSTRTDTTM,DHMS(bas_strt_dt,24,0,0),'CONTINUOUS'));
DAYHRS = ifn(days_of_po=1,INITIALHRS,INTCK('HOURS',BASSTRTDTTM,DHMS(bas_strt_dt,24,0,0),'CONTINUOUS'));
NEWBASEHRS= ifn(days_of_po=1,INITIALHRS,BASEHRS-INITIALHRS);
END;
But it would take a little longer to run. I wouldn't recommend it.
Note: This comment was intended to be a response to the OP (@pink_poodle), but was erroneously issued as a reply to @David_Billa
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.