サンプリング

Last-modified: 2008-08-05 (火) 16:01:03

サンプリングの方法について紹介します.

もっとも簡単なサンプリング

非常に簡単にサンプリングをする方法として,①一様乱数関数?を使う方法と,②nth(n番目毎に抽出)を紹介します.

  • 一様乱数を使う方法
    data sample;set master;
      if ranuni(0)<0.1; /*乱数が0.1未満(10%の確率で起こる)のとき抽出*/
      *if ranuni(1)<0.1; /*もし,同じ乱数で再現したい場合は,シード値を正整数にしておくこと*/
    run;
  • nth(n番目毎に抽出)
    data sample;set master;
      if mod(_n_,10)=1; /*1,11,21番目と10件ごとに抽出*/
    run;

これらの方法は,サンプリングレート(抽出比率)を与えることで,プログラムにサンプルリングを行わせます.サンプリングレートではなく,ほしいサンプル数を与えてサンプリングさせる方法を次に示します.

SURVEYSELECTプロシジャを使う方法

SASでサンプリングを行う最も簡単な方法は、SAS/STATのSURVEYSELECTプロシジャ
を利用することです。
具体的には、OUT=で出力デーセットを、またN=でオブザベーション数を指定します。
SEED=を指定すれば、そのシードに基づいて乱数が内部で生成されます。
指定しないと、システムクロックに基づいて乱数が生成されます。
まずは、単純にサンプリングする方法から。


data test;   /*サンプルデータ。100オブザベーション*/
  do id=1 to 100;
    output;
  end;
run;

/*SURVEYSELECTプロシジャで、データセットWORK.testから
 データセットWORK.samp1へ20のオブザベーションをランダムに抽出する。
 その時のシードは4649。*/
proc surveyselect data=test
             out=samp1 n=20 seed=4649;
run;

/*
単純なサンプリングであれば、DATAステップだけでも
可能です。 以下のプログラムは、前項と同じように
20オブザベーションを抽出するものです。
*/
data samp2;
  retain _n 20;
  set test nobs=_obs;
  if (_obs+1-_n_)*rand('uniform')<=_n then do;
    _n=_n-1;
    output;
  end;
run;

/*
SURVEYSELECTプロシジャには、他にも様々な機能が備わって
います。サンプルデータとして、変数groupをグループ変数として、
5つのグループ(1~5)を作成し、各グループには10~50と10刻みで
オブザベーションが含まれているものを用意します。計150オブザベーション
です。
 */

data test2;
  do group=1 to 5;
    do i=1 to group*10;
	  id+1;
	  output;
	end;
  end;
run;

/*
次のプログラムは、データセットWORK.test2の各グループから一律
20%ずつデータをランダムに抽出します。 この割合は、SAMPRATE=オプションで
与えることができます。
 */
proc surveyselect data=test2 out=samp2 samprate=0.2;
  strata group; /*グループ変数はSTRATAステートメントで指定する。*/
run;

一般化nthサンプリング

乱数を使わないサンプリングの1つにnth(エヌス)サンプリングがあります.オブザベーションを順に数えて,n番目(n-th)のものを抽出するという非常にシンプルなもので,オブザベーションの並びに周期性が認められなければ,①乱数を使わない,②再現しやすいというメリットがあります.
以下に,n個毎に1個とるのではなく,n個毎にm個とるように一般化したnthサンプリングのプログラムを記載します.

options nocenter;

data all;
  do i=1 to 35000;
   id=_n_;
   output;
  end;
run;

*************************************************
 nth.sas
 一般化nth sampling
 n件毎に抽出するサンプリングロジック
 nの値が,2未満や小数でも実行できるように一般化
 例)10個から7個とる場合
 _n_     1   2   3   4   5   6   7   8   9  10
 num    0.7 1.4 2.1 2.8 3.5 4.2 4.9 5.6 6.3 7.0
 抽出    x   o   o   x   o   o   x   o   o   o

 020622 翔 nobs=で,元データ数を自動取得
*************************************************;
%let all=all;    /* 元データセット名 */
%let smp=smp;    /* サンプリングデータセット名 */
%let r=1100;     /* サンプル抽出数 */
data &smp;set &all nobs=nobs;
  num=_n_*&r/nobs;
  lag=lag(num);
  if int(lag) ne int(num) and int(num)>=1 then output;
run;


/* 結果チェック 等分布になるはず.グラフの両端は半幅なので,高さが同じではないことに注意 */
proc chart;hvar i/levels=10;run;