【问题标题】:Random sampling without replacement in longitudinal data纵向数据中不替换的随机抽样
【发布时间】:2018-02-24 21:34:03
【问题描述】:

我的数据是纵向的。

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 也可以)吗?非常感谢。

【问题讨论】:

  • 所以您想从每次访问中抽取 10%,但最终数据集中的所有 ID 都应该是唯一的?
  • 是的。就像你说的那样。
  • 只要访问的ID是唯一的,你可以使用ave:dat$picked <- ave(is.numeric(dat$VISIT), dat$VISIT, sample(c(TRUE, FALSE), length(x), probs=c(.1, .9), replac=TRUE))
  • @Imo 这并不能确保最终数据集具有唯一 ID。
  • 您的约束可能意味着,在对上次访问进行抽样时,没有剩余的 ID 尚未为上次访问抽样。如果发生这种情况,你想怎么办?

标签: r sas sas-macro statistical-sampling


【解决方案1】:

这可以通过一些相当有创意的数据步骤编程来实现。下面的代码使用了一种贪心的方法,依次从每次访问中采样,只对之前没有采样过的 id 进行采样。如果超过 90% 的访问 id 已经被采样,则输出不到 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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-20
    相关资源
    最近更新 更多