楼主: 调殇
1495 8

遇到的问题需要宏、hash、sql方面的高手帮忙,谢谢 [推广有奖]

  • 9关注
  • 1粉丝

讲师

2%

还不是VIP/贵宾

-

威望
0
论坛币
155 个
通用积分
2.0000
学术水平
2 点
热心指数
0 点
信用等级
0 点
经验
11367 点
帖子
189
精华
0
在线时间
581 小时
注册时间
2010-4-20
最后登录
2020-11-23

楼主
调殇 发表于 2013-11-3 21:06:31 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
表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

……
……

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


二维码

扫码加我 拉你入群

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

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

关键词:HASH sql Has Count 表格形式

回帖推荐

pobel 发表于8楼  查看完整内容

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 ; %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 ...

pobel 发表于4楼  查看完整内容

以下代码应该能实现所有组合,我没有做很多的测试,楼主可以试一下能不能解决问题。 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; retai ...
已有 1 人评分经验 学术水平 收起 理由
Imasasor + 20 + 2 补偿

总评分: 经验 + 20  学术水平 + 2   查看全部评分

有道无术,术尚可进;有术无道,止于术也。

沙发
pobel 在职认证  发表于 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()
已有 3 人评分经验 论坛币 学术水平 热心指数 信用等级 收起 理由
Eternal0601 + 5 + 5 + 5 精彩帖子
调殇 + 1 + 1 + 1 谢谢pobel大神,每次看您的代码都有所收获
webgu + 100 + 100 + 3 + 3 + 3 不敢直视

总评分: 经验 + 100  论坛币 + 100  学术水平 + 9  热心指数 + 9  信用等级 + 9   查看全部评分

和谐拯救危机

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

板凳
pobel 在职认证  发表于 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)
已有 2 人评分学术水平 热心指数 信用等级 收起 理由
Eternal0601 + 5 + 5 + 5 膜拜。。。
调殇 + 1 + 1 + 1 谢谢pobel大神,可以解决目前的问题了。程序.

总评分: 学术水平 + 6  热心指数 + 6  信用等级 + 6   查看全部评分

和谐拯救危机

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

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

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

7
调殇 发表于 2013-11-10 10:30:53
pobel 发表于 2013-11-10 09:01
如果数据量太大,这种方法确实会有局限性。用sql也许能绕开这个问题,不过应该会需要很多个sql步,也会涉 ...
恩,很感谢pobel大神的解答。解决方法可能也需要偶尔的灵光一闪
有道无术,术尚可进;有术无道,止于术也。

8
pobel 在职认证  发表于 2013-11-11 10:33:21
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
;

%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 of T- variable;
        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;

        *** Values of T- variables;
        data _null_;
             set allgrp end=last;
                 by n;
                 array t(&varnum);
                 length varlist $40 code $1000;
                 do i=1 to n;
                    varlist=catx(",",varlist,"T"||cats(t(i)));
                 end;
                 if _N_=1 then code="Proc sql;";
                 if first.n then code=cats(code,"Create table all_",n)
                                      ||" as select distinct * from (select distinct "||cats(varlist)
                                  ||" from &lib..&inds";
             else code=" Union select distinct "||cats(varlist)||" from &lib..&inds";
                 if last.n then do;
                    code=cats(code,");");
                        end;
                 if last then code=cats(code,"quit;");
                 call execute(strip(code));
        run;

        *** Count number of IDs;
   %do i=1 %to &varnum;
       data _null_;
               set all_&i end=last;
                   length value varlist $40 code $1000;
                   array T(&i);
                   n=0;
                   do a=1 to &i;
                      value=catx(",",value,quote(strip(T(a))));
                          if index(varlist,strip(T(a)))=0 then do; n+1; end;
                          varlist=catx("*",varlist,T(a));
                   end;
                   if _n_=1 then code="Proc sql; Create table Fmt_&i as "
                              ||"select distinct "||quote(strip(varlist))|| " as start,id "
                              ||" from all where T in ("||cats(value)||") group by id having(count(*))="||cats(n);
                   else code=" union select distinct "||quote(strip(varlist))|| " as start,id "
                              ||" from all where T in ("||cats(value)||") group by id having(count(*))="||cats(n);
                   if last then code=cats(code,";quit;");
                   call execute(strip(code));
            run;
   %end;

   *** Format;
   data fmt_all;
      length start $80;
      set  %do i=1 %to &varnum;
               fmt_&i
                   %end;
          ;
   run;
      
        proc sql;
           create table fmtin as
              select distinct "I" as type, "idnum" as fmtname, start,count(distinct id) as label
                    from fmt_all
                        group by start
                union select distinct "I" as type,"idnum" as fmtname, "other" as start,0 as label
                  from fmt_all;
        quit;

        proc format cntlin=fmtin;
        run;

        *** Input;
        data _null_;
             set allgrp end=last;
                 var=compress(cats("T",of t1-t&varnum,"_count"),".");
                 length value $200 code $1000;
                   array T(&varnum);
                   value="catx('*'";
                   do a=1 to n;               
                          value=strip(value)||",T"||cats(T(a));
                   end;
                   value=strip(value)||")";

                 code=cats(var,"=input(",value,",idnum.);");
                 if _n_=1 then call execute("data &dsout; set &lib..&inds; ");
                 call execute(strip(code));
                 if last then call execute("run;");
        run;

        *** Drop temparary table;
        proc sql;
           %do i=1 %to &varnum;
             drop table all_&i;
                 drop table fmt_&i;
           %end;
           drop table allgrp;
           drop table fmtin;
           drop table fmt_all;
        quit;
%mend;

options nomprint;
*** Test1;
data have;
  input T1 $ ;
  cards;
X1  
X4  
;
%test()

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


*** Test3;
data have;
  input T1 $ T2  $ T3  $ T4  $ T5 $;
  cards;
X1        X2        X3        X5   X2                                                                             
X1        X2        X5        X4   X4
;
%test()
已有 1 人评分学术水平 热心指数 信用等级 收起 理由
调殇 + 1 + 1 + 1 膜拜~

总评分: 学术水平 + 1  热心指数 + 1  信用等级 + 1   查看全部评分

和谐拯救危机

9
调殇 发表于 2013-11-13 10:04:06
pobel 发表于 2013-11-11 10:33
data all;
   input ID  $         T $ @@;
   cards;
谢谢大神的指点,这两天比较忙。代码运行无误,解决了format的限制,太感谢了
有道无术,术尚可进;有术无道,止于术也。

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2025-12-31 23:22