首页 > 解决方案 > 创建一个比较SAS中两行的键

问题描述

我有 SAS 数据集,它有 2 列

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

标签: sqlsas

解决方案


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

示例代码

当两个变量值都不存在于前一行中时,假设组标识发生变化。

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

以下示例是非现场的,并且太长,无法在此处发布。

如何从两个变量中的任何一个中的链接关联的行创建组


问题的一般说明:

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。
  • 两个额外的哈希用于维护组映射路径。
  • 当数据可以在不引起映射的情况下传递时,则组已完全确定。
  • 最后一次通过
    • groupIds 分配给每一对
    • 数据输出到表

推荐阅读