基于另一行填充1行的SAS逻辑
我有这样一个SAS数据集:基于另一行填充1行的SAS逻辑,sas,Sas,我有这样一个SAS数据集: Name MgrName Dept. A B B C C D X Y 我需要用递归逻辑填写部门。我知道D是“工资单”的负责人,所以我填写: Name MgrName Dept. A B B C C D Payroll X Y 但使用某种递归,D报告链中的每个人(A、B、C)也需要分配“工资单”。在SAS中如何做到这一点?可能有一种更聪明的方法,但这里有一种哈希对象方法 data hav
Name MgrName Dept.
A B
B C
C D
X Y
我需要用递归逻辑填写部门。我知道D是“工资单”的负责人,所以我填写:
Name MgrName Dept.
A B
B C
C D Payroll
X Y
但使用某种递归,D报告链中的每个人(A、B、C)也需要分配“工资单”。在SAS中如何做到这一点?可能有一种更聪明的方法,但这里有一种哈希对象方法
data have;
input Name $ MgrName $;
datalines;
A B
B C
C D
X Y
;
data want(drop=rc);
declare hash h1(dataset:'have');
h1.definekey('MgrName');
h1.definedata('Name');
h1.definedone();
declare hash h2();
h2.definekey('Name');
h2.definedone();
length Name $ 100 MgrName $ 100;
do rc=h1.find(key:'D') by 0 while (rc=0);
h2.replace();
rc=h1.find(key:Name);
end;
do until (lr);
set have end=lr;
Dept=ifc(h2.check()=0, 'Payroll', '');
output;
end;
run;
以下是在
Proc DS2
程序上下文中基于哈希的方法
每个节点(名称)只有一个父节点(mgrname),因此哈希可以使用name键并将mgrname作为数据。循环查找方法将查找节点的祖先父级,或者不查找
示例(名称为id
,名称管理器为pid
):
数据已经存在;
输入id$pid$;数据线;
A B
B C
C D
fd
G F
氢氟酸
P H
Q H
R H
xy
跑
程序ds2;
数据需要/覆盖=是;
声明包哈希链接();
声明char\u seek\u pid;
声明char\u seek\u id;
申报部门;
保持部门id;
*填充散列;
方法init();
links.definekey('id');
链接。定义数据(“pid”);
dataset(“{select pid,id from have{options locktable=share}”);
links.multidata(“是”);
links.definedone();
结束;
*寻找应用价值的祖先;
方法apply(charrootid、char值、charid);
声明整数限制;
极限=0;
_seek_id=id;
暂且(
links.find([[u seek\u id],[u seek\u pid])=0和
限值<100和
rootid ne\u seek\u pid
);
上限+1;
_seek\u id=\u seek\u pid;
结束;
如果rootid=\u seek\u pid,则dept=value;
结束;
*将某些值应用于某些节点及其子节点;
方法run();
设置有(锁台=共享);
应用('D','payroll',id);
应用('F','shadow$',id);
结束;
enddata;
跑
退出
%让syslast=want;
您的数据是否可以有多个MgrName='D'值?谢谢。不,数据是这样的,“Name”和“MgrName”都是唯一的。名称是否有多个管理器?这种情况应该很少见,但在某些组织中可能会发生。经理可以有多个直接下属吗?这将是正常的,否则您将有N-1个管理者来管理N名员工。请注意,您的名称->管理者名称对基本上是在定义一个图。这里是关于如何找到连通子图的前一个问题。
data have;
input id $ pid $;datalines;
A B
B C
C D
F D
G F
H F
P H
Q H
R H
X Y
run;
proc ds2;
data want / overwrite=yes;
declare package hash links();
declare char _seek_pid;
declare char _seek_id;
declare char dept;
keep id pid dept;
* populate hash;
method init();
links.definekey('id');
links.definedata('pid');
links.dataset('{select pid, id from have {options locktable=share}}');
links.multidata('yes');
links.definedone();
end;
* seek ancestor from which value should be applied;
method apply(char rootid, char value, char id);
declare int limit;
limit = 0;
_seek_id = id;
do while (
links.find([_seek_id], [_seek_pid]) = 0 and
limit < 100 and
rootid ne _seek_pid
);
limit+1;
_seek_id = _seek_pid;
end;
if rootid = _seek_pid then dept = value;
end;
* apply some values to some nodes and children thereof;
method run();
set have (locktable=share);
apply ('D','payroll', id);
apply ('F','shadow$', id);
end;
enddata;
run;
quit;
%let syslast = want;