【问题标题】:Removing rows between two values in SAS删除SAS中两个值之间的行
【发布时间】:2020-02-26 01:56:16
【问题描述】:

对于以下数据,我尝试根据这些条件过滤每个组 ID 的行:

  • 在每行带有type='B' and value='Y' 之后执行以下操作
    • 删除行,直到下一行具有type='F' and value='Y'
  • 如果没有 B='Y,则保留所有这些(例如 id=002)

我们可以创建我想要的数据集中显示的标志变量吗?这样我就可以过滤 Flag='Y'?

  ID     Type     Date         Value
  001     F       1/2/2018      Y
  001     B       1/3/2018
  001     B       1/4/2018      Y
  001     B       1/5/2018
  001     B       1/6/2018
  001     F       1/6/2018      Y
  001     B       1/6/2018      
  001     B       1/7/2018
  001     B       1/8/2018      Y
  001     B       1/8/2018
  001     B       1/9/2018
  002     F       1/2/2018      Y
  002     B       1/3/2018
  002     B       1/4/2018

想要

  ID     Type     Date         Value   Flag
  001     F       1/2/2018      Y       Y
  001     B       1/3/2018              Y
  001     B       1/4/2018      Y       Y 
  001     B       1/5/2018
  001     B       1/6/2018
  001     F       1/6/2018      Y       Y
  001     B       1/6/2018              Y
  001     B       1/7/2018              Y
  001     B       1/8/2018      Y       Y 
  001     B       1/8/2018
  001     B       1/9/2018
  002     F       1/2/2018      Y       Y
  002     B       1/3/2018              Y
  002     B       1/4/2018              Y

我尝试了以下操作

data F;
set have;
where Type='F';run;

data B;
 set have;
 where Type='B';run;

 proc sql;
  create table all as select
  a.* from B as b
  inner join F as f
  on a.id=b.id
  and b.date >= a.date;
quit;

这包括我的数据集中的所有行。非常感谢任何帮助。

【问题讨论】:

  • 消除或保留行的标准是什么?

标签: sas delete-row retain proc-sql


【解决方案1】:

将行的状态计算为组@98​​7654321@ 中连续子组的一部分(称为行的“运行”)的标准相对简单,但如果某些情况下可能会出现或指示受损状态有趣的数据案例发生:

  • 在 F Y 之前有两个或多个 B Y(额外的“运行结束”)
  • 在 B Y 之前有两个或多个 F Y(运行中的“运行开始”)
  • 组中的第一行不是 F Y(“运行开始”不是组中的第一行)
data want(drop=run_:);
  SET have;
  BY id;

  run_first = (type='F' and value='Y');
  run_final = (type='B' and value='Y');

  * set flag state at criteria for start of contiguous sub-group criteria;
  run_flag + run_first;

  if first.id and NOT run_flag then
    put 'WARNING: first row in group ' id= ' is not F Y, this may be incorrect';

  if run_flag > 1 and run_first then 
    put 'WARNING: an additional F Y before a B Y at row ' _n_;

  if run_flag then
    OUTPUT;

  if run_flag = 0 and run_final then 
    put 'WARNING: an additional B Y before a F Y at row ' _n_;

  * reset flag at criteria for contiguous sub-group;
  if last.id or run_final then 
    run_flag = 0;
run;

【讨论】:

  • 嗨,理查德。有没有办法添加与“在一行 F Y 之前的一个额外 B Y”相关的案例?
  • 当然可以。假设,在单个 DATA 步骤中,您想要输出 直到并包括在 F Y 行之前的 最后 B Y 行的行,而不是 直到并包括在 F Y 行之前的 第一个 B Y 行。如果是这样,您可以将已知的(在 SAS 编码器圈中)编码为 DOW 循环。如果确实是这种情况,请撰写一个新问题(在搜索和阅读涉及 SAS 'DOW' 的其他答案之后)。
【解决方案2】:

和 Richard 一样,我不太明白过滤条件是什么。

我发现您的加入存在一个问题。您在 select 语句中使用了 a.*,但使用“b”和“f”作为数据集别名。这不起作用,因为没有数据集被分配给别名“a”。

正确的方法如下:

proc sql;
  create table all as 
  select b.* from B as b
  inner join F as f
  on b.id=f.id
  and b.date >= f.date;
quit;

但是,即使那样,我也不相信内部联接是解决您的问题的正确方法。请告诉我们您的过滤条件?

【讨论】:

  • 感谢 Richard 和 Pin。过滤器是删除每个 type B='Y' 行之后的行,直到它到达下一个 type='F' 行。如果没有 B='Y 则保留所有这些(例如 id=002)
  • 谢谢,我在新答案中发布了我的尝试,请检查一下并告诉我您的想法,希望它能解决您的问题
【解决方案3】:

我有一个解决方案,但它不是最优雅的(可能无法涵盖极端情况。)如果其他人有更好的解决方案,请分享。

首先,创建数据集以防其他人想尝试:

Data work.have;
  input @01 ID 3.
        @05 Type $1.
        @07 Date date7.
        @18 Value $1.;
  format ID 3.
         Type $1.
         Date date11.
         Value $1.; 
  datalines;
001 F '02Jan18'n Y
001 B '03Jan18'n  
001 B '04Jan18'n Y
001 B '05Jan18'n  
001 B '06Jan18'n 
001 F '06Jan18'n Y
001 B '06Jan18'n 
001 B '07Jan18'n 
001 B '08Jan18'n Y
001 B '08Jan18'n 
001 B '09Jan18'n 
002 F '02Jan18'n Y
002 B '03Jan18'n 
002 B '04Jan18'n 
;
run;

解决方案: 我基于您编辑的创建标志变量的建议。

Data Flag;
  set work.have;

  if Type = 'B' and Value = 'Y' then
    flag + 1;
  if Type = 'F' then
    flag = 0;

  if Value ne 'Y' and flag = 1 then delete;
run;

标志变量默认为0。

第一个 IF-Then 条件标识 Type B ='Y' 行并将它们标记为 1,并为后续行保留此标志。

第二个 IF-Then 条件识别 type='F' 行并将 Flag 重置为 0

Last If-Then 条件删除所有 Flag=1 的行,除了第一次出现的 Type B ='Y' 行。

我希望这适用于您的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-25
    • 1970-01-01
    • 2017-07-13
    相关资源
    最近更新 更多