楼主: yukai08008
1311 2

[学习分享] Apriori_V1_sas宏代码_Andy的原创帖21 [推广有奖]

  • 2关注
  • 17粉丝

讲师

2%

还不是VIP/贵宾

-

威望
0
论坛币
2176 个
通用积分
3.0600
学术水平
10 点
热心指数
7 点
信用等级
7 点
经验
5915 点
帖子
120
精华
0
在线时间
556 小时
注册时间
2012-11-28
最后登录
2022-4-11

相似文件 换一批

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

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

经管之家联合CDA

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

感谢您参与论坛问题回答

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

+2 论坛币
Apriori算法用于关联规则的分析,第一部分是寻找频繁项集(具体介绍参考Web数据挖掘第二版)。
以下用SAS宏代码实现Apriori的频繁项集寻找。
1、数据整理: 数据集ap2是整理好的业务数据集,物件(item)按c1-c6重新编号(见数据集it1)
data ap;
input id $ item $;
cards;
t1 牛肉
t1 鸡肉
t1 牛奶
t2 牛肉
t2 奶酪
t3 奶酪
t3 靴子
t4 牛肉
t4 鸡肉
t4 奶酪
t5 牛肉
t5 鸡肉
t5 衣服
t5 奶酪
t5 牛奶
t6 鸡肉
t6 衣服
t6 牛奶
t7 鸡肉
t7 牛奶
t7 衣服
;
run;
%dsort(ap out=it ,item)
data it1;
set it;
item_id+1;
vtem=1;
run;
%mer(ap,it1,item,ap1)
%sort(ap1,id item_id)
proc transpose data=ap1 out=ap2 prefix=c;
by id;
id item_id;
var vtem;
run;

2、初始化。C为候选集系列,F为达到支持度要求的频繁项集。C1,C2 单独整理,C3及之后全部由迭代部分完成。控制部分建立了一个iter表,宏会根据这个表进行迭代。
/*第一次建立C1*/
/*1获取变量列_全部为数字型*/
%let lib=WORK;
%let set=AP2;
proc sql noprint;
select num_numeric into :n1
from sashelp.vtable
where libname="&lib" and memname="&set";
quit;
/*输入C1*/
data c1;
do id=1 to &n1;
item1=cats('c',id);
output;
end;
run;
/*计算F1,使用j2的fset宏*/
%fset(1,ap2,c1,f1);
/*手动生成C2,使用c2的c2宏*/
%c2;
/*生成f2*/
%fset(2,ap2,c2,f2);
/*生成iter表*/
data iter;
length inset $ 10;
iter=3;
inset='f2';
run;
3、迭代。从第三次开始迭代,max为最大可能的频繁项,中途如果不满足迭代条件则会直接退出宏。
/*迭代步*/
%macro apro(start=3,max=10);
/*增加主控步~ iter表*/
%do iter=&start %to &max;
    proc sql noprint;
        select count(*) into :jud
    from iter
        where iter=&iter;
        quit;
        %if &jud eq 0 %then
    %do;%goto jumpout;%end;
    /*此处加入处理步*/
    /*从iter表获取迭代初始数据集*/
        data _null_;
        set iter;
        if iter eq &iter then do;
        call symput('inset',inset);
        end;
        run;
    /*迭代1-生成合并集*/
        %csetg(&iter,&inset,mset);
    %csetp(&iter,mset,&inset,%sysfunc(cats(c,&iter)));
        %fset(&iter,ap2,%sysfunc(cats(c,&iter)),%sysfunc(cats(f,&iter)));
%end;
%jumpout: ;
%mend;
%apro;

迭代表:
iter字段 本次迭代次数
inset 本轮使用的F数据集(上一轮产生)

宏:
1、c2。通过f1产生c2,2-频繁候选集通过满足支持度的1-频繁集中产生。
2、fset。根据交易数据和候选数据集生成满足支持度的频繁集。
3、csetg。根据上一轮的F集,合并产生新的候选集。
4、csetp。对新的候选集进行剪枝。

宏代码:
1、c2.
%macro c2;
/*获得C1的记录数*/
data c2;
length item1-item2 $ 8;
run;
data _null_;
if 0 then set c1 nobs=cn;
call symput('cn',cn);
run;

%do i=1 %to &cn-1;
     data lf;
         set f1;
         if _n_=&i;
         lf=item1;
         keep lf;
         run;
    %do j=&i+1 %to &cn;
     data rt;
         set f1;
         if _n_=&j;
         rt=item1;
         keep rt;
         run;
         data mer;
         length item1-item2 $ 8;
         set lf;set rt;
         item1=lf;
         item2=rt;
         keep item:;
         run;
         proc append base=c2 data=mer;
         run;
         %end;
%end;
data c2;
set c2;
if item1 ne '';
run;
%mend;

2、fset
%macro fset(iter,tset,cset,oset,sup=0.3);
/*1取出交易记录的行数*/
data _null_;
if 0 then set &tset nobs=n;
gate=ceil(n*&sup);
call symput('gate',gate);/*传递到宏变量*/
run;
/*2取出C集记录行数*/
data _null_;
if 0 then set &cset nobs=n;
call symput('cnum',n);
run;
/*3对C记录开始循环*/
%do i=1 %to &cnum;
    data vec;
        set &cset;
        if _n_=&i;/*每次取出一行记录*/
        run;
    /*提取规则*/
        data _null_;
    set vec;
        rul=catx(' and ',of item1-%sysfunc(cats(item,&iter)));
        call symput('rul',rul);/*获得规则参数*/
        run;
        data trans;
    set &tset end=last;
        if &rul then cnt+1;
        if last then do;
        call symput('cnt',cnt);
        end;
        run;
        data &cset;
        set &cset;
        if _n_=&i then cnt=symget('cnt');
        run;
%end;
    data &oset;
        set &cset;
        if cnt ge &gate ;
        run;
/*如果iter ge 3且f级中数量ge 2,那么就在iter表中注册新任务*/
        proc sql noprint;
        select count(*) into :inum
        from &oset;
        quit;
        %if &iter ge 3 and &inum ge 2 %then %do;
        data task;
        length inset $ 10;
        iter=&iter+1;
    inset="&oset";
        run;
        proc append base=iter data=task;
        run;
        %end;
%mend;


3、csetg
%macro csetg(iter,inset,outset);

%let la=%eval(&iter-1);/*获得k-1的下标*/
/*设置一个临时数据集存放新生成的记录*/
     data  tem;
         array item(*) $ item1-%sysfunc(cats(item,&iter));
         run;
/*获取输入数据集的行数*/
         data _null_;
         if 0 then set &inset nobs=n;
         call symput('rnum',n);
         run;

%do i=1 %to &rnum-1;/*从第一行开始循环*/
    data lf;
    set &inset;
    if _n_=&i;
    array lf(*) $ lf1-%sysfunc(cats(lf,&la));
        array it(*) $ item1-%sysfunc(cats(item,&la));
        do i=1 to &la;
        lf=it;
        end;
        keep lf:;
        run;
    %do j=&i+1 %to &rnum;/*匹配第二行到末尾*/
    /*获取待合并的行*/
    data rt;
        set &inset;
        if _n_=&j;
    array rt(*) $ rt1-%sysfunc(cats(rt,&la));
        array it(*) $ item1-%sysfunc(cats(item,&la));
        do i=1 to &la;
        rt=it;
        end;
        keep rt:;
        run;
    /*尝试合并唯有最后一项不同的记录*/
        data mer;
        set lf;set rt;
        array mer(*) $ item1-%sysfunc(cats(item,&iter));
        array lf(*) $ lf1-%sysfunc(cats(lf,&la));
        array rt(*) $ rt1-%sysfunc(cats(rt,&la));
        do i=1 to &la-1;/*比较前面k-2项*/
    if lf ne rt then go to jump;/*碰到有不同的就跳过*/
        mer=lf;/*否则就进行合并*/
        end;
        /*最后两项分别取两条记录的最后一项*/
        mer[&la]=lf[&la];
        mer[&iter]=rt[&la];
        jump:call symput('bt',0);/*如果前面k-2有不同的那么不会写入新的合并集*/
    if mer[&iter] ne '' then do;
        call symput('bt',1);/*如果仅有最后一项不同则准备写入*/
        end;
        keep item:;
        run;
        %if &bt %then %do;
        proc append base=tem data=mer;
        run;
        %end;
%end;
%end;
data &outset;
set tem;
if item1 ne '';
run;
%mend;

4、csetp
%macro csetp(iter,inset,chset,outset);
%let la=%eval(&iter-1);
/*获取输入数据集行数*/
data _null_;
if 0 then set &inset nobs=n ;
call symput('rnum',n);
run;
/*获取f(k-1)集*/
data chset;
set &chset;
keyw='a';
keep item: keyw;
run;
%do i=1 %to &rnum;/*从第一行开始*/
    data tem;/*获取第一行*/
        set &inset;
        if _n_=&i;
        run;
        %let kcnt=0;
        %do j=1 %to &iter;/*每次丢弃一项,形成k-1子集*/
        data tem1;
        set tem;
        drop %sysfunc(cats(item,&j));
        keep item:;
        run;
    /*重新建立k-1数组*/
        data tem2;
        set tem1;
        array cmp(*) $ cmp1-%sysfunc(cats(cmp,&la));
        array it(*) $ item:;
        keyw='a';
        do i=1 to &la;
        cmp=it;
        end;
        keep  keyw cmp:;
        run;
    /*合并C集和检验的子集,通过关键字keyw*/
        %mer(chset,tem2,keyw,chset1);
        data chset2;
        set chset1;
        array it(*) $ item1-%sysfunc(cats(item,&la));
        array cmp(*) $ cmp1-%sysfunc(cats(cmp,&la));
        lcnt=0;
        do i=1 to &la;
    if it eq cmp then lcnt+1;
        end;
        if lcnt eq &la then res=1;
        else res=0;
        run;
    /*每次搜索应当只匹配到一项*/
        proc sql noprint;
        select sum(res) into :res
        from chset2;
        quit;
    /*累加匹配次数*/
        %let kcnt=%eval(&kcnt+&res);
        %end;
        data &inset;
        set &inset;
        if _n_=&i and (&kcnt eq &iter) then chk=1;/*对循环的行标记结果*/
        run;
        %end;
        data &outset;
        set &inset;
        if chk;
        run;
%mend;
apro1.txt (6.46 KB, 需要: 1 个论坛币)





二维码

扫码加我 拉你入群

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

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

关键词:Apriori Priori PRIOR Andy SAS宏 靴子 鸡肉 牛奶 衣服

已有 1 人评分经验 收起 理由
晓七 + 50 精彩帖子

总评分: 经验 + 50   查看全部评分

沙发
yukai08008 在职认证  发表于 2016-7-31 01:10:18 |只看作者 |坛友微信交流群
以下几个简单的宏没有解释
sort:排序
mer:横向merge
dsort:去重排序

使用道具

藤椅
晓七 在职认证  发表于 2016-7-31 01:38:51 |只看作者 |坛友微信交流群
谢谢分享。

使用道具

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

本版微信群
加好友,备注cda
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-4-23 19:26