创建比较SAS中两行的密钥

时间:2018-10-03 10:34:05

标签: sql sas

我有2列的SAS数据集

Var1  Var2
A      B
B      C
C      D
D      E
F      G
H      F

我可以为上述行创建相同的唯一键吗?我想要的最终输出是

Var1  Var2  Key
A      B     1
B      C     1
C      D     1
D      E     1
F      G     2
H      F     2

2 个答案:

答案 0 :(得分:2)

基于行到行链接分配组标识符的一般问题可能非常丰富且困难。但是,对于顺序情况,解决方案还不错。

示例代码

假定上一行中两个变量值都不存在时,组标识也会更改。

data have;input
Var1 $  Var2 $;datalines;
A      B
B      C
C      D
D      E
F      G
H      F
run;

data want;
  set have;
  group_id + ( var1 ne lag(var2) AND var2 ne lag(var1) );
run;

复杂的情况

@Vivek Gupta在评论中表示

  

数据集中的行是随机排列的

考虑带有项X和Y的任意行p和q。组是由链接创建的,其条件是:

   p.X = q.X
OR p.X = q.Y
OR p.y = q.x
OR p.y = q.y

基于散列的求解器将首先从数据扫描中填充组。使用哈希查找重复扫描数据会将项目迁移到较低的组中(从而扩大了组),直到扫描没有迁移为止。

data pairs;
  id + 1;
  input item1 $ item2 $ ;
cards;
A B
C D
D E
B C
H F
X Y
F G
run;

data _null_ ;
  length item $8 group 8;
  retain item '' group .;

  if 0 then set pairs;

  declare hash pairs();
  pairs.defineKey('item1', 'item2');
  pairs.defineDone();

  declare hash map(ordered:'A');
  map.definekey ('item');
  map.definedata ('item', 'group');
  map.definedone();

  _groupId = 0;
  noMappings = 0;

  nPass = 0;

  do until (end);
    set pairs end=end;

    pairs.replace();

    found1 = map.find(key:item1) eq 0; item1g = group;
    found2 = map.find(key:item2) eq 0; item2g = group;

    put item1= item2= found1= found2= item1g= item2=;

    select;
      when (    found1 and not found2) map.add(key:item2,data:item2,data:item1g);
      when (not found1 and     found2) map.add(key:item1,data:item1,data:item2g);
      when (not found1 and not found2) do;
                                       _groupId + 1;
                                       map.add(key:item1,data:item1,data:_groupId);
                                       map.add(key:item2,data:item2,data:_groupId);
                                       end;
      otherwise
      ;
    end;
  end;

  declare hiter data('pairs');

  do iteration = 1 to 1000 until (discrete);

  put iteration=;

    discrete = 1;
    do index = 1 by 1 while (data.next() = 0);

      found1 = map.find(key:item1) eq 0; item1g = group;
      found2 = map.find(key:item2) eq 0; item2g = group;

      put index= item1= item2= item1g= item2g=;

      if (item1g < item2g) then do; map.replace(key:item2,data:item2,data:item1g); discrete=0; end;
      if (item2g < item1g) then do; map.replace(key:item1,data:item1,data:item2g); discrete=0; end;
    end;
  end;

  if discrete then put 'NOTE: discrete groups at' iteration=; else put 'NOTE: Groups not discrete after ' iteration=;

  map.output(dataset:'map');
run;

复杂案例#2

组是通过条件为

的链接创建的
   p.X = q.X
OR p.y = q.y

以下示例不在现场,而且时间太长,无法在此处发布。

How to create groups from rows associated by linkages in either of two variables


一般问题说明:

Given: P = p{i} = (p{i,1),p{i,2}), a set of pairs (key1, key2).

Find: The distinct groups, G = g{x}, of P,
      such that each pair p in a group g has this property:

      key1 matches key1 of any other pair in g.
      -or-
      key2 matches key2 of any other pair in g.

简而言之,示例显示

  • 使用哈希的迭代方式。
  • 两个散列保持分配给每个键值的groupId。
  • 另外两个哈希值用于维护组映射路径。
  • 如果可以在不引起映射的情况下传递数据,则组 已经完全确定。
  • 完成最后一遍
    • groupId被分配给每对
    • 数据输出到表

答案 1 :(得分:1)

由于您尚未描述任何逻辑,因此对于下面的查询示例输出而言,它可以正常工作

- 1