统计图中节点/边的SAS数据步
假设我有一个名为统计图中节点/边的SAS数据步,sas,datastep,Sas,Datastep,假设我有一个名为links的数据集中表示的有向图,它有两个变量:from\u id和to\u id。我想使用SAS数据步骤做两件事:(1)计算节点的数量,(2)计算边的数量 假设链接数据集如下所示 from_id to_id ---------------- 1 2 2 3 3 1 3 2 在本例中,有3个节点和4条边。(我们可以假设链接中没有重复的边。节点为1、2和3。边是1->2、2->3、3->
links
的数据集中表示的有向图,它有两个变量:from\u id
和to\u id
。我想使用SAS数据步骤做两件事:(1)计算节点的数量,(2)计算边的数量
假设链接
数据集如下所示
from_id to_id
----------------
1 2
2 3
3 1
3 2
在本例中,有3个节点和4条边。(我们可以假设链接中没有重复的边。节点为1、2和3。边是1->2、2->3、3->1和3->2
下面是一个SAS宏,它结合使用SAS数据步骤和proc sql来计算节点和边。它工作得很好,但我希望使用SAS数据步骤,以便(可能)更快地计算节点和边
/* display number of nodes and edges for graph */
%macro graph_info(links);
data nodes;
set &links;
node_id = from_id;
output;
node_id = to_id;
output;
keep node_id;
run;
proc sql noprint;
select count(distinct node_id) into :numNodes from nodes;
quit;
proc datasets lib=work nolist;
delete nodes;
quit;
proc sql noprint;
select count(*) into :numEdges from &links;
quit;
%put Nodes: &numNodes;
%put Edges: &numEdges;
%mend;
如果您有足够的内存,您可以使用散列对象来实现这一点
data _null_;
set links end=lastrec;
format node_id 8.;
if _N_ eq 1 then do;
declare hash h();
h.defineKey("node_id");
h.defineDone();
end;
node_id = from_id;
rc=h.find();
if rc ne 0 then h.add();
node_id = to_id;
rc=h.find();
if rc ne 0 then h.add();
if lastrec then do;
call symput('numLinks', put(h.num_items, 8. -L));
call symput('numEdges', put(_N_, 8. -L));
end;
run;
请注意:此代码未经测试,因为我手头没有SAS安装。然而,基本想法应该是可行的。迭代数据步骤,将每个节点添加到哈希对象,并在最后一个对象上将宏变量设置为哈希对象的大小
data _null_;
set links end=lastrec;
format node_id 8.;
if _N_ eq 1 then do;
declare hash h();
h.defineKey("node_id");
h.defineDone();
end;
node_id = from_id;
rc=h.find();
if rc ne 0 then h.add();
node_id = to_id;
rc=h.find();
if rc ne 0 then h.add();
if lastrec then do;
call symput('numLinks', put(h.num_items, 8. -L));
call symput('numEdges', put(_N_, 8. -L));
end;
run;
您可能有多少个节点?它们都适合内存吗?最多可容纳数亿个节点/边。数据集很容易达到10GB左右。虽然我可以访问内存更多的机器,但我的桌面客户端有8 GB的内存。如果它不适合内存,显然可以通过一个进程排序和一个数据步骤来完成。我要补充的两件事是:不要使用NOBS,因为如果数据集被修改,这可能会出错-使用N,这显然是安全的;和2:在添加节点之前,是否需要检查该节点是否存在于哈希中?否则您将添加重复的节点,我认为?我认为当您调用add()时,重复的节点将被删除,所以这样应该可以。但是关于N的观点很好。我将编辑。363rc=h.defineKey(node\u id)代码>然后错误:第363行第9列的未初始化对象。
No.add()不会自动检查。测试后,我对您的代码进行了编辑-现在应该可以工作了(如果批准的话)。除此之外,你还有一些小的语法问题,我已经纠正了。太好了!只花了不到10分钟的时间,而之前我等待基于proc-sql的方法的时间超过了45分钟。再次感谢。