使用do循环创建层次结构

时间:2015-02-19 17:12:25

标签: loops sas

我正在尝试从两列构建层次结构,其中一列是客户端标识符,另一列是其直接父级,但我有一个问题,因为客户端可以拥有可以拥有另一个父级的父级。

目前我在宏中有许多合并语句

%macro hierarchy (level);
    data sourcedata (drop = PARENT_ID);
        merge sourcedata (in = a)
              inputdata (in = b);
        by CLIENT_ID;
        if a;
        length Parent_L&level $32.;
        Parent_L&level = PARENT_ID;

        if Parent_L&level = Parent_L%eval(&level-1) then Parent_L&level ="";
        CLIENT_ID = Parent_L&level;

    proc sort; 
        by Parent_L&level;
    run;
%mend;
%hierarchy(2)
%hierarchy(3)
%hierarchy(4)

我的输出看起来像

client_ID  Parent_L1 Parent_L2 Parent_L3 Parent_L4
clientA    clientB   .          .         .  
ClientE    clientA   clientB    .         .

我正在寻找的是一种方法,直到最后一个parent_Ln全部为空,因为我不确定我需要多少级别

感谢

1 个答案:

答案 0 :(得分:0)

您需要的长度是树的深度。 在SQL中计算它有点麻烦,因为您确实需要哈希表,或者至少需要数组。 您可以使用hash in data step or ds2访问孩子的父母。 如果您有SAS / OR,则更容易: 你可以解决shortest path并制作你的桌子 从森林的根源的路径。 对于此示例,我将使用the link Reeza provided中的数据集:

data have;
infile datalines delimiter='|';
input subject1 subject2;
datalines;
        2    |    4 
        2    |    5 
        2    |    6 
        2    |    8
        4    |    7 
        4    |    11 
        6    |    9 
        6    |    10
        6    |    12
        10  |    15 
        10  |    16 
        13  |    14 
        16  |    17
;

proc optmodel printlevel=0;
    set<num,num> REFERRALS;
    set CLIENTS = union{<u,v> in REFERRALS} {u, v};
    set ROOTS = CLIENTS diff setof{<u,v> in REFERRALS} v;
    read data have into REFERRALS=[subject1 subject2];

    /* source, sink, seq, tail, head. */
    set<num,num,num,num,num> PATHS;
    num len{ROOTS,CLIENTS} init .;
    num longest = max(of len[*]);
    solve with NETWORK / graph_direction = directed
        links     = ( include = REFERRALS )
        out       = ( sppaths = PATHS spweights = len )
        shortpath = ( source  = ROOTS  )
    ;

    num parent{ci in CLIENTS, i in 1 .. longest} init .;
    for{<u, v, i, s, t> in PATHS} 
        parent[v, len[u,v] - i + 1] = s;
    print parent;
    create data want from [client]=CLIENTS
        {i in 1 .. longest} <COL('Parent_L'||i) = parent[client,i]>;
quit;