2017-09-15 6 views
2

私のデータは縦方向です。縦方向のデータを置換しないランダムサンプリング

VISIT ID VAR1 
1  001 ... 
1  002 ... 
1  003 ... 
1  004 ... 
... 
2  001 ... 
2  002 ... 
2  003 ... 
2  004 ... 

最終的な目標は、テストを実行するたびに10%の訪問を選ぶことです。私はproc SURVEYSELECTを使用してSRSを置き換えずに行い、 "VISIT"を階層として使用しようとしました。しかし、最後のサンプルには重複IDがあります。たとえば、VISIT = 1およびVISIT = 2の両方でID = 001が選択されている可能性があります。

SURVEYSELECTや他の手順を使用する方法はありますか(Rも問題ありません)?どうもありがとう。

+0

したがって、訪問ごとに10%を使いたいが、最終データセットのすべてのIDは一意である必要がありますか? – useR

+0

はい。あなたが言ったのとまったく同じです。 –

+0

IDは訪問時に一意である限り、ave: 'dat $ picked < - ave(dat。$ VISIT)、dat $ VISIT、sample(c(TRUE、FALSE)、length(x) probs = c(.1、.9)、replac = TRUE)) 'となります。 – lmo

答えて

0

これはかなり創造的なデータステッププログラミングで可能です。以下のコードでは、各訪問から順番にサンプリングし、以前にサンプリングされていないIDのみをサンプリングして貪欲なアプローチを使用しています。訪問のIDの90%以上が既にサンプリングされている場合、10%未満が出力されます。極端な場合には、訪問のIDがすべてサンプリングされた時点で、その訪問のための行は出力されません。

/*Create some test data*/ 
data test_data; 
    call streaminit(1); 
    do visit = 1 to 1000; 
    do id = 1 to ceil(rand('uniform')*1000); 
     output; 
    end; 
    end; 
run; 


data sample; 
    /*Create a hash object to keep track of unique IDs not sampled yet*/ 
    if 0 then set test_data; 
    call streaminit(0); 
    if _n_ = 1 then do; 
    declare hash h(); 
    rc = h.definekey('id'); 
    rc = h.definedata('available'); 
    rc = h.definedone(); 
    end; 
    /*Find out how many not-previously-sampled ids there are for the current visit*/ 
    do ids_per_visit = 1 by 1 until(last.visit); 
    set test_data; 
    by visit; 
    if h.find() ne 0 then do; 
     available = 1; 
     rc = h.add(); 
    end; 
    available_per_visit = sum(available_per_visit,available); 
    end; 
    /*Read through the current visit again, randomly sampling from the not-yet-sampled ids*/ 
    samprate = 0.1; 
    number_to_sample = round(available_per_visit * samprate,1); 
    do _n_ = 1 to ids_per_visit; 
    set test_data; 
    if available_per_visit > 0 then do; 
     rc = h.find(); 
     if available = 1 then do; 
     if rand('uniform') < number_to_sample/available_per_visit then do; 
      available = 0; 
      rc = h.replace(); 
      samples_per_visit = sum(samples_per_visit,1); 
      output; 
      number_to_sample = number_to_sample - 1; 
     end; 
     available_per_visit = available_per_visit - 1; 
     end; 
    end; 
    end; 
run; 

/*Check that there are no duplicate IDs*/ 
proc sort data = sample out = sample_dedup nodupkey; 
by id; 
run; 
関連する問題