TABULATE入門1

Last-modified: 2015-09-12 (土) 03:28:24

**************************************************************;
* TAB030328s1.sas                                            *;
* proc tabulate を使おう                                     *;
* session 1 : tabulate って何?                              *;
* 2003.3.28, 翔                       *;
* 2008.3.17, 改定01                                          *;
**************************************************************;

options nocenter;

libname mydata "c:\";
/* デモのSASコードを実行したければ,train_space.txtにアクセス可能にしておくこと*/

/*****************************************************
tabulate プロシージャは,ひとことでいうとfreq プロシージャと同じく
クロス表を出力するプロシージャです.
特長は,Freqが2変数の度数クロス表(2元分割表)が基本であるのに対し,
tabulate は,3変数以上の複雑なクロス表が作成できることです.
また,度数(オブザベーションの件数)だけでなく,平均,標準偏差などの
統計量も表示できるので,means/summary プロシージャの基本機能ももっている
といえます.
*/


/*
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

*/

/*
freqで,発送先の性別X年齢度数クロス表をつくります.
*/


proc freq data=creditcard;
  tables xgender*xage;

run;
/*
xgender        xage

度数          |
パーセント    |
行のパーセント|
列のパーセント|      30|      40|      50|      60|   合計
--------------+--------+--------+--------+--------+
female        |     35 |     79 |     73 |    115 |    302
              |   2.41 |   5.45 |   5.03 |   7.93 |  20.83
              |  11.59 |  26.16 |  24.17 |  38.08 |
              |  33.02 |  21.70 |  18.16 |  19.90 |
--------------+--------+--------+--------+--------+
male          |     71 |    285 |    329 |    463 |   1148
              |   4.90 |  19.66 |  22.69 |  31.93 |  79.17
              |   6.18 |  24.83 |  28.66 |  40.33 |
              |  66.98 |  78.30 |  81.84 |  80.10 |
--------------+--------+--------+--------+--------+
合計               106      364      402      578     1450
                  7.31    25.10    27.72    39.86   100.00
*/

/*
同じ内容の表を,tabulateで作ると..   */

proc tabulate data=creditcard;
  class xgender xage;
  table xgender,xage;

run;

/*
--------------------------------------------------------------------------------
|                          |                       xage                        |
|                          |---------------------------------------------------|
|                          |     30     |     40     |     50     |     60     |
|                          |------------+------------+------------+------------|
|                          |     N      |     N      |     N      |     N      |
|--------------------------+------------+------------+------------+------------|
|xgender                   |            |            |            |            |
|--------------------------|            |            |            |            |
|female                    |       35.00|       79.00|       73.00|      115.00|
|--------------------------+------------+------------+------------+------------|
|male                      |       71.00|      285.00|      329.00|      463.00|
--------------------------------------------------------------------------------
*/

/*
freqとtabulateで,度数表としては同じ内容のものが得られました.
違いを確認しておくと,
1.tabulateでは,変数をclass文で宣言しないと,table文で使えない
2.freq では,パーセント,計が自動的に書かれる.
の2つが大事です.
前者は,tabulateを使う際の面倒な点ですが,度数以外の統計量を扱うために
このような記述が要求されます.(詳しくはsession 3 で.)
後者は,tabulateの場合は,パーセントや計は,表示するように指定することができます.
小さい表だと,自動的に表示されたほうが便利かもしれませんが,少し大きい表だと,
3つのパーセンテージは,じゃまです.
*/


/************************************************************
tabulateで,計と横パーセント(性別年齢構成比)を追加してみます.
ついでに,度数の表示フォーマットも,小数点以下四捨五入にします.
*/

proc tabulate data=creditcard;
  class xgender xage;
  table (all xgender)*(n*f=7. rowpctn)
       ,all xage;
run;

/*
---------------------------------------------------------------------------------------------
|                          |            |                       xage                        |
|                          |            |---------------------------------------------------|
|                          |    All     |     30     |     40     |     50     |     60     |
|--------------------------+------------+------------+------------+------------+------------|
|All         |N            |        1450|         106|         364|         402|         578|
|            |-------------+------------+------------+------------+------------+------------|
|            |RowPctN      |      100.00|        7.31|       25.10|       27.72|       39.86|
|------------+-------------+------------+------------+------------+------------+------------|
|xgender     |             |            |            |            |            |            |
|------------+-------------|            |            |            |            |            |
|female      |N            |         302|          35|          79|          73|         115|
|            |-------------+------------+------------+------------+------------+------------|
|            |RowPctN      |      100.00|       11.59|       26.16|       24.17|       38.08|
|------------+-------------+------------+------------+------------+------------+------------|
|male        |N            |        1148|          71|         285|         329|         463|
|            |-------------+------------+------------+------------+------------+------------|
|            |RowPctN      |      100.00|        6.18|       24.83|       28.66|       40.33|
---------------------------------------------------------------------------------------------
*/

/*
table文を細かく指定することで,目的の表の形をつくります.詳しいことは,
後のセッションにゆずりますので,ここでは簡単な解説にしておきます.
ALL というキーワードが,計を意味します.
ここでは,性別 xgenderより前に,ALL を書いたので,表側の縦計が先頭行になっています.
表頭の年齢についても同じです.
ですから,freqと同じように,計を右下にもってくることもできます.
この表のように,計を左上にもってくるのは,私の好みです.
まず全体でいくつあって,それをドリルダウンしていくというトップダウンな探索を
イメージしています.
n と rowpctn で件数と横パーセントを表示させています.n は,デフォルトなので,
表示統計量が指定されていなければ,度数 n が表示されます.f=7.は,その前の
n をフォーマット7. で表示せよということです.
*/


/***************************************************
次に3変数でのクロス表をつくります.
年収xincomeを追加し,xgenderとxincomeを表側でクロスさせ,表頭の年齢とあわせます
*/

proc tabulate data=creditcard formchar="           " noseps missing format=7.;
  class xgender xage xincome;
  table all xgender*xincome
       ,all xage;
run;

/*
                                                 xage

                              All     30      40      50      60

                               N       N       N       N       N

 All                           1450     106     364     402     578
 xgender      xincome
 female       .                   2       .       1       .       1
              1                 128      16      30      30      52
              100                59      10      24      10      15
              300                50       8      15      16      11
              500                25       1       6       6      12
              700                19       .       .       6      13
              1000               19       .       3       5      11
 male         .                  32       3      14       5      10
              1                 545      40     125     149     231
              100                55       7      37       5       6
              300               108      14      39      37      18
              500               129       5      43      44      37
              700               119       1      19      43      56
              1000              160       1       8      46     105

*/

/*
見た目がずいぶんかわりましたが,「 formchar="           " noseps」の指定で,
罫線をとったからです.
表側で,xgenderとxincomeをクロスさせましたが,表頭でも同じです.
さらにクロスを3変数,4変数と深くしていくこともできます.
*/

/***************************************************
今度は,度数やパーセンテージではなく,別な変数の平均値を
表示させてみます.
年齢,性別毎の年間総利用料の平均をクロス表にしてみましょう.*/

proc tabulate data=creditcard formchar="           " noseps missing format=comma9.;
  class xgender xage;
  var xusage;
  table all xgender
       ,(all xage)*xusage*mean;

run;

/*
                                                       xage

                               All       30        40        50        60

                             xusage    xusage    xusage    xusage    xusage

                              Mean      Mean      Mean      Mean      Mean

 All                          118,759   114,906   124,561   123,731   112,353
 xgender
 female                       135,464   121,143   144,177   139,452   131,304
 male                         114,364   111,831   119,123   120,243   107,646
*/

/*
xusage*meanが,年間総利用料の平均値の表示を指定しています.
xusageは,class文ではなく,var文で宣言されており,xusageを,
カテゴリ分類ではなく,値を平均したり,標準偏差を求めたり
する対象として使うことを意味しています.
meanは,n,rowpctn と同じく統計量のキーワードです.
*/

/********************************************************
このセッションの最後に,tabulateを使って,データの特徴を視覚化(?!)して,探索的に分析することに
向いていることを紹介します.私が,tabulateを使う多くの理由がこれです.
視覚化といっても,あくまでクロス表でしかなく,グラフィックなものではないのですが,
これも立派な「元祖」視覚化だと思います.
下のtabulate プログラムとその出力されたクロス表は,カード会員の入会日MbrSinceと退会日CxlDateの
度数クロス表です.(実際のデータは大きいので,アップしません.結果だけみてください)
うっすらとですが,左上から右下に退会者の山の稜線が3本ほど見えると思います.
それぞれ,入会日の3ヶ月後と,12ヶ月後,24ヵ月後あたりです.
目を細めたほうがいいかもしれません.(もっとはっきり見えるデータもあるのですが,ちょっと手元には,
こんなのしかなかった)
これは,どの月の入会客も,入会日の3ヶ月後と以降12ヶ月の倍数月にやめやすい,
それは,年会費請求のタイミングがトリガーになっているということが,視覚的にわかるわけです.
この例では,たいした発見ではありませんが,それでも,この3本の斜めの稜線以外にも,
縦に,すなわち特定の月に退会の集中傾向のある部分も見えます.
クロス表を眺めてみつけたいくつかの兆候を別な角度から検証して,退会のメカニズムを
紐解いていくと,この表がさらにくっきりしたものになっていきます.

このような分析作業をする場合,freqだと,表現力が高くないので,大量の統計量を
スプレッドして,眺めてみるということが難しい.
SASのステップの中で,繰り返し調整しながら探索できることが,tabulateの便利な
ところと思います.
*/


/*
proc tabulate data=CardMbr formchar="           " noseps missing format=3.;
  class MbrSince CxlDate;
  table all MbrSince="Member Since"
       ,all*f=7. CxlDate="Cancel Date"/rts=10;
  format MbrSince CxlDate yymmdd4.;
  run;

                                                             Cancel Date

                      99- 99- 99- 99- 99- 00- 00- 00- 00- 00- 00- 00- 00- 00- 00- 00- 00- 01- 01- 01- 01- 01- 01- 01-
            All    .  08  09  10  11  12  01  02  03  04  05  06  07  08  09  10  11  12  01  02  03  04  05  06  07

             N     N   N   N   N   N   N   N   N   N   N   N   N   N   N   N   N   N   N   N   N   N   N   N   N   N

 All        40215 3E4 116 130 116 136 159 156 208 246 300 205 216 180 195 174 296 698 193 197 268 345 703 269 259 256
 Member
 Since
 9807        1136 869  12  16   7  10   6  18  13  12  17  25  22  11  18  12   8   6   2   6   6  12  16   5   4   3
 9808         852 667  20  12   6  12   6  10   4   6  11   9  10  13  13   4   8   4   5   2   3   7   8   6   5   1
 9809         826 590  20  18   8  20  11   9  10   5  13  11   7  12  14   9   9   9   8   2  13   9   6   5   3   5
 9810         899 691   6  11   7  10  16   8   7  19  12   9   3   8   8   8  16  14   4   4   6  12  10   6   3   1
 9811         645 514   2   8  11   6   5   5  11   7   7   9   5   3   2   2  11   6   5   1   6   4   9   1   1   4
 9812         690 533   6   5  12   7  12   8   9  11   8   5   5   1   2   1  11  13   3   4   9  11   7   2   2   3
 9901         728 508   5   5   3   5   7  12  19  22   7   5   3   4   3   3  15  61   7   3   3   8  10   5   2   3
 9902        1052 698   5   5   5   7   8   8  22  17  61  17   5   5   3   4   4  57   5  11   9  14  69   8   5   .
 9903        1352 927  12  14  12  13  12  22  26  27  20  11  14   8   8   7   6  28  13  11  20  20  98  11   4   8
 9904        1243 932   8   8  11  13  10  16  17  13  20  13  12  13  10   4   8  28   3   6  21  17  38   9  10   3
 9905        1371 1E3   5   4   9   8  11   5   7  14  12   7   7  13   6   4   2  43   9   2   7  13  17  10   6   9
 9906        1783 1E3   6  12   8   7  20   6  14  13  22  17  20  13  13   9  20  60   4   5   7   8  22  10  16   7
 9907        1647 1E3   4   2   7   7   6   8  13  13  10  14  16  18  10  16  17  52  11   4  10  12  18  11  10   8
 9908        1284 1E3   5  10   5   3   9   5  10  17  13   7   7   5  17   4  10  36   5   7   5  14  12   2   7   8
 9909        1121 897   .   .   3   3  11   2   3  10  11   3  12   6  12  11  14  76   8   2   3   7   4   9   5   9
 9910        1181 983   .   .   2   1   6   3   9   8  15   5   9   7   8  15  19  45   6   6   5  10   6   2   7   4
 9911        1000 825   .   .   .   4   2   3   4   9   8   8   9   7   2  10  13  40  10  13  10   4   7   1   5   6
 9912        1202 983   .   .   .   .   1   7   4  11   9   6   9   2   6   5  14  49  15   9   8  12  32   8   5   7
 0001        1008 827   .   .   .   .   .   1   6   9  10   7  12   4   3   6  13  12   8   9   8  10  52   7   2   2
 0002         888 725   .   .   .   .   .   .   .   3   6   6   5  10   7   5   8   7   8  11  15  12  39   9   7   5
 0003        1186 1E3   .   .   .   .   .   .   .   .   7   6   5   6   1   6   7   7   6  12  13  20  40  12   6   6
 0004        1161 1E3   .   .   .   .   .   .   .   .   1   5   8   3  10   4   9   5   5  11  16  11  34  14  13   6
 0005        1216 1E3   .   .   .   .   .   .   .   .   .   .  10   3   2   6  11   6   6   5   5  14  33   6   7   7
 0006        1167 1E3   .   .   .   .   .   .   .   .   .   .   1   5   6   5  11   2   6   6   1  10  15   8  21   9
 0007        1025 913   .   .   .   .   .   .   .   .   .   .   .   .   7   6  10   8   5   8   8  11  10  11  11  17
 0008         939 846   .   .   .   .   .   .   .   .   .   .   .   .   4   6   8   3  11   7   4   9  12   5  10  14
 0009         910 803   .   .   .   .   .   .   .   .   .   .   .   .   .   2   6  13   4  16  10  12  11   8  10  15
 0010         993 881   .   .   .   .   .   .   .   .   .   .   .   .   .   .   8   8   7   8  18   9  17  13  12  12
 0011         984 927   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4   1   5  14  10  11   7   5
 0012        1053 1E3   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   5   6   5   8   5   3  11
 0101         822 761   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   8   5  14  15  10   9
 0102         862 822   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   7   9   6   7  11
 0103        1245 1E3   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   2   8  16  11  10
 0104        1324 1E3   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   2  12  10   7
 0105        1107 1E3   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   8   6
 0106        1170 1E3   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   4  14
 0107        1143 1E3   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   .   1
*/

******************************************************************************************;
************** E N D *********************************************************************;
******************************************************************************************;

質問・意見

サマリ 質問の要旨を簡潔にお願いします。
お名前
状態
メッセージ

質問・意見一覧

一覧に表示する項目はありません.