【问题标题】:SAS Data Step counting nodes/edges in a graphSAS 数据步数计算图中的节点/边
【发布时间】:2012-10-30 04:34:43
【问题描述】:

假设我在名为links 的数据集中表示了一个有向 图,它有两个变量:from_idto_id。我想使用 SAS Data Step 做两件事:(1)计算节点数,(2)计算边数。

假设links数据集如下所示。

from_id    to_id
----------------
   1         2
   2         3
   3         1
   3         2

在这个例子中,有 3 个节点和 4 条边。 (我们可以假设links 中没有重复边)。节点是 1、2 和 3。边是 1->2、2->3、3->1 和 3->2。

下面是一个 SAS 宏,它使用 SAS Data Step 和 proc sql 来计算节点和边。它工作得很好,但我希望使用 SAS Data Step 以便(可能)更快地计算节点和边。

/* 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;

【问题讨论】:

  • 您可能拥有多少个节点?它们都适合记忆吗?
  • 多达几亿个节点/边。数据集很容易达到 10 GB 左右。虽然我可以访问内存更大的机器,但我的桌面客户端有 8 GB 内存。
  • 如果它不适合内存,您显然可以使用单个 proc 排序和单个数据步骤来完成。

标签: sas datastep


【解决方案1】:

如果你有足够的内存,你可以用一个散列对象来做到这一点。

请注意:此代码未经测试,因为我手头没有 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;

【讨论】:

  • 我要添加的唯一两件事是 1:不要使用 NOBS,因为如果修改了数据集,那可能是错误的 - 使用 N 这显然是安全的;和2:添加之前不需要检查节点是否存在于哈希中吗?否则你会添加重复的节点,我想?
  • 我认为调用 add() 时会删除重复项,所以应该没问题。但是关于 N 的优点。我会编辑。
  • 363 rc = h.defineKey(node_id); 然后ERROR: Uninitialized object at line 363 column 9.
  • 没有。 add() 不会自动检查。我在测试后对您的代码进行了编辑 - 它现在应该可以工作(如果它被批准)。除此之外,您还有一些小的语法问题,我已更正。
  • 太棒了!用了不到 10 分钟,而之前我为基于 proc sql 的方法等待了超过 45 分钟。再次感谢。
猜你喜欢
  • 2016-12-13
  • 1970-01-01
  • 1970-01-01
  • 2014-12-06
  • 1970-01-01
  • 1970-01-01
  • 2016-11-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多