SAS合并数据集以覆盖值

时间:2015-03-04 01:58:21

标签: sas

我想使用数据集B通过合并数据集A和A来覆盖数据集A中的某些值。 B具有合并ID。但是它没有按预期工作。这是我做的测试:

/* create table A */
data a;
  infile datalines;
  input id1 $ id2 $ var1;
datalines;
    1 a 10
    1 b 10
    2 a 10
    2 b 10
;
run;

/* create table B */
data b;
  infile datalines;
  input id1 $ var1 var2;
datalines;
    1 20 30
    2 20 30
;
run; 

/* merge A&B to overwrite var1 in table A using values in table B */
data c;
    merge a b;
    by id1;
run;

表C看起来像这样:

 ID1 ID2 VAR1 VAR2

 1   a     20   30

 1   b     10   30

 2   a     20   30

 2   b     10   30

为什么第2行和第4行中的10s没有被表B中的20替换?虽然var2按预期工作?

我知道我可以简单地使用proc SQL来做到这一点,这就是我为解决问题所做的。但是我仍然很好奇是否有办法用合并做我想做的事情?为什么这不起作用?在这种情况下,我更喜欢合并SQL,因为逻辑更容易实现(util我发现这不能正常工作)。

我使用SAS 9.4。

3 个答案:

答案 0 :(得分:2)

这与SAS在合并期间如何迭代数据集有关。基本上,每个A的第二个记录都没有与来自B的记录对齐.VAR2的值从前一个记录中转移。 VAR1从A获取其值(因为没有B)。

IF B中有 EVERY ID1的记录,那么您可以像这样重写合并来实现您的目标。

/* merge A&B to overwrite var1 in table A using values in table B */
data c;
    merge a(drop=var1) b;
    by id1;
run;

这会从A中删除VAR1,以便从B中的记录中删除它。

否则你需要更复杂的逻辑(我可以建议使用coalesce()函数进行SQL左连接吗?)。

答案 1 :(得分:2)

像DomPazz建议的那样,proc sql就是这样做的方法。 merge只会保留每个数据集中的一个值。 coalesce函数从列表中选择第一个非缺失值,因此它使用var1中的b,但如果b.var1为空,则使用a.var1

proc sql;
create table c as
select
  a.id1,
  a.id2,
  coalesce(b.var1,a.var1) as var1,
  b.var2
from
  a
  left join b
  on a.id1 = b.id1
;
quit;

答案 2 :(得分:1)

merge方法仍然可以正常工作,您只需要更明确地了解如何为var1选择“最佳”值,例如:

data c (drop = a_var1 b_var1);
    merge a(rename=(var1 = a_var1))
          b(rename=(var1 = b_var1));
    by id1;
    * Now you have two different variables named a_var1 and b_var1;
    * Implement logic to choose your favorite;
    if NOT MISSING(b_var1) Then DO;
        var1 = b_var1;
        var1_source='B';
    END;
    else DO;
        var1 = a_var1;
        var1_source='A';
    END;
run;

如果您选择“var1”的条件与“如果b存在,请使用它”一样简单,那么这与使用coalesce()的SQL方法相同。

我发现这个方法对于更复杂的标准很有用,而且总是很高兴知道数据的来源(coalesce()不会发生这种情况)。