SAS - 根据更多变量的所有可能组合查找并分配 ID

SAS - Find and assign an ID base on all possible combinations of more variables

我需要为三个变量中相同值的每个组合分配相同的 ID,我真的不知道我能做些什么来发现三个变量中相同三个字母的组合(A-B-C 应该与 B-C-A 匹配) 这是我的输入数据:

data HAVE;
input ID VAR1 VAR2 VAR3 $;
DATALINES;
001 A B C
002 A C B
003 B C A
004 A B 
005 B A 
006 D E F
007 E F D
008 F E D
009 E F 
010 F E
;
RUN;

结果 ID_NEW 应该是:

data HAVE;
input ID VAR1 VAR2 VAR3 $ ID_NEW;
DATALINES;
001 A B C 1
002 A C B 1
003 B C A 1
004 A B   2
005 B A   2
006 D E F 3
007 E F D 3
008 F E D 3
009 E F   4
010 F E   4
;
RUN;

我能够通过 proc sql 发现两者的组合并使用键 t1.var1=t2.var2 和 t1.var2=t2.var1 执行左连接但是它发现了三个字母组合,我想避免连接,因为我可以有 6 种可能的组合,我觉得有一个聪明的方法,无需重复连接 6 次!也许结合使用 catt 和 scan 功能?

提前感谢您的帮助:)!

您可以使用 SORTC 函数执行此操作,该函数将字符值数组按字母顺序排序:

http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a003106052.htm

一种方法是创建一个包含按字母顺序排列的 VAR1-VAR3 值的新变量:

data want;
  length sorted_vars $ 20;
  set have;
  array vars[*] var1-var3;
  call sortc(of vars[*]);
  sorted_vars = cats(of vars[*]);
run;

以上代码未经测试,但应该非常接近。从那里,您可以对 sorted_vars 进行排序,并在每个 first.sorted_vars.

上递增 id_new 变量

ID_NEW是基于组合。每个独特的组合都可以被认为是一个集合元素。通过对数据值进行排序(将值排列转换为表示值组合的不同排列)并将它们与定界符连接成单个值(即集合元素)来获得集合元素。定界确保元素中贡献值的分离。 set元素也可以看成是hash key,于是就有了single-pass方案。

例子

perm     sort     element/key
A B C -> A B C -> A,B,C
B C A -> A B C -> A,B,C

CALL SORTC 将对变量进行排序,但您不想对实际变量进行排序,因此必须将这些值复制到将要排序的其他变量中(并从输出中删除)

hash 可以将键值与 combination_id 相关联。 combo_id 每次遇到新的键值时递增,或者当键已经存在时检索。

示例:

data HAVE;
input ID VAR1 $ VAR2 $ VAR3 $;
DATALINES;
001 A B C
002 A C B
003 B C A
004 A B .
005 B A .
006 D E F
007 E F D
008 F E D
009 E F .
010 F E .
011 C A B
012 E D F
RUN;

data want;
  if 0 then set have; * prep pdv;

  length _key 0 combo_id 8; * host variables for hash;

  if _n_ = 1 then do;
     declare hash ids();
     ids.defineKey ('_key');
     ids.defineData ('combo_id');
     ids.defineDone();
  end;

  set have;

  * copy data into variables that will be sorted;

  * combination of raw data;
  * use cats in case some of variables are numeric;
  _item1 = cats(var1);
  _item2 = cats(var2);
  _item3 = cats(var3);

  * alternative if combo_id is to be based on formatted data values;
  * use vvalue to obtained formatted representation of data values;
  * _item1 = vvalue(var1);
  * _item2 = vvalue(var2);
  * _item3 = vvalue(var3);

  array items _item1-_item3;  * arrayify the _items so they can be sorted;

  call sortc(of items(*));

  * delimit with hex 255, a character not likely to occur
  * in the data value or formatted representation;

  _key = catx('FF'x, of items(*)); 

  * retrieve or increment the combo_id;

  if ids.find() ne 0 then do;
    combo_id = ids.num_items + 1;
    ids.add();
  end;

  drop _:;
run;