【问题标题】:SAS - Drop observations once a condition is met, by IDSAS - 一旦满足条件,就按 ID 删除观察结果
【发布时间】:2013-12-14 22:14:45
【问题描述】:

对于每个 ID,我想删除在虚拟变量取值为 1 之后的所有观察结果。例如:

我拥有的数据:

ID  TIME    DUMMY 
1   1       0
1   2       0
1   3       1
1   4       0
2   1       0
2   2       0
2   3       1
3   1       1
3   2       0
3   3       0

我想要的输出:

ID  TIME    DUMMY 
1   1       0
1   2       0
1   3       1
2   1       0
2   2       0
2   3       1
3   1       1

【问题讨论】:

  • 那么,到目前为止,您尝试了什么?问题不是很清楚,您要删除多少个观察值。因为在第一个 DUMMY=1 之后,您放弃了一个观察结果。但是随后您在数据集的末尾删除了两个观察结果..
  • 很抱歉造成误解;对于给定的 ID,我想在虚拟变量取值 1 后删除所有观察值。这就是为什么在我的示例中,丢弃的观察值数量取决于 ID。

标签: sas


【解决方案1】:

这是一种方法:

data want(drop = a);
  set have;
  by id;
  retain a;
  if first.id then a = 1;
  if a = 1 then output;
  if dummy = 1 then a = 0;
run;

【讨论】:

  • 倒数第三行应该是: if lag(dummy) = 1 then a = 0;谢谢!
  • 如果您有两个连续的 ID,每行都有 dummy =1,那么您的滞后条件会在您实际想要保留第二个 ID 时删除它。我在上面所做的修复避免了这样做。
  • 看起来不错,但我会使用更好的变量名来明确(不是 a 作为触发器)。
【解决方案2】:

使用 dow-loop 似乎比保留和滞后更优雅。 在此处阅读有关此编程结构的更多信息:http://analytics.ncsu.edu/sesug/2011/SS01.Dorfman.pdf 很有用。

data want(drop=printit);
    if 0 then set have;
    printit = last.id;
    do until(last.id or dummy);
        set have;
        by id;
        if printit then output;
    end;
run;

do 语句之前的行只是为了保持列的原始顺序。

【讨论】:

  • if printit then output; 如何输出除每个 ID 中的最后一条以外的任何记录?
  • 首先要了解的是那里有 2 个有效循环。整个数据步骤的隐式循环和显式 do 循环。退出 do 循环有两种替代条件,即按组结束(因此 last.id = 1)或当 dummy = 1 时。退出内部循环后,执行返回到 do 语句上方的行,printit 是更新:如果 do 循环因为 dummy 而退出,则为 0,如果因为 last.id 而退出,则为 1。因此,在 dummy=1 之后和按组更改之前的记录将被忽略。在 do 语句之前使用 put _all_; 以查看发生了什么。
  • 如果第一行 dummy = 0,并且它不是 by 组中的唯一行,它如何获得输出?根据我对它的阅读,显式 do 循环将直接到达 by 组中的最后一行并仅输出该行。然后 printit 将设置为 1,然后再为下一组开始循环。如果您能稍微扩展您的答案(根据您自己的建议)以解释它是如何工作的,我将不胜感激,因为这将有助于人们更好地理解它。
  • 方便,第一次迭代前last.id默认为1,所以printit = 1。直到执行完do块后才会计算直到条件,所以last.id发生时更新为0 . Dummy 在第一次迭代中不扮演任何角色。
【解决方案3】:

我将使用OUTPUTRETAINRETURN 语句的帮助来覆盖DATA 步骤循环。 RETURN 语句强制DATA 步骤立即进入下一个迭代。这应该删除 DUMMYs = 1 观察之间的所有观察:

data want;
    set test;
    drop count;
    if DUMMY = 1 then do;
        retain count;
        count = 1;
        output;
        return;
    end;

    if count = 1 and DUMMY ne 1 then do;
        retain count;
        delete;
        return;
    end;
    output;

run;

输出:

                                ID    TIME    DUMMY

                                 1      1       0
                                 1      2       0
                                 1      3       1
                                 2      3       1
                                 3      1       1

【讨论】:

  • 这不能回答我原来的问题。您的输出与问题中显示的不匹配。 user667489 提出了一种正确的方法,以及我提出的修改。谢谢
  • 您说您希望删除 DUMMY 变量取值为 1 后的所有观察结果..
  • @YickLeung 对于 ID = 2,您在 dummy 取值为 1 之前删除了两个观察值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-16
  • 2014-10-09
  • 1970-01-01
  • 1970-01-01
  • 2016-01-29
  • 2022-08-31
  • 2013-06-24
相关资源
最近更新 更多