BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Daniel_Tan
Fluorite | Level 6

I am trying to identify "valid" defaulted borrowers from the default listing span from 2012 to 2019. If a borrower re-default within the default's tracking period (win_end_date) then that particular default observation need to be removed. On contrary, If a borrower redefault after expiry of tracking period then that default event will be recognised as "valid" again.   

 

Here is my sample and expected results:

 

Raw Data   
Cust_NODEF_DATEWin_End_DateRemark
1010621231-Dec-1231-Dec-141st Default (tracked performance up to 24 momths)
1010621231-Dec-1331-Dec-15Overlapped with 1st Default  tracking period (Re-Defaulted  within tracking periods of 1st Default)
1010621231-Dec-1431-Dec-16Overlapped with 1st Default  tracking period (Re-Defaulted  within tracking periods of 1st Default)
1010621231-Dec-1531-Dec-172nd Default (happen after expiry of tracking period of 1st Default)
1010621231-Dec-1731-Dec-19Overlapped with 2nd Default  tracking period (Re-Defaulted  within tracking periods of 2nd Default)
1010621231-Dec-1831-Dec-203rd Default
1037880330-Jun-1430-Jun-161st Default
1037880331-Dec-1531-Dec-17Overlapped with 1st Default  tracking period (Re-Defaulted  within tracking periods of 1st Default)
    
Expected Output   
Cust_NODEF_DATEWin_End_Date 
1010621231-Dec-1231-Dec-14 
1010621231-Dec-1531-Dec-17 
1010621231-Dec-1831-Dec-20 
1037880330-Jun-1430-Jun-16 
1 ACCEPTED SOLUTION

Accepted Solutions
ketpt42
Quartz | Level 8
data have;

format cust_no 8. def_date win_end_date date9.;
input cust_no :8. def_date :date11. win_end_date :date11.;
datalines;
10106212    31-Dec-12   31-Dec-14   
10106212    31-Dec-13   31-Dec-15   
10106212    31-Dec-14   31-Dec-16   
10106212    31-Dec-15   31-Dec-17   
10106212    31-Dec-17   31-Dec-19   
10106212    31-Dec-18   31-Dec-20   
10378803    30-Jun-14   30-Jun-16   
10378803    31-Dec-15   31-Dec-17   
;
run;

data want;
    set have;
    by cust_no;
    
    retain curr_win_end_date;
    
    if first.cust_no  or def_date gt curr_win_end_date then curr_win_end_date=win_end_date;
    else if not first.cust_no and def_date le curr_win_end_date then delete;
    
    drop curr_win_end_date;
run;
cust_no	        def_date	win_end_date	
10106212	31DEC2012	31DEC2014
10106212	31DEC2015	31DEC2017
10106212	31DEC2018	31DEC2020
10378803	30JUN2014	30JUN2016

View solution in original post

4 REPLIES 4
ketpt42
Quartz | Level 8
data have;

format cust_no 8. def_date win_end_date date9.;
input cust_no :8. def_date :date11. win_end_date :date11.;
datalines;
10106212    31-Dec-12   31-Dec-14   
10106212    31-Dec-13   31-Dec-15   
10106212    31-Dec-14   31-Dec-16   
10106212    31-Dec-15   31-Dec-17   
10106212    31-Dec-17   31-Dec-19   
10106212    31-Dec-18   31-Dec-20   
10378803    30-Jun-14   30-Jun-16   
10378803    31-Dec-15   31-Dec-17   
;
run;

data want;
    set have;
    by cust_no;
    
    retain curr_win_end_date;
    
    if first.cust_no  or def_date gt curr_win_end_date then curr_win_end_date=win_end_date;
    else if not first.cust_no and def_date le curr_win_end_date then delete;
    
    drop curr_win_end_date;
run;
cust_no	        def_date	win_end_date	
10106212	31DEC2012	31DEC2014
10106212	31DEC2015	31DEC2017
10106212	31DEC2018	31DEC2020
10378803	30JUN2014	30JUN2016
mkeintz
PROC Star

I think this can be done in a straightforward way by using a date cutpoint updated each time the CUST_NO changes or a qualifying record is output.

 

data have;
  format cust_no 8. def_date win_end_date date9.;
  input cust_no :8. def_date :date11. win_end_date :date11.;
datalines;
10106212    31-Dec-12   31-Dec-14   
10106212    31-Dec-13   31-Dec-15   
10106212    31-Dec-14   31-Dec-16   
10106212    31-Dec-15   31-Dec-17   
10106212    31-Dec-17   31-Dec-19   
10106212    31-Dec-18   31-Dec-20   
10378803    30-Jun-14   30-Jun-16   
10378803    31-Dec-15   31-Dec-17   
run;

data want (drop=cut_point);
  set have;
  by cust_no;
  retain cut_point;
  if first.cust_no=1 then cut_point=.;
  if def_date > cut_point;
  cut_point=win_end_date;
run;

This takes advantage of the fact that when cut_point=., it will be considered lower than all valid date values.

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------

hackathon24-white-horiz.png

2025 SAS Hackathon: There is still time!

Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!

Register Now

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 4 replies
  • 1263 views
  • 2 likes
  • 3 in conversation