Date: Thu, 5 Feb 2009 06:48:38 -0600
Reply-To: "./ ADD NAME=Data _null_;" <iebupdte@GMAIL.COM>
Sender: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From: "./ ADD NAME=Data _null_;" <iebupdte@GMAIL.COM>
Subject: Re: array label question
In-Reply-To: <30648bb30902041734w26ae3049l4c545c0e53871e68@mail.gmail.com>
Content-Type: text/plain; charset=ISO-8859-1
Ian,
Thanks for the correction. I like to think I would have figured that
out eventually, or before it was too late. Hari are you reading
this?
I was thinking more of a discussion, I don't recall using the word
challenge, but if you want to call it that, the challenge was to start
with these two pieces of data.
%let bounds = 2007:2009, 1:4, 1:3, 1:2;
%let vars = Yr--IncentiveType;
and we would also need to know the name of the input data set, so
three pieces of data.
%let data = have;
For the past little while, I have been interested in seeking solutions
to what one might call "typical macro problems" using regular SAS
code. I am not always successful.
I don't have a particular prejudice toward macro I just like to try
different approaches. Most of the macros that I see when I do code
review are completely unnecessary, as are many of the data and proc
steps in these programs.
> #iw-value=1
I am somewhat disappointed, but not surprised, that you give this
topic low IW value.
On 2/4/09, Ian Whitlock <iw1sas@gmail.com> wrote:
> Summary: Correction and response to
> Challenge - No nested DO-loops and no %Sign Language
> #iw-value=1
>
> Data_null_,
>
> First a correction to your original code.
>
> The step
>
> data transpose;
> if 0 then set names;
> array all [2007:2008, 1:4, 1:3, 1:2] _all_;
> do until(last.indiv_id) ;
> set have;
> by indiv_id;
> all{yr,qtr,channel_cd,incentive_type} = contacts;
> end;
> run;
>
> produces the wrong values since the variables in the array come
> from a SAS data set they are retained. You need
>
> call missing (of _:) ;
>
> before the DO-loop. Otherwise, I see the solution as good and
> efficient given the request.
>
> Here is code to honor your literal challenge, albeit not its intent.
>
> data yr qtr channel_cd incentive_type ;
> do x = 2007 to 2008 , 1 to 4 ;
> if x > 4 then output yr ;
> else
> do ;
> if x <= 2 then output incentive_type ;
> if x <= 3 then output channel_cd ;
> output qtr ;
> end ;
> end ;
> run ;
>
> proc sql noprint ;
> select "_" || catx ( "_", y.x, q.x, c.x, i.x )
> into :names separated by " "
> from yr y, qtr q, channel_cd c, incentive_type i
> order by 1
> ;
> quit ;
>
> data need2 (keep = indiv_id _: ) ;
> array all {2007 : 2008,1 : 4,1 : 3,1 : 2} &names ;
>
> do i = 1 by 1 until (last.indiv_id) ;
> set have ;
> by indiv_id ;
>
> all{yr,qtr,channel_cd,incentive_type} = contacts ;
> end ;
> run ;
>
> Having limits, I did not make pretty labels, but they could
> be done with your &VARS and another SELECT :INTO in my SQL
> using %SCAN. Oops, have I crossed the line between %LET
> statements and the %Sign Language?
>
> Ian Whitlock
> =============
>
> Date: Wed, 4 Feb 2009 10:07:18 -0600
> From: "./ ADD NAME=Data _null_;" <iebupdte@GMAIL.COM>
> Subject: Re: array label question
> Comments: To: Hari Nath <hari_s_nath@yahoo.com>
>
> I was thinking "How to write this without having to write the data
> step with DO YR, DO QRT etc." where the needed information was taken
> from the ARRAY specification and a list of variables or a "SAS
> Variable List".
>
>
> %let bounds = 2007:2009, 1:4, 1:3, 1:2;
> %let vars = Yr--IncentiveType;
>
>
> The following is what I came up with. I know I could do all this with
> %Sign Language but that was not my goal. My goal was to use PROCS and
> data steps and as few macro variables as possible. I got pretty close
> but &VARS keeps showing in most of the steps. We can discuss if
> anyone is interested...
>
>
> dm 'clear log; clear output;';
> data have;
> input INDIV_ID:$12. yr qtr channelCD IncentiveType CONTACTS;
> label yr='Year' qtr='Quarter' channelCd='Channel CD'
> IncentiveType='Incentive';
> cards;
> 100000100004 2007 1 1 2 1
> 100000100004 2007 1 3 2 7
> 100000100004 2008 3 1 2 1
> 100000100005 2007 1 1 2 1
> 100000100005 2007 1 3 2 7
> 100000100005 2008 2 3 2 1
> 100000100005 2008 3 3 1 1
> 100000100005 2008 3 3 2 2
> 100000100007 2007 4 1 2 2
> 100000100007 2008 3 1 2 4
> ;;;;
> run;
>
>
> %let bounds = 2007:2009, 1:4, 1:3, 1:2;
> %let vars = Yr--IncentiveType;
>
>
> proc transpose data=work.have(obs=0) out=work.vars;
> var &vars; * Expand the variable list;
> run;
> proc sql noprint;
> * Replace VARS with expanded list. While not actually necessary;
> * for this example it is more of a work practice;
> select _name_ into :vars separated by ' ' from work.vars;
> quit;
> run;
> %put NOTE: VARS=&VARS;
>
>
> data names(drop=all:);
> set vars;
> array all[&bounds];
> do _v_ = lbound(all,_n_) to hbound(all,_n_);
> output;
> end;
> run;
> proc transpose
> data = work.names
> out = work.classdata(drop=_name_ _v_)
> ;
> by _v_ notsorted;
> var _v_;
> run;
> proc summary data=work.classdata(obs=0) classdata=work.classdata nway
> missing completetypes chartype;
> class &vars;
> output out=work.frame(label="With missing values we don't want");
> run;
> proc summary data=work.frame nway;
> class &vars;
> output
> out=work.frame
> (
> label= 'Name Frame, With missing values removed'
> drop=_type_ _freq_
> )
> / levels
> ;
> run;
> data work.frame;
> set work.frame;
> array _V_[*] &vars;
> length _NAME_ $32 _LABEL_ $128;
> _name_ = catx('_',of _v_[*]);
> do _n_ = 1 to dim(_v_);
> _label_ = catx(', ',_label_,catx('=',vlabel(_v_[_n_]),_v_[_n_]));
> end;
> run;
> proc transpose data=work.frame out=names(drop=_name_);
> var _level_;
> id _name_;
> idlabel _label_;
> run;
> proc contents varnum;
> proc print;
> run;
>
>
> <SNIP remainder
> at http://listserv.uga.edu/cgi-bin/wa?A2=ind0902a&L=sas-l&D=1&P=15011>
>
|