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

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

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

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