我想使用数据集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。
答案 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()
不会发生这种情况)。