【问题标题】:SAS iterative loops between two datasets两个数据集之间的 SAS 迭代循环
【发布时间】:2018-02-08 01:31:02
【问题描述】:

我遇到了两个数据集的情况。

一个包含客户级别的默认记录,每行包括ID_customerdate_defaultamount_default 等列,以及一个等于amount_default 的变量,我需要将其作为可编辑变量,我称之为left_default

第二个包括在客户层面为偿还这些违约而支付的款项(如果有)。该变量类似于默认值之一,例如 ID_customer、date_payment、amount_payment 和一个等于 amount_payment 的变量,我需要它作为可编辑的变量,我称之为 left_paymnet

我想要实现的是代码迭代地遍历默认表的每一行,并且对于每个默认记录,它会在付款表中检查同一客户是否进行了任何付款,付款日期大于或等于到默认值之一。

逻辑是oldeast默认获得优先考虑newer的报酬

如果有任何符合上述标准的付款,那么根据付款金额,我应该用新列填充默认表,每笔付款一个,直到完全覆盖默认金额。

同时,如果paymnet金额大于未支付的默认金额,那么我应该将left_payment列更新为支付剩余的部分后剩余的支付金额。

我认为举个例子更简单。

假设我们有

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  

所以在第一次迭代中,代码首先应该关注第一个默认值 5 欧元,然后在付款表中查找付款应该从第一行付款中检索 3 欧元,从第二行付款中检索 2 欧元。所以在第一次迭代之后,结果应该是

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  

由于第一次默认未全额支付,第二次迭代应创建以下结果

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  

如果全额支付,则作为第一个默认值,然后迭代移动到第二个默认值

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  

因此,作为最终结果,我们知道每个违约的每一部分何时已支付。

这涉及到 SAS,我想两个循环遍历两个数据集,但不确定如何将类似的代码放在一起,因为在网络上似乎没有太多文档。

这是我正在处理的代码示例。很确定它有很多错误,但为了正确看待我的问题:

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;

【问题讨论】:

  • 这不是一个适合 Stack Overflow 的问题。我们很乐意帮助您编写代码,但这不是代码编写服务。
  • 嗨,乔,我有一个代码示例,但我很确定我在这里做错了很多事情。但如果它可以帮助我在这里发布它
  • 我建议您为每次付款添加一个新行而不是一个新列,并添加一个新的交易 id 列来跟踪它们。这将更容易管理。
  • 我认为这是一个有趣的问题,但没有得到回应,因为在列方面所需的输出并不是大多数人所推荐的。但是,如何将付款应用于最旧的违约(并跟踪每笔付款适用于哪些违约)的核心问题很有趣。如果您今天或明天没有收到很多回复,我可能会尝试发布一个新问题,这是此问题的修订版。我认为编辑的变化太大了。
  • 我提出了一个新问题,这是对此问题的修订版,其结构对我来说更有意义。我根据信用卡借记和贷记来构建它,并使用长而细的数据集。 stackoverflow.com/questions/46009596/…

标签: loops sas


【解决方案1】:

将信息放在宽行中似乎是一种令人困惑的格式。如果您想要的基本上是每个 ID 的默认和付款的运行分类帐,我认为将数据保存在窄列中会更容易。例如,下面将默认值和付款(按 ID 和日期)交错,并创建一个正在运行的余额:

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;

返回:

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

【讨论】:

  • 嗨昆汀。谢谢您的答复。但是,我需要在默认值和付款之间的列中建立关联,因为每个默认行都可以代表“资本”或“利息”实体,因此我需要知道付款是否已用于偿还资本或利息违约
  • 我还是喜欢这些行。但我的回答避开了将每笔付款分配给特定默认值的目标。我得再想想。这是一个有趣的问题。
  • 昆汀,作为附带问题。我看到你使用'+'和'+-'符号组合就像一种“保留”声明。我从未见过这些运算符的这种用法。你能告诉我它是如何在 SAS 中定义的,以便我可以对这个特定用途进行一些搜索吗?谢谢
  • 这是一个求和语句。 X+1; 等价于 retain x 0; x=sum(x,1);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-07
  • 1970-01-01
  • 1970-01-01
  • 2021-12-27
  • 1970-01-01
相关资源
最近更新 更多