【问题标题】:SAS - Find and assign an ID base on all possible combinations of more variablesSAS - 根据更多变量的所有可能组合查找并分配 ID
【发布时间】:2019-02-22 10:59:57
【问题描述】:

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

提前感谢您的帮助:)!

【问题讨论】:

    标签: sas combinations uniqueidentifier scanning


    【解决方案1】:

    ID_NEW 基于组合。每个独特的组合都可以被认为是一个集合元素。集合元素是通过对数据值进行排序(将值排列转换为表示值组合的不同排列)并将它们与分隔符连接成单个值(即集合元素)来获得的。定界确保元素中贡献值的分离。一个集合元素也可以被认为是一个散列键,单程解决方案就应运而生了。

    例子

    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 可以将键值与组合 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 $100 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;
    

    【讨论】:

      【解决方案2】:

      您将能够使用 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,这有点令人困惑,但我也这样做了(当然你的方法更好!)。我只添加一个事实,即最好按降序排序,以免连接缺失值!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多