今天的文章的使用場(chǎng)景是,是因?yàn)槲液軣嶂蕴幚砟欠N別人不喜歡整理的各種流水?dāng)?shù)據(jù),例如運(yùn)營(yíng)商通話流水啊,銀行卡流水啊,信用卡流水等等,那么這些數(shù)據(jù)做衍生變量有個(gè)經(jīng)常會(huì)碰到的問(wèn)題,就是像這種“最近一天的通話次數(shù)”有可能跟“最近三天的通話次數(shù)”這種相關(guān)性很強(qiáng),但是在擬合的之后,這種相關(guān)性強(qiáng)的只能進(jìn)一個(gè),不然共線性就來(lái)找你啦,所以這時(shí)候你要處理是:1、你要讓那個(gè)變量進(jìn)去。2、那些變量是一類的,他們共線性在一起很強(qiáng)。
你跟我說(shuō),這誰(shuí)不會(huì)啊,這不就是vif嘛,一看我就知道那幾個(gè)相關(guān)性高了,是的,我們經(jīng)常會(huì)有vif,但是模型做多了,你會(huì)發(fā)現(xiàn),vif無(wú)論要多方便,但是有時(shí)候vif過(guò)了,但是還是存在共線性,所以你這時(shí)候還是要去看相關(guān)矩陣。所以vif并不會(huì)萬(wàn)能,我今天也不是要說(shuō)相關(guān)矩陣,我今天要說(shuō)的是sas的一個(gè)過(guò)程步叫做“proc varclus”,看著是不是很像聚類的那個(gè)過(guò)程步,是這個(gè)這個(gè)是變量的聚類,將相關(guān)性強(qiáng)的變量聚在一起,這里我不展開(kāi)細(xì)講,我給你鏈接,你自己去看,我今天不是來(lái)介紹這個(gè)過(guò)程的,我是來(lái)給代碼~~
鏈接在這里:http://blog.sina.com.cn/s/blog_5d3b177c0100equm.html
https://wenku.baidu.com/view/7c4929f34693daef5ef73de1.html。
這是思路
? 代碼主要實(shí)現(xiàn)其實(shí)就是對(duì)變量降維,而且是降維后,給你提取同類變量中那個(gè)最好的。代碼的思路是這樣子的:
1、?輸入一批數(shù)值變量,現(xiàn)在的代碼只能實(shí)現(xiàn)數(shù)值變量的。我建議兩百以內(nèi),你想要一千,我絕不攔你。
2、?使用proc varclus過(guò)程將變量聚類,控制群的數(shù)目
????????Minclusters(minc)=正整數(shù):指定最少要有幾個(gè)群。
????????Maxclusters(maxc)=正整數(shù):指定最多有幾個(gè)群。
????????Proportion(percent)=正有理數(shù):群主成份所能解釋的變異數(shù)百分比。注意,這里proportion=0.75與percent=75是一樣的。
????????Maxeigen=實(shí)數(shù):規(guī)定每個(gè)群內(nèi)第二特征值的最大可能值。
????請(qǐng)自行選擇,本人最常使用第二特征根。
3、?每一簇的變量都去跑一遍iv,再結(jié)合變量聚類結(jié)果指標(biāo)和業(yè)務(wù)進(jìn)行變量篩選。?
????挑選變量的原則如下:
????????選擇IV值最大的變量
????????選擇1-R平方最小的變量
????????選擇業(yè)務(wù)解釋性好的變量。
4、 選擇取出這一簇里面,iv最高的或者1-R方最小的。
5、?我知道你會(huì)說(shuō),但是我想看下其他變量的怎么樣,我也給你保留了!
代碼:
%macro varclus(DSin=,target=,Maxclusters=,group=,method=,DSout=);
*method=1每組取iv最大;method=2每組取1-R方最小;
%let lib=%upcase(%scan(&DSin.,1,'.'));
? ? %let dname=%upcase(%scan(&DSin.,2,'.'));
proc sql noprint;
? ? ? ? select name into:name_list? SEPARATED by " "
? ? ? ? from sashelp.VCOLUMN
? ? ? ? where left(libname)="&lib." and left(memname)="&dname."? and lowcase(name)^=lowcase("user_id.") and lowcase(name)^=lowcase("&target") ;
? ? quit;
? %put &name_list.;
ods listing close;
ods output clusterquality=summary
? ? ? ? ? rsquare=clusters;
proc varclus data=&DSin.
? ? ? ? ? ? Minclusters=2
Maxclusters=&Maxclusters.
percent=75
Maxeigen=7
? ? ? ? ? ? outtree=fortree
? ? ? ? ? ? short;
var &name_list.;
run;
ods listing;
data _null_;
? ? set summary;
? ? call symput('nvar',compress(NumberOfClusters));
run;
data clusters_&nvar;
set clusters;
where NumberOfClusters=&nvar;
run;
data var_select;
set clusters_&nvar;
? ? retain Cluster1;
? ? if Cluster~="" then Cluster1=Cluster;
run;
data _null_;
set var_select;
call symputx(compress("varname"||_n_),compress(Variable));
call symputx(compress("n"),compress(_n_));
run;
data total_result;
length varname$30.;
length group_id 8.;
length new_min 8.;
length new_max 8.;
length interval$30.;
length group_num 8.;
length bad_num 8.;
length good_num 8.;
length good_rate 8.;
length bad_rate 8.;
length woe 8.;
length iv 8.;
run;
%do i=1 %to &n.;
%put &&varname&n.;
proc rank data=&DSin.(keep =&&varname&i. &target.) out = tmp ties = low groups = &group.;
var &&varname&i.;
ranks new_var;
run;
proc sql noprint;
create table result1 as
select distinct
"&&varname&i." as varname,
new_var,
min(&&varname&i.) as min,
max(&&varname&i.) as max,
case when new_var^=. then compress(put(min(&&varname&i.),8.)||"-"||put(max(&&varname&i.),8.)) else "null " end as interval,
count(*) as group_num,
sum(&target.) as bad_num,
count(*)-sum(&target.) as good_num
from tmp
group by new_var;
quit;
proc sql noprint;
select count(*)into:good_total from tmp(where=(&target.=0));
select count(*)into:bad_total from tmp(where=(&target.=1));
create table result2 as
select
varname,
case when new_var=. then 0 else new_var end as group_id,
case when min=min(min) then . else min end as new_min,
case when max=max(max) then . else max end as new_max,
interval,group_num,bad_num,good_num,
good_num/&good_total. as good_rate,
bad_num/&bad_total. as bad_rate,
log((bad_num/&bad_total.)/(good_num/&good_total.)) as woe,
log((bad_num/&bad_total.)/(good_num/&good_total.))*((bad_num/&bad_total.)-(good_num/&good_total.)) as iv
from result1 a;
quit;
proc append base=total_result data=result2 force;run;
proc sql;
create table iv_result as
select distinct varname, sum(iv) as iv
from total_result(where=(varname^=''))
group by varname;
quit;
%end;
/*合并篩選指標(biāo)*/
proc sql noprint;
create table var_select_m as?
select * from var_select as a left join iv_result as b on a.Variable=b.varname;
quit;
/*變量篩選*/
%if &method.=1 %then %do;
proc sort data=var_select_m;
? ? by Cluster1 descending iv /* iv*/;
run;
%end;
%else %do;
proc sort data=var_select_m;
? ? by Cluster1 RSquareRatio /* RSquareRatio*/;
run;
%end;
data var_selected(where=(row=1));
set var_select_m;
? ? if first.Cluster1 then row=1;
? ? else row+1;
? ? by Cluster1;
run;
%global var_clus;
proc sql noprint;
select Variable into :var_clus separated by ' '
? ? from Var_selected;
quit;
%put &var_clus;
data &DSout.;
set &DSin.;
keep target &var_clus;
run;
%mend;
這是代碼講解
varclus(DSin=,target=,Maxclusters=,group=,method=,DSout=)
DSin:你的數(shù)據(jù)集
Maxclusters:填的是你想最多變成多少簇。
Group:跑iv的時(shí)候你想分幾組算iv。
method:method=1每組取iv最大;method=2每組取1-R方最小;
以上就是這個(gè)宏的參數(shù)填寫(xiě),接下來(lái)我跟大家說(shuō)下結(jié)果有哪些。
結(jié)果:這個(gè)結(jié)果產(chǎn)出的全部數(shù)據(jù)集。主要看兩張表:
1、Var_select_d:

保留的是每一簇篩選出來(lái)的變量,如果想換取變量,請(qǐng)參考下一張表。
2、Var_select_m

這張表保存的是每個(gè)簇的各個(gè)變量的指標(biāo)。