sas 变量降维、变量聚类、变量去除共线性

今天的文章的使用场景是,是因为我很热衷处理那种别人不喜欢整理的各种流水数据,例如运营商通话流水啊,银行卡流水啊,信用卡流水等等,那么这些数据做衍生变量有个经常会碰到的问题,就是像这种“最近一天的通话次数”有可能跟“最近三天的通话次数”这种相关性很强,但是在拟合的之后,这种相关性强的只能进一个,不然共线性就来找你啦,所以这时候你要处理是:1、你要让那个变量进去。2、那些变量是一类的,他们共线性在一起很强。

你跟我说,这谁不会啊,这不就是vif嘛,一看我就知道那几个相关性高了,是的,我们经常会有vif,但是模型做多了,你会发现,vif无论要多方便,但是有时候vif过了,但是还是存在共线性,所以你这时候还是要去看相关矩阵。所以vif并不会万能,我今天也不是要说相关矩阵,我今天要说的是sas的一个过程步叫做“proc varclus”,看着是不是很像聚类的那个过程步,是这个这个是变量的聚类,将相关性强的变量聚在一起,这里我不展开细讲,我给你链接,你自己去看,我今天不是来介绍这个过程的,我是来给代码~~

链接在这里:http://blog.sina.com.cn/s/blog_5d3b177c0100equm.html

https://wenku.baidu.com/view/7c4929f34693daef5ef73de1.html。

这是思路

  代码主要实现其实就是对变量降维,而且是降维后,给你提取同类变量中那个最好的。代码的思路是这样子的:

1、 输入一批数值变量,现在的代码只能实现数值变量的。我建议两百以内,你想要一千,我绝不拦你。

2、 使用proc varclus过程将变量聚类,控制群的数目

        Minclusters(minc)=正整数:指定最少要有几个群。

        Maxclusters(maxc)=正整数:指定最多有几个群。

        Proportion(percent)=正有理数:群主成份所能解释的变异数百分比。注意,这里proportion=0.75与percent=75是一样的。

        Maxeigen=实数:规定每个群内第二特征值的最大可能值。

    请自行选择,本人最常使用第二特征根。

3、 每一簇的变量都去跑一遍iv,再结合变量聚类结果指标和业务进行变量筛选。 

    挑选变量的原则如下:

        选择IV值最大的变量

        选择1-R平方最小的变量

        选择业务解释性好的变量。

4、 选择取出这一簇里面,iv最高的或者1-R方最小的。

5、 我知道你会说,但是我想看下其他变量的怎么样,我也给你保留了!

代码:

%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;

/*合并筛选指标*/

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:你的数据集

Maxclusters:填的是你想最多变成多少簇。

Group:跑iv的时候你想分几组算iv。

method:method=1每组取iv最大;method=2每组取1-R方最小;

以上就是这个宏的参数填写,接下来我跟大家说下结果有哪些。

结果:这个结果产出的全部数据集。主要看两张表:

1、Var_select_d:

保留的是每一簇筛选出来的变量,如果想换取变量,请参考下一张表。

2、Var_select_m

这张表保存的是每个簇的各个变量的指标。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,617评论 18 399
  • 身边的朋友一个个的都结婚了,朋友问,你呢?亲戚说,找个差不多的嫁了吧到了30岁就晚了。 前几年的我听到...
    一年一班阅读 899评论 1 0
  • 兜兜转转那山那峰 未知身边潜伏赢到了最后 还未饮左正餐 即得你兵临城下的婚讯 身后的护城墙何时决了堤 这铠甲明明伪...
    JS_cdb4阅读 310评论 0 1
  • 虹,还是那道美丽的虹 那《童年》的《星》 依然在记忆的河底 悠扬灿烂 曾经 沉醉在你的歌声 心弛神往的天籁 陪我走...
    一枚冰儿阅读 286评论 0 0
  • A1 老公爱吃水果,本来是个好习惯,但是他单次吃的量太大,比如吃橘子可以一次吃1斤,吃西瓜可以一次吃一个。他本身...
    wlhuiyi阅读 163评论 0 0