注:该系列文章都是学习马姆杜 雷法特著的《信用风险评分卡研究——基于SAS的开发与实施》一书时的学习记录和练手,供以后自己查看。如有不准确或不清楚的地方,请查找原著。
4.计算不同变量的WOE
- 代码如下
<span style="font-size:12px;">%macro CalcWOE(Dsin,Invar,Dcvar,WOEvar,Dsout);
/*频率表*/
proc freq data=&Dsin noprint;
tables &Invar*&Dcvar/out=Temp_Freqs;
run;
proc sort Temp_Freqs;
by &Invar &Dcvar;
run;
/*by分组统计*/
data Freq_Invar;
set Temp_Freqs;
retain c0 c1 c0t 0 c1t 0;
by &Invar &Dcvar;
if first.&Invar then do;
c0=Count;
c0t=c0t+c0;
end;
if last.&Invar then do;
c1=Count;
c1t=c1t+c1;
end;
if last.&Invar then output;
drop &Dcvar Count Percent;
call symput("c0t",c0t);
call symput("c1t",c1t);
run;
/*计算WOE*/
data WOEds;
set Freq_Invar;
GoodList=c0/&c0t;
BadList=c1/&c1t;
if(GoodList>0 and BadList>0) then WOE=log(BadList/GoodList);
else WOE=.;
run;
/*输出数据集*/
proc sql noprint;
create table &Dsout as
select a.*,b.WOE as &WOEvar from &Dsin a,WOEds b where a.&Invar=b.&Invar;
quit;
%mend;
%CalcWOE(Ccmodel.Cc6,CustAge_b,Status,CustAge_WOE,Ccmodel.Cc7);
run;</span>
- out
过程步一般以某一个关键字开头,如tables,by等,而选型则在斜杠之后。
- by, first, last
在使用带有by语句的过程步时,一定要用sort语句对数据集进行排序;
by语句根据变量对数据集进行分组;
假设原数据example为:
id_1 | id_2 | num |
1 | 1 | 5 |
3 | 0 | 3 |
2 | 0 | 6 |
2 | 1 | 4 |
3 | 1 | 7 |
1 | 1 | 5 |
<span style="font-size:12px;">/*读入数据*/</span>
<span style="font-size:12px;">data example;
input id_1 id_2 num;
datalines;
1 0 5
3 0 3
2 0 6
2 1 4
3 1 7
1 1 5
;
run;</span>
<span style="font-size:12px;">/*根据id_1,id_2排序,默认从小到大排列,在每个变量前加descending从大到小排列*/
proc sort data=example;
by id_1 id_2;
run;</span>
<span style="font-size:12px;">结果如下:</span>
<table width="131" height="135" style="width: 131px; height: 135px;" border="1" cellspacing="1" cellpadding="1"><tbody><tr><td><span style="font-size:12px;">id_1
</span></td><td><span style="font-size:12px;">id_2
</span></td><td><span style="font-size:12px;">num
</span></td></tr><tr><td><span style="font-size:12px;">1
</span></td><td><span style="font-size:12px;">0
</span></td><td><span style="font-size:12px;">5
</span></td></tr><tr><td><span style="font-size:12px;">1
</span></td><td><span style="font-size:12px;">1
</span></td><td><span style="font-size:12px;">5
</span></td></tr><tr><td><span style="font-size:12px;">2
</span></td><td><span style="font-size:12px;">0
</span></td><td><span style="font-size:12px;">6
</span></td></tr><tr><td><span style="font-size:12px;">2
</span></td><td><span style="font-size:12px;">1
</span></td><td><span style="font-size:12px;">4
</span></td></tr><tr><td><span style="font-size:12px;">3
</span></td><td><span style="font-size:12px;">0
</span></td><td><span style="font-size:12px;">3
</span></td></tr><tr><td><span style="font-size:12px;">3
</span></td><td><span style="font-size:12px;">1
</span></td><td><span style="font-size:12px;">7
</span></td></tr></tbody></table>
<span style="font-size:12px;">/*by first*/
data example_1;
set example;
by id_1 id_2;
if first.id_1 then output;
proc print;
run;</span>
<span style="font-size:12px;">结果如下:</span>
<table width="129" height="78" style="width: 129px; height: 78px;" border="1" cellspacing="1" cellpadding="1"><tbody><tr><td><span style="font-size:12px;">obs
</span></td><td><span style="font-size:12px;">id_1
</span></td><td><span style="font-size:12px;">id_2
</span></td><td><span style="font-size:12px;">num
</span></td></tr><tr><td><span style="font-size:12px;">1
</span></td><td><span style="font-size:12px;">1
</span></td><td><span style="font-size:12px;">0
</span></td><td><span style="font-size:12px;">5
</span></td></tr><tr><td><span style="font-size:12px;">2
</span></td><td><span style="font-size:12px;">2
</span></td><td><span style="font-size:12px;">0
</span></td><td><span style="font-size:12px;">6
</span></td></tr><tr><td><span style="font-size:12px;">3
</span></td><td><span style="font-size:12px;">3
</span></td><td><span style="font-size:12px;">0
</span></td><td><span style="font-size:18px;"><span style="font-size:12px;">3</span>
</span></td></tr></tbody></table>
可见,first.id_1取得是每个id_1分组中的第一个数据;
同理,last.id_1取得是每个id_1分组中的最后一个数据。
- retain
对变量进行值的初始化和保留到下一个迭代步的作用。
- 宏变量定义方法
%let c0t=831; ---不能在宏函数外调用
call symput('c0t',c0t);---可以在宏函数外调用;另只能提取该变量最后一个值。
select x into :y;---不能再宏函数外调用
- %eval与%sysevalf
宏的本质是文本,对宏进行数字运算时,要使用%eval与%sysevalf;
%eval必须是整数。