gpt4 book ai didi

replace - 在 SAS 中查找并替换单独表中的值

转载 作者:行者123 更新时间:2023-12-02 06:48:45 28 4
gpt4 key购买 nike

数据集 HAVE 包含两个名称拼写错误的变量:namesfriends

Name   Age   Friend
Jon 11 Ann
Jon 11 Tom
Jimb 12 Egg
Joe 11 Egg
Joe 11 Anne
Joe 11 Tom
Jed 10 Ann

我有一个小型数据集 CORRECTIONS,其中包括 wrong_namesresolved_names

current_names   resolved_names
Jon John
Ann Anne
Jimb Jim

我需要 namesHAVE 中的 friends 中的任何名称与 wrong_names 列中的名称相匹配CORRECTIONS 以重新编码为 resolved_name 中的相应字符串。生成的数据集 WANT 应该如下所示:

Name   Age   Friend
John 11 Anne
John 11 Tom
Jim 12 Egg
Joe 11 Egg
Joe 11 Anne
Joe 11 Tom
Jed 10 Anne

在 R 中,我可以使用 if_else() 简单地调用每个数据帧和向量,但 SAS 中的 DATA 步骤不能很好地处理多个数据集。我如何使用 CORRECTIONS 作为查找表来进行这些替换?

最佳答案

在 SAS 中有很多方法可以进行查找。

不过,首先,我建议对查找表进行重复数据删除(例如,使用 PROC SORT 和数据步骤/设置/依据)- 决定保留哪些重复项(如果存在)。

至于查找任务本身,为了简单和学习,我建议如下:

“OLD SCHOOL”方式 - 适用于审核输入和输出(当输入表按要求的顺序时更容易验证连接的结果):

*** data to validate;
data have;
length name $10. age 4. friend $10.;
input name age friend;
datalines;
Jon 11 Ann
Jon 11 Tom
Jimb 12 Egg
Joe 11 Egg
Joe 11 Anne
Joe 11 Tom
Jed 10 Ann
run;

*** lookup table;
data corrections;
length current_names $10. resolved_names $10.;
input current_names resolved_names;
datalines;
Jon John
Ann Anne
Jimb Jim
run;

*** de-duplicate lookup table;
proc sort data=corrections nodupkey; by current_names; run;

proc sort data=have; by name; run;

data have_corrected;
merge have(in=a)
corrections(in=b rename=(current_names=name))
;
by name;
if a;
if b then do;
name=resolved_names;
end;
run;

SQL 方式 - 避免对 have 表进行排序:

proc sql;
create table have_corrected_sql as
select
coalesce(b.resolved_names, a.name) as name,
a.age,
a.friend
from work.have as a left join work.corrections as b
on a.name eq b.current_names
order by name;
quit;

注意 Coalesce() 用于用 have 表中的名称替换缺失的 resolved_names 值(即没有更正时)

编辑:为了反射(reflect) Quentin 的(正确)评论,即我错过了对姓名和 friend 字段的更新。

基于更正 2 个字段,同样有许多方法,但本质是仅当值存在于查找(更正)表中时才更新该值。散列对象在这方面非常擅长,一旦您理解了它的声明。

注意:Hash 对象中的任何关键字段都需要在 Length 语句之前指定。

编辑:根据 ChrisJ 对 Length 语句声明的替代方案和我的回复(见下文)- 最好声明在声明哈希表之前需要定义关键变量。

data have_corrected;
keep name age friend;
length current_names $10.;

*** load valid names into hash lookup table;
if _n_=1 then do;
declare hash h(dataset: 'work.corrections');
rc = h.defineKey('current_names');
rc = h.defineData('resolved_names');
rc = h.defineDone();
end;
do until(eof);
set have(in=a) end=eof;
*** validate both name fields;
if h.find(key:name) eq 0 then
name = resolved_names;
if h.find(key:friend) eq 0 then
friend = resolved_names;
output;
end;
run;

编辑:回答有关 ChrisJ 的 SQL/更新替代方案的评论

基本上,您需要将每个 UPDATE 语句限制为仅在更正表中具有名称值或友元值的行 - 这是通过在指定 set var = (clause) 之后添加另一个 where 子句来完成的。见下文。

注意。 AFAIK,满足您要求的 SQL 解决方案将需要对基表和查找表进行 1 次以上的传递。

然而,查找/哈希表需要单次传递基表,加载查找表,然后是查找操作本身。您可以在日志中看到性能差异...

proc sql;
*** create copy of have table;
create table work.have_sql as select * from work.have;
*** correct name field;
update work.have_sql as u
set name = (select resolved_names
from work.corrections as n
where u.name=n.current_names)
where u.name in (select current_names from work.corrections)
;
*** correct friend field;
update work.have_sql as u
set friend = (select resolved_names
from work.corrections as n
where u.friend=n.current_names)
where u.friend in (select current_names from work.corrections)
;
quit;

关于replace - 在 SAS 中查找并替换单独表中的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50547587/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com