1. 程式人生 > >《信用風險評分卡研究——基於SAS的開發與實施》學習筆記(2)

《信用風險評分卡研究——基於SAS的開發與實施》學習筆記(2)

注:該系列文章都是學習馬姆杜 雷法特著的《信用風險評分卡研究——基於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必須是整數。