SAS iterative loops between two datasets

2019-08-08 22:41发布

问题:

I'm stuck with a situation where I have two datasets.

One containing defaults records at customer level, with each line including columns like ID_customer, date_default, amount_default, and a variable equal to amount_default which I need as editable variable which I call left_default

The second includes the payments, if any, made at customer level to repay these defaults. The variable are similar to the one of defaults, like ID_customer, date_payment, amount_payment and a variable equal to amount_payment which I need as ediatable which I call left_paymnet

What I want achive is that the code iteratively go through each lines of the default table, and for each default record it checks in the payment table if there are any payment made by the same customer, with the payment date greater or equal to the one of the default.

The logic is oldeast default get paid with priority respect to newer

If there is any payment with the above mentioned criteria, then depending on the amount of the payment made then I should populate the default table with new columns, one for each payment until the default amount is fully covered.

At the same time, if the paymnet amount is greater than the default amount left unpaid, then I should update the left_payment column with the amount of payment left after paying the part of the remaining default.

I think with an example is simpler.

Let say we have

table default

ID amount_default date_default left_defaullt  
1    5                01012015         5  
1    4                10012015         4  

table paymnet

ID amoutn_payment date_paymnet left_paymnet  
1  3                15122015         3  
1  6                18012016         6  

So at the first iteration the code first should focus on the first default of 5 euro, and then looking for payments in the payment table should retrieve 3 euro from the first line of payment and 2 euro from the second line of payment. So that after the first iteration the result should be

default

ID amount_default date_default left_defaullt payment1 datepayment1  
1  5                01012015       2             3        15122015  
1  4                10012015       4  

payment

ID amoutn_payment date_paymnet left_paymnet  
1  3                15122015      0  
1  6                18012016      6  

As the first default is not fully paid the second iteration should create the following result

default

ID amount_default date_default left_defaullt pay1 date1   pay2  datet2  
1  5                01012015      0             3    15122015  2    18012016  
1  4                10012015      4  

payment

ID amoutn_payment date_paymnet left_paymnet  
1  3                15122015     0  
1  6                18012016     4  

as the first default if fully paid then the iteration move to the second default

ID amount_default date_default left_defaullt pay1 date1   pay2  datet2  
1  5                01012015       0             3      15122015  2    18012016  
1  4                10012015       0             4       18012016  

payment

ID amoutn_payment date_paymnet left_paymnet  
1  3                15122015     0  
1  6                18012016     0  

So that as final result we know when each part of each default has been paid.

This involve in SAS I suppose two do loops through two datasets but not sure how to put together a similar code as it seems in the web there is no much documentation.

Here an example of the code I'm working on. Pretty sure it has many pieces wrong but as in order to offer a proper view of my issue:

data tot_imp;                
   input contract $ nie $ account_type $ fecha date9. missing_pago;  
   format fecha date9.;
   datalines;         
1 xx cc 01SEP2017 5
1 xx cc 04SEP2017 4
;                          
run;  


data pagos;                
   input contract $ nie $ account_type $ fecha date9. remain_pago;  
   format fecha date9.;
   datalines;         
1 xx cc 09SEP2017 3
1 xx cc 12SEP2017 2
;                          
run;  



data tot_imp_el;
set tot_imp nobs=num1;

do k=1 to num1;

partial=0;

do i=1 to num;
set pagos (rename=(contract=con nie=nies account_type=type fecha=fechas)) nobs=num point=i;

if con=contract and nies=nie and fechas>=fecha and remain_pago>0 then do; /* if the pago date is later than the impago and the same pago has not been used for other impagos*/

if missing_impago-remain_pago<=0 then do; /* if the pago pays all the impago */

call symput("cc", partial);
call symput("pago","pago"&cc);
call symput("fecha","fecha_pago"&cc);

partial=partial+1;
&pago=missing_pago;
remain_pago=remain_pago-missing_pago; 
missing_pago=0 ;
&fecha=fechas;
drop con nies type fechas remaing_pago;

leave;

end;

else do;

call symput("cc", partial);
call symput("pago","pago"&cc);
call symput("fecha","fecha_pago"&cc);

partial=partial+1;
missing_pago=missing_pago-remain_pago;
&pago=remaing_pago;
&fecha=fechas;
remain_pago=0;

drop con nies type fechas remaing_pago;

end;

end;

end;

run;

回答1:

This seems like a confusing format to put the information in wide rows. If what you want is basically a running ledger of defaults and payments for each ID, I think it would be easier to keep the data in narrow columns. For example, below interleaves the defaults and they payments (by ID and Date), and creates a running Balance:

data default;
  input ID amount date ddmmyy8.;
  format date date9.;
  cards;
1 5 01012015
1 4 10012015
;
run;

data payment;
  input ID amount date ddmmyy8.;
  format date date9.;
  cards;
1 3 15122015 3 
1 6 18012016 6
;

data want;
  set default (in=d) 
      payment (in=p)
  ;
  by id date;
  if first.id then balance=0;
  if d then do;
    type='Default';
    balance+-amount;
  end;
  if p then do;
    type='Payment';
    balance+amount;
  end;
run;

proc print data=want;
run;

Returns:

Obs    ID    amount         date    balance     type

 1      1       5      01JAN2015       -5      Default
 2      1       4      10JAN2015       -9      Default
 3      1       3      15DEC2015       -6      Payment
 4      1       6      18JAN2016        0      Payment


标签: loops sas