**************************************************************;
* TAB030402s5.sas *;
* proc tabulate を使おう *;
* section 5 : 事前加工をうまくする *;
* 2003.4.2, 翔 *;
* 2008.3.18, 改定1 *;
**************************************************************;
options nocenter;
libname mydata "c:\";
/*
前セッションと同じく
1年間にクレジットカードを利用したホテル利用者の特徴を学習させることを目的としたのデータ。1,450人分を使って,実行例を示します.
*/
data creditcard;
infile "c:\train_space.txt" firstobs=2 dlm='09'x; /*外部ファイルから入力*/
input id hotel xgender $ xage xincome xmarital $ xusage xretail xrest xenter xtrans xother; /*読み込むデータを指定*/
run;
proc print data=creditcard(obs=5);run;
/*
OBS id hotel xgender xage xincome xmarital xusage xretail xrest xenter xtrans xother
1 1 0 female 60 . single 300000 100000 1 0 0 30000
2 2 1 male 40 . single 30000 10000 0 0 0 30000
3 3 0 male 40 . single 100000 100000 1 0 10000 100000
4 4 0 male 30 . single 300000 300000 10000 100000 30000 10000
5 5 0 male 40 . single 10000 10000 1 0 0 1
*/
/*****************************************************
今回が最後のセクションです.
ここでは,tabulateにかける前に,ちょっとデータに工夫しておくと,
便利なことをいくつか紹介します.
1.サンプリングデータの集計
2.sum/meanを使った反応数/反応率
3.承認率と利用率と延滞率と利用単価と
4.金額変数向き汎用フォーマット
5.度数分布と平均を見たかったら
6.ディサイルセグメント集計
*/
/******************************************************
1.サンプリングデータの集計
他のプロシージャと同じく,tabulateもfreq文を使って,
各オブザベーションの度数を与えることができます.
仮に,creditcardのデータが,母集団から,男は,1/10,
女は,1/5でサンプリングされたデータだとすると,
母集団の度数にweight backした値でクロス表を
出力できます.
その際,事前にfreq変数を作っておきます.
デフォルト先と正常先のサンプリングレートが違う場合に,
よく使います.
*/
data credit;set creditcard;
if xgender="male" then freq=10; /*男なら度数は10倍*/
else freq=5; /*女なら度数は5倍*/
run;
proc tabulate data=credit formchar=" " noseps missing format=comma9.;
class xincome xgender;
table all xincome
,(all xgender)*(n pctn*f=7.1)
/rts=10;
freq freq; /* freq文で,変数freqに度数が与えられていることを指示*/
run;
/*
xgender
All female male
N PctN N PctN N PctN
All 12,990 100.0 1,510 11.6 11,480 88.4
xincome
. 330 2.5 10 0.1 320 2.5
1 6,090 46.9 640 4.9 5,450 42.0
100 845 6.5 295 2.3 550 4.2
300 1,330 10.2 250 1.9 1,080 8.3
500 1,415 10.9 125 1.0 1,290 9.9
700 1,285 9.9 95 0.7 1,190 9.2
1000 1,695 13.0 95 0.7 1,600 12.3
*/
/****************************************************************
2.sum/meanを使った反応数/反応率
PCTNを使わずに,反応率を表示させます.
ポイントは,反応=1・非反応=0を分類変数として扱わず,
分析変数とみなして,1の合計を反応数,平均を反応率とすることです.
メリットは,興味のない非反応数と非反応率を出力しないですむことで,
表示をすっきりさせることは,探索的作業には重要です.
*/
data credit;set creditcard;
resp=(xrest>0); /*前回の値が0より大きければ,真(1),そうでなければ偽(0)*/
run;
/*
PCTNを使った場合
*/
proc tabulate data=credit formchar=" " noseps missing format=comma9.;
class xincome resp;
table all xincome
,(all resp)*(n rowpctn*f=7.1)
/rts=10;
run;
/*
resp
All 0 1
N RowPctN N RowPctN N RowPctN
All 1,450 100.0 1,108 76.4 342 23.6
xincome
. 34 100.0 25 73.5 9 26.5
1 673 100.0 518 77.0 155 23.0
100 114 100.0 97 85.1 17 14.9
300 158 100.0 124 78.5 34 21.5
500 154 100.0 108 70.1 46 29.9
700 138 100.0 107 77.5 31 22.5
1000 179 100.0 129 72.1 50 27.9
*/
/*
MEANを使った場合
*/
proc tabulate data=credit formchar=" " noseps missing format=comma9.;
class xincome;
var resp;
table all xincome
,resp*(n sum mean*f=percent9.1)
/rts=10;
run;
/*
resp
N Sum Mean
All 1,450 342 23.6%
xincome
. 34 9 26.5%
1 673 155 23.0%
100 114 17 14.9%
300 158 34 21.5%
500 154 46 29.9%
700 138 31 22.5%
1000 179 50 27.9%
*/
/*
次の例は,ある専業の極度アップDMの反応データです.
LE件数XLE金額のクロス表が3つ並んでいて,上から順に,
DM発送数,反応数,反応率です.
LE件数も,LE金額も,それぞれ反応率に対して同程度の効きが見られますが,
LE件数XLE金額のクロス表上で見ると,LE金額のほうが本来影響力をもっており,
LE件数は見せかけであることがわかります.
(一般にリスクはLE金額よりLE件数が重要視されることと,逆ですね)
proc tabulate data=dmyes.mst4 formchar=" "
missing noseps format=comma7.;
class len1 lea1;
var res3;
table res3*(n sum mean*f=percent7.1)*(all len1)
,all lea1
/rts=30;
format lea1 amt.;
run;
lea1-LE金額直近
All 0 -500 -1000 -1500 1500+
res3-20 N All 93,443 36,864 22,941 18,184 8,820 6,634
日以内反 len1-LE
応有無 件数直近
0 36,900 36,852 42 6 . .
1 29,901 12 21,258 7,328 573 730
2 19,384 . 1,545 10,110 5,724 2,005
3 5,411 . 86 659 2,217 2,449
4 1,614 . 9 78 287 1,240
5 222 . 1 3 17 201
6 11 . . . 2 9
Sum All 4,775 1,398 979 965 667 766
len1-LE
件数直近
0 1,402 1,398 3 1 . .
1 1,441 0 909 434 38 60
2 1,177 . 63 491 405 218
3 527 . 3 33 192 299
4 198 . 0 6 27 165
5 28 . 1 0 5 22
6 2 . . . 0 2
Mean All 5.1% 3.8% 4.3% 5.3% 7.6% 11.5%
len1-LE
件数直近
0 3.8% 3.8% 7.1% 16.7% . .
1 4.8% 0.0% 4.3% 5.9% 6.6% 8.2%
2 6.1% . 4.1% 4.9% 7.1% 10.9%
3 9.7% . 3.5% 5.0% 8.7% 12.2%
4 12.3% . 0.0% 7.7% 9.4% 13.3%
5 12.6% . 100% 0.0% 29.4% 10.9%
6 18.2% . . . 0.0% 22.2%
*/
/****************************************************
3.承認率と利用率と延滞率と利用単価と
ローン申込データがあり,諾否,利用額,延滞有無が記録されているデータから,
承認率と利用率と延滞率と利用単価を計算することとします.
利用率は,申込先全体での利用者の比率ではなく,承認者のなかでの比率です.
同じように,延滞率は利用者中の延滞者率,利用単価も利用者中の利用額平均
とすべきでしょう.
このように,統計をとる範囲が全体と一致しない場合,異なる母数毎に
集計し直さなくても,対象外のデータを欠損にすることで,一度に対応できます.
注)消化率は,(単純平均でなければ)PCTSUMを使うしかなかったかも?
(忘れてしまった..)
*/
data cardloan;
input CID sex $ decision $ balance delinquent;
cards;
001 M A 350000 1
002 M A 120000 0
003 M A 410000 0
004 M D 0 0
005 M D 0 0
006 F A 230000 1
007 F A 50000 0
008 F A 0 0
009 F D 0 0
;
data cardloan;set cardloan;
approve=(decision="A"); /* 承認 */
usage =(balance>0); /* 利用 */
if approve ne 1 then usage=.; /*否認先なら利用(有無)は欠損*/
if usage ne 1 then balance=.; /*未利用者なら残高は欠損*/
if usage ne 1 then delinquent=.; /*未利用者なら延滞は欠損*/
run;
proc print;run;
/*
OBS CID sex decision balance delinquent approve usage
1 1 M A 350000 1 1 1
2 2 M A 120000 0 1 1
3 3 M A 410000 0 1 1
4 4 M D . . 0 .
5 5 M D . . 0 .
6 6 F A 230000 1 1 1
7 7 F A 50000 0 1 1
8 8 F A . . 1 0
9 9 F D . . 0 .
*/
proc tabulate data=cardloan formchar=" " noseps missing format=comma5.;
class sex;
var approve usage balance delinquent;
table all sex
,n
approve*(sum mean*f=percent9.1)
usage*(sum mean*f=percent9.1)
balance*(mean*f=comma9.)
delinquent*(sum mean*f=percent9.1)
/rts=10;
run;
/*
approve usage balance delinquent
N Sum Mean Sum Mean Mean Sum Mean
All 9 6 66.7% 5 83.3% 232,000 2 40.0%
sex
F 4 3 75.0% 2 66.7% 140,000 1 50.0%
M 5 3 60.0% 3 100.0% 293,333 1 33.3%
*/
/****************************************************
4.金額変数向き汎用フォーマット
tabulateに限ったことではないですが,利用額,残高,収入など
指数分布のように,片裾の重いデータに対して,手っ取りばやく
区切って分布具合をみるのに便利なフォーマットの切り方を紹介します.
もし,平均と4分位などに見当がついているなら,それを目安に
フォーマットを区切ればいいですが,変数がたくさんあると,
いちいちそれに合わせて切るのは面倒です.
かといって,10万,20万,30万と等間隔で切るのは,
高額の部分でいきづまるし,対数をとると,いまいち見た目が
よくない..と私は感じます.
そういう時,なにも考えずに,
1万,3万,10万,30万,100万,300万..
と,1と3を交代させながら,指数的にフォーマットを
切ると,あら不思議,たいがいの指数的分布変数は,
うまい具合に散らばってくれます.
なぜ3を使っているのか,それは10の0.5乗が約3だからです.
*/
proc format;
value amount
low-0= "zero"
0<- 10000="-10K"
10000<- 30000="-30K"
30000<- 100000="-100K"
100000<- 300000="-300K"
300000<-1000000="-1M"
1000000<-high="1M+"
;
run;
proc tabulate data=creditcard formchar=" " noseps missing format=comma5.;
class xusage xenter;
table all xusage xenter
,n
/rts=10;
format xusage xenter amount.;
run;
/*
N
All 1,450
xusage
zero 3
-10K 314
-30K 323
-100K 413
-300K 397
xenter
zero 1,197
-10K 97
-30K 75
-100K 58
-300K 2
*/
/****************************************************
5.度数分布と平均を見たかったら
もし,変数値の度数分布と平均値を同時に表示したければ,
前もって,その変数を別の変数にコピーしておく必要があります.
1つの変数を分類変数と分析変数の両方に宣言できないからです.
*/
data credit;set creditcard;
xenter2=xenter;
run;
proc tabulate data=credit formchar=" " noseps missing format=comma5.;
class xenter;
var xenter2;
table all xenter*n="" xenter2*mean
,all
/rts=20;
format xusage xenter amount.;
run;
/*
All
All N 1,450
xenter
zero 1,197
-10K 97
-30K 75
-100K 58
-300K 23
xenter2 Mean 10834
*/
/****************************************************
6.ディサイルセグメント集計
ディサイルとは,10%刻みことです.
以下に,13万人のクレジットカード顧客に対し,その売上額順に
顧客を10%ずつのグループに分け,パレートの法則(20-80の法則)が
成り立っているか見てみます.
*/
/*
proc print data=usage(obs=10);run;
OBS usage
1 1254920
2 76731
3 0
4 672337
5 0
6 0
7 0
8 0
9 2724
10 0
data decile;set usage;
keep usage ranuni;
if usage=. then usage=0;
ranuni=ranuni(1);
run;
proc sort data=decile;by usage ranuni;run;
data decile;set decile;n=_n_;call symput("n",n);run;
data decile;set decile;
decile=int((&n-n)/&n*10)+1;
run;
proc tabulate data=decile formchar=" " missing noseps format=comma8.;
class decile;
var usage;
table all decile
,usage*(n mean min max sum*f=comma16. pctsum)
/rts=10;
run;
usage
N Mean Min Max Sum PctSum
All 130,493 157,254 -139,722 20378964 20,520,588,499 100
decenti-
le
1 13,050 991,592 477,645 20378964 12,940,281,919 63
2 13,049 333,816 226,997 477,642 4,355,958,789 21
3 13,049 159,969 104,831 226,993 2,087,438,369 10
4 13,050 68,100 37,990 104,795 888,704,600 4
5 13,049 18,592 2,730 37,990 242,605,741 1
6 13,049 479 0 2,730 6,253,346 0
7 13,050 0 0 0 0 0
8 13,049 0 0 0 0 0
9 13,049 0 0 0 0 0
10 13,049 -50 -139,722 0 -654,265 -0
*/
/*
事前に,売上額usageで,大きい順にdecileを1から10まで振り分けます.
tabulateでは,decile毎に,顧客数,平均売上額,最小値,最大値
売上額合計,構成比を表示します.(累積%ができるといいのに..)
この例だと上位20%(1+2decile)が,全体の売上の84%(=63+21)を
生み出していることがわかります.
*/
**********************************************************************;
************** E N D *************************************************;
**********************************************************************;
質問・意見
質問・意見一覧
一覧に表示する項目はありません.