根据 SAS / SQL 中的条件删除按两个变量分组



我正在寻找以下问题的解决方案。我正在使用SAS,因此欢迎使用基本的SQL或数据步骤方法。也许解决方案很简单,但我对 SAS 有点陌生,找不到解决方案。

我得到了一个数据集,并希望按条件删除第二级的子组。因此,为了使其更容易,让我解释一个例子。条件是:当 ColC 中的任何值为 1 时,则删除主组中的子组。主组是ColA,子组是ColB

ColA | ColB | ColC
1  |  a   |  0  
1  |  a   |  1  
1  |  b   |  0  
1  |  b   |  0  
2  |  a   |  0  
2  |  a   |  0  
2  |  b   |  0  
2  |  b   |  0  
3  |  a   |  0  
3  |  a   |  0  
3  |  b   |  1  
3  |  b   |  0  

预期产出:

ColA | ColB | ColC
1  |  b   |  0  
1  |  b   |  0  
2  |  a   |  0  
2  |  a   |  0  
2  |  b   |  0  
2  |  b   |  0  
3  |  a   |  0  
3  |  a   |  0  

我尝试了以下方法:

select * from data
group by ColA, ColB having ColC <> 1

我想,将按两列分组并选择没有 ColC=1 的所有组。但它只"删除"ColC=1 的行。

另一种方法是这样的:

select * from data
where ColA in (select ColA from data where ColC <> 1)

但是,当然,我无法通过此到达子组。我也在考虑加入,但不知道该怎么做。

SQL 中的having子句将允许您按摘要函数过滤查询。下面的查询说只包括ColC和按ColAColB分组后的总和为 0 的输出。

proc sql noprint;
create table want as 
select *
from have
group by ColA, ColB
having sum(ColC) = 0
;
quit;

您可以将not exists与相关的子查询一起使用:

select d.*
from data d
where not exists (select 1
from data d2 
where d2.cola = d.cola and d2.colb = d.colb and d2.colc = 1
);

这使所有没有1cola/colb的组合都保留在colc中。

这也可以适应delete,但您似乎想要一个过滤的结果集。

这是使用双 DoW 循环的数据步进方法

data have;
input ColA ColB $ ColC;
infile datalines dlm='|';
datalines;
1  |  a   |  0  
1  |  a   |  1  
1  |  b   |  0  
1  |  b   |  0  
2  |  a   |  0  
2  |  a   |  0  
2  |  b   |  0  
2  |  b   |  0  
3  |  a   |  0  
3  |  a   |  0  
3  |  b   |  1  
3  |  b   |  0  
;
data want (drop=c);
c = 1;
do _n_ = 1 by 1 until (last.ColB);
set have;
by ColA ColB;
if ColC = 1 then c = 0;
end;
do _n_ = 1 to _n_;
set have;
if c then output;
end;
run;

使用通用代码执行此操作的简单方法:

proc sort data=have;
by cola colb;
data want;
merge have (in=in1 where=(colc=1))
have (in=in2)
;
by cola colb;       
if ^in1;
run;

第一个 HAVE 选择所有 COLC=1 的记录,由于我们合并的是 COLA 和 COLB,因此 IF 语句将删除具有相同 COLA 和 COLB 的所有记录,这是目标。

此外,哈希对象方法

data want;
if _n_ = 1 then do;
declare hash h (dataset : 'have(where=(ColC=1))');
h.definekey ('ColA', 'ColB');
h.definedone();
end;
set have;
if h.check();
run;

最新更新