如何在SAS中计算父子层级数据的代次?
计算SAS树形数据集中节点的代次
原始数据集
先创建示例数据集:
data tree; input child $ parent $; datalines; A . B A C A D B E C F D G E ; run;
解决方案一:递归FCMP函数(适配任意树深度)
这种方法通过递归查找父节点代次,适合不确定深度的树形结构,步骤如下:
- 为数据集创建索引,提升父节点查找效率
proc datasets lib=work nolist; modify tree; index create child / unique; run; quit;
- 定义递归函数计算代次
proc fcmp outlib=work.funcs.trees; function get_generation(node $) $; length parent $ 8 gen_num 8; set tree(keep=child parent) key=node; if _iorc_ = 0 then do; if missing(parent) then gen_num = 1; else gen_num = input(get_generation(parent), 8.) + 1; return(put(gen_num, 8.)); end; else return(''); endsub; run; options cmplib=work.funcs;
- 生成带代次的目标数据集
data tree_with_gen; set tree; generation = input(get_generation(child), 8.); run;
解决方案二:哈希表循环处理(无FCMP依赖)
如果无法使用FCMP函数,可通过哈希表存储已计算的代次,循环遍历完成所有节点的代次计算:
data tree_with_gen; set tree; length generation 8; declare hash gen_map(); gen_map.defineKey('child'); gen_map.defineData('generation'); gen_map.defineDone(); /* 先处理根节点 */ if missing(parent) then do; generation = 1; gen_map.add(); output; end; /* 循环处理非根节点,直到所有节点完成计算 */ do until (gen_map.num_items = nobs); set tree point=_n_; if not gen_map.check(key:child) then do; if gen_map.find(key:parent) = 0 then do; generation = generation + 1; gen_map.add(); output; end; end; if _n_ = nobs then _n_ = 0; end; nobs = nobs; drop _n_ nobs; run;
最终输出结果
两种方法均可得到如下目标数据集:
child $ parent $ generation A . 1 B A 2 C A 2 D B 3 E C 3 F D 4 G E 4
内容的提问来源于stack exchange,提问作者WaninGNighT
相关产品推荐
相关产品推荐

