【问题标题】:Generate All Unique Permutations of an Array in SAS在 SAS 中生成数组的所有唯一排列
【发布时间】:2015-03-30 07:01:52
【问题描述】:

在 SAS 中,如果我有如下字符串或数组,

array x[4] $1 ('A' 'B' 'C' 'D');

我需要生成元素的所有“唯一”排列,如下所示,

[ABCD]
[ABC]
[BCD]
[ACD]
[ABD]
[AB]
[AC]
[AD]
[BC]
[BD]
[CD]
[A]
[B]
[C]
[D]

SAS 中是否有生成所有可能的数组组合的函数?

【问题讨论】:

  • 我认为这是组合而不是排列。
  • AB 和 BA 是不同的排列但相同的组合。
  • 被问到这是在询问代码。问我编辑的方式更容易接受。
  • 感谢大家的回复。我唯一要寻找的是生成所有可能的“独特”变体,所以不管你叫它什么组合或排列对我来说都可以。

标签: arrays sas


【解决方案1】:

假设:我相信你要找的是combinations而不是permutations,所以顺序无所谓,BA和AB是一回事。

使用call allcomb 子程序和comb 函数找出可能的组合。

在此处阅读有关allcomb 和comb 的更多信息

这里

总之——

  • call allcomb 子例程给出了n 元素中的可能组合,当它们中的r 被采用时,
  • comb 函数为您提供了当一次取出 n 元素 r 时将有多少组合。

data test(keep=my_string);
length my_string $50.;
  array a[4] $ ('A' 'B' 'C' 'D');

  n = dim(a);

   do k=1 to n;
         do j=1 to comb(n,k);
             call allcomb(j,k,of a[*]);
                 do i = 1 to k;
                    if i=1 then do; my_string="";counter=0;end;
                    counter=counter+1;
                    my_string=cat(compress(my_string),compress(a[i]));
                 if counter=k then output;

                 end;
           end;
    end;
run;

【讨论】:

  • 感谢@NEOmen。我一定会调查的。看起来这样应该可以生成我想要的。
【解决方案2】:

对此略有不同的看法是使用proc summary。

创建一个虚拟数据集。将数组的每个元素分配给一个变量,这样我们就可以将它输入proc summary:

data tmp;
  array arr[*] a b c d (1 1 1 1);
run;

运行proc summary。

proc summary data=tmp noprint missing;
  class a b c d;
  output out=combinations;
run;

您还可以使用proc summary 中的ways 或types 语句来限制您可能需要的任何组合。

现在这样做的一个有趣的副作用是您在输出数据集中也得到了_type_ 列。在上面的示例中,将分配以下值:

D = 1
C = 2
B = 4
A = 8

因此,如果输出数据集中的_type_ 值为 13,那么我们知道该行是通过组合 A、B 和 D (8 + 4 + 1) 生成的。

【讨论】:

  • +1 非常好。我已经习惯了使用nway,以至于我经常忘记班级分组。我认为您不需要var、sum、dummy 或任何选项,但只有class 和output out 的默认行为应该会提供所需的输出。
  • 谢谢罗伯特。我以前从未使用过专业摘要。我一定会试试这个。
  • @SRSwift 好点 - 我已经根据你的建议更新了代码,谢谢。
【解决方案3】:

这是一个快速脚本,可以在字符串中查找单个字符的组合。如果您愿意,这可以很容易地适应数组。这种方法不是使用组合函数和调用例程(all*、lex*、ran*),而是通过使用整数的二进制表示来创建排列,直到2**len。我更喜欢这种方法,因为我认为它展示了正在发生的事情,更加透明并且不会改变数组分配的顺序。

data have;
    str = "123456"; output;
    str = "ABCD"; output;
run;
data want;
    set have;
    length comb $20.;
    len = length(str);
    /* Loop through all possible permutations */
    do _i = 0 to 2**len - 1;
        /* Store the current iteration number in binary */
        _bin = putn(_i, "binary" || put(len, best.) || ".");
        /* Initialise an empty output variable */
        comb = "";
        /* Loop through each value in the input string */
        do _k = 1 to len;
            /* Check if the kth digit of the binary representation is 1 */
            /* And if so add the kth input character to the output */
            if substr(_bin, _k, 1) = "1" then 
                comb = cats(comb,  substr(str, _k, 1));
        end;
        output;
    end;
    /* Clean up temporary variables, commented so you can see what's happening */
/*  drop _:; */
run;

如果您确实想要排列,那么similar approach 可以使用数字的因子表示。但是,我建议您改用组合函数,因为转换会涉及更多。不过,这可能是一个很好的学习编码练习。


如果 SAS 有一个通过布尔模式减少字符串的功能会很棒,但它可能不会有太多用处。

bsubstr("ABCD", "1010") --> "AC"
bsubstr("ABCD", "1110") --> "ABC"
bsubstr("ABCD", "0001") --> "D"

【讨论】:

  • 感谢@SRSwift。这是最不同的做法。甚至没有人向我建议过这个,但它很有意义并且看起来很有趣,我也会尝试一下。
【解决方案4】:

SAS 具有计算组合和排列的内置函数,allcomb 和 allperm。

ALLCOMB 函数的 SAS 文档:http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a003112305.htm

【讨论】:

  • 感谢 Chris,我查看了 allcomb 函数,但无法生成数组元素的唯一变体。
猜你喜欢
  • 1970-01-01
  • 2012-03-14
  • 2012-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-10
  • 1970-01-01
相关资源
最近更新 更多