如何消除二进制指标的子集组合?

时间:2014-01-21 14:50:27

标签: sas

我有一个数据集,其中每个观察结果是二元指示变量的组合,但不一定是所有可能的组合。我想消除作为其他观察的子集的观察。举个例子,假设我有这三个观察结果:

var1 var2 var3 var4
   0    0    1    1
   1    0    0    1
   0    1    1    1

在这种情况下,我想要消除观察1,因为它是观察的一个子集3.观察2不是其他任何的子集,因此我的输出数据集应包含观察2和3。

在SAS中有一种优雅且最快速的方法吗?到目前为止,我最好的解决方案是使用带有set选项的第二个point语句通过数据集进行暴力循环,以查看当前观察是否是任何其他观察的子集,但这些数据集可能变为一旦我开始处理很多变量,我就希望能找到更好的方法。

2 个答案:

答案 0 :(得分:3)

首先,一个考虑因素:一行是否可以为所有指标设置1?您应首先检查 - 如果一行确实拥有全部1,那么它将始终是唯一的解决方案。

_POINT_效率低下,但加载到哈希表中并不是一种非常糟糕的方法。只需加载一个包含二进制指示符CATted字符串的哈希表,然后搜索该表。

首先,使用PROC SORT NODUPKEY消除完全匹配。除非你有非常多的指标变量,否则这将消除很多行。

然后,按照更“复杂”行位于顶部的顺序对其进行排序,而在底部则不那么复杂。这可能就像创建一个变量一样简单,该变量是二进制指标的总和,并按降序排序;或者如果您的数据显示,可能按特定的指标顺序排序(如果某些指标更有可能存在)。这样做的目的是减少我们搜索的次数;如果可能的匹配位于顶部,我们将更快地保持循环。

最后,使用散列迭代器按照指标变量的降序搜索列表,以查找任何匹配项。

请参阅下面的部分测试示例。我没有验证它是否消除了所有有效消除,但它消除了大约一半的行,这听起来很合理。

data have;
array vars var1-var20;
do _u = 1 to 1e4;
    do _t = 1 to dim(Vars);
        vars[_t] = round(ranuni(7),1);
    end;
    complexity = sum(of vars[*]);
    indicators = cats(of vars[*]);
    output;
end;
drop _:;
run;

proc sort nodupkey data=have;
by indicators;
run;

proc sort data=have;
by descending complexity;
run;


data want;
if _n_ = 1 then do;
  format indicators $20.;
  call missing(indicators, complexity);
  declare hash indic(dataset:'have', ordered:'d');
  indic.defineKey('indicators');
  indic.defineData('complexity','indicators');
  indic.defineDone();
  declare hiter inditer('indic');
end;

set have(drop=indicators rename=complexity=thisrow_complex); *assuming have has a variable, "indicators", like "0011001";
array vars var1-var20;
rc=inditer.first();
rowcounter=1;
do while (rc=0 and complexity ge thisrow_complex);
    do _t = 1 to dim(vars);
      if vars[_t]=1 and char(indicators,_t) ne '1' then leave;
    end;
    if _t gt dim(Vars) then delete;
    else rc=inditer.next();
    rowcounter=rowcounter+1;
end;
run;

答案 1 :(得分:1)

我很确定他们可能是一种更加以数学为导向的方式,但是现在我可以考虑这个。请谨慎行事,因为我只检查了一个小号码。测试用例。

我的伪算法: (位模式=将所有二进制变量串联成一个字符串。)

  1. 获取排序的二进制(位)模式的唯一列表 提升顺序(这是PROC SQL步骤正在做的事情
  2. 设置两个数组。 1个数组用于跟踪当前行上的变量(var1到var4),另一个数组用于跟踪滞后(var1到var4)。
  3. 如果位模式是另一个位模式的子集(滞后版本),则“点乘积矢量乘法”应该返回滞后位模式。
  4. 如果位模式= lagged_bit_pattern,则标记要排除的模式。
  5. 在上一个data step中,您将获得需要排除的位模式列表。注意:此方法不会处理重复的模式,如下所示: record1: 1 0 0 1 record2: 1 0 0 1 可以通过PROC SORT& amp; NODUPKEY

    /*sample data*/
    data sample_data;
    input id var1-var4;
    bit_pattern = compress(catx('',var1,var2,var3,var4));
    datalines;
     1 0 0 1 1
     2 1 0 0 1
     3 0 1 1 1
     4 0 0 0 1
     5 1 1 1 0
    ;
    run;
    /*in the above example, 0001 0011 need to be eliminated. These will be highlighted in the last datastep*/
    /*get unique combination of patterns in the dataset*/
    proc sql ;
    create table all_poss_patterns as 
    select 
    var1,var2, var3,var4,
     count(*) as freq
    from sample_data
    group by var1,var2, var3,var4
    order by var1,var2, var3,var4;
    quit;
    
    data patterns_to_exclude;
    set all_poss_patterns;
    by var1-var4;
    
    length lagged1-lagged4 8;
    array first_array{*} var1-var4;
    array lagged{*}lagged1-lagged4;
    
    length bit_pattern $32.;
    length lagged_bit_pattern $32.;
    bit_pattern = '';
    lagged_bit_pattern='';
    
    
    do i = 1 to dim(first_array);
    lagged{i}=lag(first_array{i});
    end;
    
    
    do i = 1 to dim(first_array);
                   bit_pattern=cats("", bit_pattern,lagged{i}*first_array{i});
                   lagged_bit_pattern=cats("",lagged_bit_pattern,lagged{i});
    end;
    if bit_pattern=lagged_bit_pattern then exclude_pattern=1;
    else exclude_pattern=0;
    /*uncomment the following two lines to just keep the patterns that need to be excluded*/
    /*if bit_pattern ne '....' and exclude_pattern=1;*/ /*note the bit_pattern ne '....' the no. of dots should equal no. of binary vars*/
    /*keep bit_pattern;*/
    run;