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;
我需要为三个变量中相同值的每个组合分配相同的 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;