累積了一段時間的建模經(jīng)驗了,這次想把我在建模中用的代碼分批分享出來,可能寫的東西不是你能用到的,畢竟我們接觸到的數(shù)據(jù)都不一樣。但是譬如文本清洗之類的,看我之前的文章“正則式”還是可以找到解決方法的。我覺得數(shù)據(jù)面并不多,就是就我現(xiàn)有的數(shù)據(jù)做的數(shù)據(jù)處理。希望大神也可以指正我在建模中用的不恰當(dāng)?shù)奶幚頂?shù)據(jù)的方式。那么就開始今天的分享啦。 今天主要想分享給大家的有三個代碼:“缺失值填充”,“變量缺失值比例”“異常值檢測”。 缺失值補充這部分的代碼是我在遇到譬如主表的數(shù)據(jù)是有的,但是left join的時候沒有這個數(shù)據(jù),但是他并不是缺失,只是客戶真的沒有。譬如房屋貸款筆數(shù),假設(shè)客戶沒有房屋貸款,那么這個變量就是缺失的,但是他并不是缺失,他實際上沒有,所以要填補一個零。這段代碼是對數(shù)值的字符的整張數(shù)據(jù)集的變量的處理。 %macro missing(data); data aa; set &data; array arr1{*} _NUMERIC_ ; array arr2{*} _CHARACTER_ ; do i = 1 to dim(arr1); if missing(arr1(I)) then do; arr1(i)=0; /*這里的arr1(i)=0;根據(jù)自己的需要,要0就是0也可以是別的值*/ end; if missing(arr1(i)) then do; arr1(i)=0; end; end; do i = 1 to dim(arr2); if missing(arr2(I)) then do; arr2(i)="0"; end; end; run; %mend; Data填入數(shù)據(jù)集 代碼我都是調(diào)試好的,所以可以直接用。 經(jīng)過缺失值填補之后,但是還有些改缺失還是缺失的,這時候要對變量做變量缺失率的檢查,我這邊是對于變量缺失率達(dá)到70%的就去掉這個變量。具體缺失比率在多少就不要,還是要看自己的業(yè)務(wù)需求。那上代碼吧。這部分的代碼是參考另外這個公眾號的妹紙寫的代碼公眾號是:數(shù)據(jù)分析sas和r和python。 data tmp11; set raw.jxl_total_t; array arr1{*} _NUMERIC_ ; array arr2{*} _CHARACTER_ ; length variable $50; do i = 1 to dim(arr1); if missing(arr1(i)) then do; variable =vname(arr1(i));/*數(shù)值型缺失*/ output; end; end; do j = 1to dim(arr2); if missing(arr2(j)) then do; variable = vname(arr2(j)); /*字符型缺失*/ output; end; end; keep variable; run; proc sql noprint; select count(*) into : N from raw.jxl_total_t; create table miss as select variable label = "缺失變量名", count(*) as frequency label = "缺失頻數(shù)", input(compress(put(calculated frequency / &N.,percent10.2),'%'),best32.) as percent label = %nrstr("%缺失占比") from tmp11 group by variable having percent>70; quit; /*統(tǒng)計缺失頻數(shù)和占比*/ 剔掉缺失嚴(yán)重的變量,那么下一步就是做異常值的檢查,不要讓異常值壞了擬合結(jié)果,畢竟數(shù)據(jù)也是存在一顆老鼠屎壞了一鍋粥。異常值我之前在前面的文章中有用到聚類,有3倍標(biāo)準(zhǔn)差,聚類的話可能對于字符變量可能好些,3倍標(biāo)準(zhǔn)差的話需要要求數(shù)據(jù)呈正態(tài)分布,但是我的數(shù)據(jù)貌似很難達(dá)到這個需求。如果需要以上提及的聚類或者是3倍標(biāo)準(zhǔn)差可以點:路徑查看啦。那么一下這段代碼我用的箱形圖來找出異常值,并且將在區(qū)域以外的數(shù)據(jù)集用上下界的值代替。分享的代碼沒有固定的iqr,寫的條件譬如,異常值都在1.5倍iqr達(dá)到1%,那么就將這部分的值判斷為異常值,假設(shè)現(xiàn)在是3iqr外的異常值達(dá)到1%或者小于1%,但是2.5iqr以外的數(shù)據(jù)已經(jīng)達(dá)到了1.5%,那么就行選定3iqr以外的數(shù)據(jù)為異常值。異常值檢查只針對數(shù)值變量。我是不是廢話很多,我很怕你們理解不了我的意思,如果不知道iqr是什么的,先百度下拉。接下來上代碼。 %macro pub(data,var); PROC UNIVARIATE DATA= &data.(where=(&var.^=.)) NOprint; VAR &var.; OUTPUT OUT=qdata Q1=q1 Q3=q3 QRANGE=iqr STD=VSTD Mean=VMean; RUN; DATA _null_; SET qdata; call symput('STD', VSTD); call symput('Mean', VMean); CALL SYMPUT("q1",q1); CALL SYMPUT("q3",q3); CALL SYMPUT("iqr",compress(iqr)); RUN; %let qa=%sysevalf(&q1. -(1.5*&iqr.)); %let qb=%sysevalf(&q3. +(1.5*&iqr.)); %let qc=%sysevalf(&q1. -(2*&iqr.)); %let q4=%sysevalf(&q3. +(2*&iqr.)); %let q5=%sysevalf(&q1. -(2.5*&iqr.)); %let q6=%sysevalf(&q3. +(2.5*&iqr.)); %let q7=%sysevalf(&q1. -(3*&iqr.)); %let q8=%sysevalf(&q3. +(3*&iqr.)); %put &q1.&q8.; DATA outliers; SET &data.(where=(&var.^=.)); LENGTH severity $2; severity=""; IF &var. <= &qa. OR &var. >= &qb. THEN severity="1"; else IF &var. <= &qc. OR &var. >= &q4. THEN severity="2"; else IF &var. <= &q5. OR &var. >= &q6. THEN severity="3"; else IF &var. <= &q7. OR &var. >= &q8. THEN severity="4"; IF severity in ("1","2","3","4") THEN OUTPUT outliers; RUN; proc sql; %do f=1 %to 4; select count(*) into:outliers_&f. from outliers where severity="&f."; %end; select count(*) into :n from &data.; quit; %put &outliers_1. &outliers_2.; %put &n.; %let out_1=%sysevalf(&outliers_1./&n.); %let out_2=%sysevalf(&outliers_2./&n.); %let out_3=%sysevalf(&outliers_3./&n.); %let out_4=%sysevalf(&outliers_4./&n.); data &data.; set &data.; length &var._1 8.; if &out_1.<0.01 and &var.^=. then do; if &var. <=&qa. then &var._1=0; else if &var. >=&qb. then &var._1=&qb.; else &var._1=&var.; end; if &out_2.<0.01 and &var.^=. then do; if &var. <=&qc. then &var._1=0; else if &var. >=&q4. then &var._1=&q4.; else &var._1=&var.; end; if &out_3.<0.01 and &var.^=. then do; if &var. <=&q5. then &var._1=0; else if &var. >=&q6. then &var._1=&q6.; else &var._1=&var.; end; if &out_4.<0.01 and &var.^=. then do; if &var. <=&q7. then &var._1=0; else if &var. >=&q8. then &var._1=&q8.; else &var._1=&var.; end; else do ; &var._1=. ; end; drop &var. ; rename &var._1=&var. ; run; %mend; pub(data,var) data填入數(shù)據(jù)集,var填入你要檢測的變量。 代碼中有很多可以優(yōu)化地方,譬如那些重復(fù)的東西就可以用循環(huán)的,你問我為什么不用,是因為我懶得改了,如果你想自己優(yōu)化一下,就自己優(yōu)化一下吧。如果我后續(xù)優(yōu)化了,再分享給你們也可以。 |
|