1
votes

I'm trying to create some classdata for a PROC TABULATE command. How can I do the following with less code? Rather than having to spell out the eventtime and node for each of the two groups, can I add text to each node, starting with L, then LL and LW etc?

proc sql; create table foo(prefflag num, eventtime num,node char(100)); quit;
proc sql;  insert into foo (prefflag, eventtime, node)                                                                                         
values (0,1, "")
values (0,2, "L")
values (0,2, "W")
values (0,3, "LL")
values (0,3, "LW")
values (0,3, "WL")
values (0,3, "WW")
values (0,4, "LLL")
values (0,4, "LLW")
values (0,4, "LWL")
values (0,4, "LWW")
values (0,4, "WLL")
values (0,4, "WLW")
values (0,4, "WWL")
values (0,4, "WWW")
values (0,5, "LLLL")
values (0,5, "LLLW")
values (0,5, "LLWL")
values (0,5, "LLWW")
values (0,5, "LWLL")
values (0,5, "LWLW")
values (0,5, "LWWL")
values (0,5, "LWWW")
values (0,5, "WLLL")
values (0,5, "WLLW")
values (0,5, "WLWL")
values (0,5, "WLWW")
values (0,5, "WWLL")
values (0,5, "WWLW")
values (0,5, "WWWL")
values (0,5, "WWWW")
values (1,1, "")
values (1,2, "L")
values (1,2, "W")
values (1,3, "LL")
values (1,3, "LW")
values (1,3, "WL")
values (1,3, "WW")
values (1,4, "LLL")
values (1,4, "LLW")
values (1,4, "LWL")
values (1,4, "LWW")
values (1,4, "WLL")
values (1,4, "WLW")
values (1,4, "WWL")
values (1,4, "WWW")
values (1,5, "LLLL")
values (1,5, "LLLW")
values (1,5, "LLWL")
values (1,5, "LLWW")
values (1,5, "LWLL")
values (1,5, "LWLW")
values (1,5, "LWWL")
values (1,5, "LWWW")
values (1,5, "WLLL")
values (1,5, "WLLW")
values (1,5, "WLWL")
values (1,5, "WLWW")
values (1,5, "WWLL")
values (1,5, "WWLW")
values (1,5, "WWWL")
values (1,5, "WWWW");                                                                                                                                                                                                         
quit; 
2
After 'values (0,5, "WWWL")' there is 'values (1,5, "WWWW")', should it be 'values (0,5, "WWWW")' instead? - Amir
Should the quotes be a mixture of single and double or should they be all the same? - Amir
I've corrected those two issues there: they were typos, yep. - user2146441

2 Answers

2
votes

Try using arrays in a DATA step. Not necessarily less code, but less repetitive.

data foo;
  format node $4.;
  array a[2] $ ('L','W');
  array b[4] $ ('LL,','LW',...);
  array c[8] $ ('LLL',...);
  array d[16] $ ('LLLL',...);

  do i=0 to 1;
    preflag=i;
    eventtime=1; node=''; output;
    eventtime=2; do j=1 to dim(a); node=a[j]; output; end;
    eventtime=3; do j=1 to dim(b); node=b[j]; output; end;
    eventtime=4; do j=1 to dim(c); node=c[j]; output; end;
    eventtime=5; do j=1 to dim(d); node=d[j]; output; end;
  end;

  drop a1-a2 b1-b4 c1-c8 d1-d16;

run;
2
votes

Here is a method you can use to generate a list with any number of eventtimes using macros:

%macro create; %macro null; %mend null;
data time1;
    length node $20;
    eventtime = 1;
    node = '';
run;

%let string = ;
%do time = 2 %to 5;
    %let lagtime = %eval(&time-1);
    %if &time = 2 %then %let string = %sysfunc(compress(i&time));
    %else %let string = %sysfunc(compress(&string||i&time));
    data time&time;
        set time&lagtime;
        eventtime = &time;
        do i&time = "L", "W";
            node = compress(&string); 
            output; 
        end;
    run;

    data time1;
        set time1 time&time;
        drop i2-i5;
    run;

%end;
%mend create;
%create;

You can change the 5's to any number for more eventtimes. The last step is to double the data set for the two different prefflags:

data final;
    set time1 (in=a) time1 (in=b);
    if a then prefflag = 0;
    if b then prefflag = 1;
run;

The above is based on the following code, which produces the same results without macros, but is a longer piece of code and only works for 5 eventtimes:

data cat3;
    length node $10;
    do prefflag = 0 to 1;
        do eventtime = 1 to 5;
            i = ''; j = ''; k = '';
            if eventtime = 1 then do;
                node = '';
                output;
            end;
            do i = "L", "W";
                if eventtime = 2 then do; 
                    node = compress(i); 
                    output; 
                end;
                do j = "L", "W";
                    if eventtime = 3 then do; 
                        node = compress(i||j); 
                        output; 
                    end;
                    do k = "L", "W";
                        if eventtime = 4 then do; 
                            node = compress(i||j||k); 
                            output; 
                        end;
                        do l = "L", "W";
                            if eventtime = 5 then do; 
                                node = compress(i||j||k||l); 
                                output; 
                            end;
                        end;
                    end;
                end;
            end;
        end;
    end;
run;