全部版块 我的主页
论坛 数据科学与人工智能 数据分析与数据科学 SAS专版
1444 8
2013-11-03
表ALL (ID、T是变量名):
IDT

1

X1

1

X2

1

X5

2

X2

2

X4

3

X2

3

X3

4

X1

4

X2

4

X4

5

X1

5

X3

6

X2

6

X3

7

X1

7

X3

8

X1

8

X2

8

X3

8

X5

9

X1

9

X2

9

X3

(原)表T1 (T1、T2是变量名):
T1T2
X1X2
X1X3
X1X5
X2X3
X2X4
X2X5

(求得)表T1  (T1_COUNT是指对应的变量T1下的值在ALL表中T变量出现的次数,如X1为6次
T1T2T1_COUNTT2_COUNT
X1X267
X1X3
X1X5
X2X3
X2X4
X2X5

(原)表T2 (T1、T2、T3是变量名):
T1T2T3
X1X2X3
X1X2X5

(求得)表T2  (T12_COUNT是指对应的变量(T1与T2)下的值在ALL表同一ID中同时出现在T变量下的次数,如X1与X2在ID分类下同时出现的次数为4
T1T2T3T1_COUNTT2_COUNTT3_COUNTT12_COUNTT13_COUNTT23_COUNT
X1X2X34
X1X2X5

类似的,有以下表格形式
T1T2T3T4T1_COUNTT2_COUNTT3_COUNTT4_COUNTT12_COUNTT13_COUNTT14_COUNT
X1X2X3X5
X1X2X5X4
T1T2T3T4T23_COUNTT24_COUNTT34_COUNTT123_COUNTT124_COUNTT234_COUNT
X1X2X3X5
X1X2X5X4

……
……

希望能够编一个宏来处理,或者有个参考也可以,谢谢~!


二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

全部回复
2013-11-4 14:46:19

data all;
   input ID  $         T $ @@;
   cards;
1 X1 1 X2 1 X5 2 X2 2 X4 3 X2 3 X3 4 X1 4 X2 4 X4 5 X1 5 X3
6 X2 6 X3 7 X1 7 X3 8 X1 8 X2 8 X3 8 X5 9 X1 9 X2 9 X3
;


*** Get list of IDs per T value;
proc sort data=all;
   by t id;
run;

data idfmt;
   set all;
   by t id;
   length label $200;
   retain fmtname "idlist" type "c" label;
   if first.t then label="*"||id;
   else label=catx("*",label,id);
   if last.t then label=cats(label,"*");
   if last.t;
   rename t=start;
   drop id;
run;

proc format cntlin=idfmt;
run;

*** Macro;
%macro test(lib=work,inds=have,dsout=wanted);
    proc sql noprint;
                 select max(compress(name," ","a")) into : varnum
                  from dictionary.columns
                  where libname=upcase("&lib") and upcase(memname)=upcase("&inds");
        quit;

        data &dsout;
            set &lib..&inds;
               
            %do i=1 %to &varnum;
                    tmp=put(t&i,$idlist.);
            T&i._count=count(tmp,"*")-1;

                %if &varnum ne 1 %then %do j=%eval(&i+1) %to &varnum;
                             t&i&j._count=0;
                             do a=1 to t&i._count;
                                    if index(put(t&j,$idlist.),catx(scan(tmp,a),"*","*")) then t&i&j._count+1;
                                 end;
                         %end;
                %end;
                drop a tmp;
        run;

%mend;

*** Test1;
data have;
   input T1  $        T2  $;
   cards;
X1        X2
X1        X3               
X1        X5               
X2        X3               
X2        X4               
X2        X5
;
%test()

*** Test2;
data have;
  input T1  $ T2  $ T3  $;
  cards;
X1        X2        X3
X1        X2        X5
;
%test()

*** Test3;
data have;
  input T1 $ T2  $ T3  $ T4  $;
  cards;
X1        X2        X3        X5                                                                               
X1        X2        X5        X4
;
%test()
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-11-4 18:43:02
pobel 发表于 2013-11-4 14:46
data all;
   input ID  $         T $ @@;
   cards;
谢谢pobel大神。我用您的代码可以完美解决之前描述的问题。想解决的问题其实是关联规则中最小置信度计算的一个步骤。  我刚开始考虑有些不足,刚刚发现当项数(即包含T字符的变量个数)大于等于4项时会比原来麻烦。我已经把问题描述修改了(见红色部分)。自己也试过多添加几个do loop来解决,但没想出当项数未知时的解决方式。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-11-7 16:25:45
调殇 发表于 2013-11-4 18:43
谢谢pobel大神。我用您的代码可以完美解决之前描述的问题。想解决的问题其实是关联规则中最小置信度计算的 ...
以下代码应该能实现所有组合,我没有做很多的测试,楼主可以试一下能不能解决问题。

data all;
   input ID  $ T $ @@;
   cards;
1 X1 1 X2 1 X5 2 X2 2 X4 3 X2 3 X3 4 X1 4 X2 4 X4 5 X1 5 X3
6 X2 6 X3 7 X1 7 X3 8 X1 8 X2 8 X3 8 X5 9 X1 9 X2 9 X3
;


*** Get list of IDs per T value;
proc sort data=all;
   by t id;
run;

data idfmt;
   set all;
   by t id;
   length label $200;
   retain fmtname "idlist" type "c" label;
   if first.t then label="*"||id;
   else label=catx("*",label,id);
   if last.t then label=cats(label,"*");
   if last.t;
   rename t=start;
   drop id;
run;

proc format cntlin=idfmt;
run;

*** Macro;
%macro test(lib=work,inds=have,dsout=wanted);
    *** Count number of T- variables;
    proc sql noprint;
             select max(compress(name," ","a")) into : varnum
              from dictionary.columns
              where libname=upcase("&lib") and upcase(memname)=upcase("&inds");
    quit;

        *** All possible combinations;
        data allgrp;
            format n 3.;
            %do i=1 %to &varnum ;
                    %do j=1 %to &i;
                            do t&j=&j to &varnum;
                        %end;
                        %let condition=1;
                        %let sub=&i;
                        %do %while(&sub ge 2);
                %let condition=&condition and t&sub>t%eval(&sub-1);
                %let sub=%eval(&sub-1);
                        %end;
                           if &condition  then do;
                                   n=n(of t1-t&varnum);
                       output;
                                        end;
                        %do j=1 %to &i;
                            end;
                        %end;
                %end;
        run;

        *** Counting;
        data _null_;
           length code code1 code2 $3000;
           set allgrp end=last;
           if _n_=1 then call execute("data &dsout; set have;");
           var=compress(cats("T",of t1-t&varnum,"_count"),".");
           array t(&varnum);
           code=cats("tmp=put(T",t1,",$idlist.);");
           if n=1 then do;
                code1=cats(var,"=count(tmp,'*')-1;");
           end;
           else do;
             code1=cats(var,"=0;");
             code2=cats("do a=1 to t",t1,"_count; if 1");
             do  i=2 to n;
                     code2= strip(code2)||" and index(put(T"||cats(t(i))||",$idlist.), catx(scan(tmp,a),'*','*'))";                        
                  end;
                  code2=strip(code2)||" then "||strip(var)||"+1; end;";
                end;

                call execute(strip(code));
                call execute(strip(code1));
                call execute(strip(code2));
                if last then call execute("drop tmp a; run;");
        run;
%mend;

*** Test;
data have;
  input T1 $ T2  $ T3  $;
  cards;
X1        X2        X3                                                                          
X1        X2        X5
X3       X4         X5
;
options nomprint;
%test(dsout=wanted1)


data have;
  input T1 $ T2  $ T3  $ T4  $ T5 $;
  cards;
X1        X2        X3        X5   X2                                                                             
X1        X2        X5        X4   X4
;
%test(dsout=wanted2)
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-11-9 17:47:49
pobel 发表于 2013-11-7 16:25
以下代码应该能实现所有组合,我没有做很多的测试,楼主可以试一下能不能解决问题。

data all;
程序巧用了format,但也留下了缺陷,字符型format长度最长为32767,应该应付不了百万级别的数据。不过还是非常感谢pobel大神,学到了很多。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2013-11-10 09:01:02
调殇 发表于 2013-11-9 17:47
程序巧用了format,但也留下了缺陷,字符型format长度最长为32767,应该应付不了百万级别的数据。不过还是 ...
如果数据量太大,这种方法确实会有局限性。用sql也许能绕开这个问题,不过应该会需要很多个sql步,也会涉及到很多次数据集连接,对于百万级数据,效率可能就是问题了。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

点击查看更多内容…
相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群