From: Chang Chung on
On Tue, 15 Dec 2009 11:32:31 +0100, =?iso-8859-1?b?SMOla2Fu?= Lane
<hlane(a)CLS.DK> wrote:

> Thank you all for providing nice help. It works out a lot better now
>with another change, but a problem is that sampled only is set the
>last time that the person appears, captured by last.pnr. I would have
>liked sampled to be set every time and then a record written only the
>last time.
>
> For example, current records of
>
> pnr=1,aar=2001
> pnr=1,aar=2002
> pnr=1,aar=2003
>
> should result in pnr=1,sampled2001=1,sampled2002=1,sampled2003=1
> and not as now only in pnr=1,sampled2003=1.
>
> How do I do that?
>
>
> DATA libout.pdata;
> SET cpr;
> byear=aar-alder;
> %let numyears=%eval (&slutaar-&startaar+1);
> Array sampled{&numyears} sampled&startaar - sampled&slutaar;
> %let index=aar-&startaar+1;
>sampled{&index}=1;
> DROP alder numyears;
> IF last.pnr THEN output;
> ELSE DO;
> END;
> RUN;
>
> Regards,
>
> H�kan Lane
>
>>
>>
>> -----Original Message-----
>> From: SAS(r) Discussion [mailto:SAS-L(a)LISTSERV.UGA.EDU] On Behalf Of
>> Håkan Lane
>> Sent: Monday, December 14, 2009 7:31 AM
>> To: SAS-L(a)LISTSERV.UGA.EDU
>> Subject: SAS dynamic arrays
>>
>> I would like to implement an array the size of which is not known
>> a priori. Instead of declaring an implicit value for the number of
>> elements, I wish to find this value from a variable. This can be
>> done in other languages including Fortran.
>>
>> My attempt to code this as shown below fails.
>>
>> DATA libout.pdata;
>> SET cpr;
>> byear=aar-alder;
>> numyears=&slutaar-&startaar+1;
>> Array sampled{numyears} sampled&startaar - sampled&slutaar;
>> sampled{aar}=1;
>> DROP alder numyears;
>> IF last.pnr THEN output;
>> ELSE DO;
>> END;
>> RUN;
>>
>> The idea is to replace a structure with one record every year that
>> a person was in our records with their age so an array with a 1 if
>> they were in and 0 if they weren't. The age (alder from above) is
>> represented with a birthyear. This would quite obviously save a lot
>> of redundant data. The issue is that we might run the program with
>> different start and end years. That is why it would be better for
>> them to be external constants.
>>

Hi, H�kan Lane:
This kind of data management task is sometimes known as "reshaping." Your
input data are in a "long" shape and you want it to be "wide." If your data
are not too large, this can be easily done using proc transpose as shown
below. Hope this helps a bit.
Cheers,
Chang

/* a test data shaped long */
data one;
input id year;
cards;
1 2001
1 2002
1 2003
2 2002
2 2003
;
run;

/* reshape wide with vars set to 1 */
data two;
set one;
sampled = 1;
run;
proc sort data=two;
by id year;
run;
proc transpose
data=two out=three(drop=_name_) prefix=sampled;
var sampled;
id year;
by id;
run;

/* check */
proc print data=three noobs;
run;
/* on lst
id sampled2001 sampled2002 sampled2003

1 1 1 1
2 . 1 1
*/
From: Tom Abernathy on
Replace {numyears} with {*} in your array statement.
SAS will figure out the dimension for you by counting how many
variables are referenced by the range sampled&startaar -
sampled&slutaar.
If you need it to control your program you can use DIM(sampled) to get
the number of variables in your array.

On Dec 14, 7:31 am, hl...(a)CLS.DK (HÃ¥kan Lane) wrote:
>    I would like to implement an array the size of which is not known a
> priori. Instead of declaring an implicit value for the number of
> elements, I wish to find this value from a variable. This can be done
> in other languages including Fortran.
>
>   My attempt to code this as shown below fails.
>
>   DATA libout.pdata;
>   SET cpr;
>   byear=aar-alder;
>   numyears=&slutaar-&startaar+1;
>   Array sampled{numyears} sampled&startaar - sampled&slutaar;
>   sampled{aar}=1;
>   DROP alder numyears;
>   IF last.pnr THEN output;
>   ELSE DO;
>   END;
>   RUN;
>
>   The idea is to replace a structure with one record every year that a
> person was in our records with their age so an array with a 1 if they
> were in and 0 if they weren't. The age (alder from above) is
> represented with a birthyear. This would quite obviously save a lot of
> redundant data. The issue is that we might run the program with
> different start and end years. That is why it would be better for them
> to be external constants.
>
>   Thanks in advance.
>
>   Regards,
>
>   Håkan Lane

From: =?iso-8859-1?b?SMOla2Fu?= Lane on
There seems to be an error in the code. If I quote it, I get an
error on my correspondence to id being just first in a line like that
�, and if I try to change it I don't get the desired results. Thanks.

H�kan

>
> Hi, H�kan Lane:
> This kind of data management task is sometimes known as "reshaping." Your
> input data are in a "long" shape and you want it to be "wide." If your data
> are not too large, this can be easily done using proc transpose as shown
> below. Hope this helps a bit.
> Cheers,
> Chang
>
> /* a test data shaped long */
> data one;
> input id year;
> cards;
> 1 2001
> 1 2002
> 1 2003
> 2 2002
> 2 2003
> ;
> run;
>
> /* reshape wide with vars set to 1 */
> data two;
> set one;
> sampled = 1;
> run;
> proc sort data=two;
> by id year;
> run;
> proc transpose
> data=two out=three(drop=_name_) prefix=sampled;
> var sampled;
> id year;
> by id;
> run;
>
> /* check */
> proc print data=three noobs;
> run;
> /* on lst
> id sampled2001 sampled2002 sampled2003
>
> 1 1 1 1
> 2 . 1 1
> */
>
From: Dale McLerran on
--- On Tue, 12/15/09, Håkan Lane <hlane(a)CLS.DK> wrote:

> From: Håkan Lane <hlane(a)CLS.DK>
> Subject: Re: SAS dynamic arrays
> To: SAS-L(a)LISTSERV.UGA.EDU
> Date: Tuesday, December 15, 2009, 2:32 AM
> Thank you all for providing nice
> help. It works out a lot better now
> with another change, but a problem is that sampled only is
> set the
> last time that the person appears, captured by last.pnr. I
> would have
> liked sampled to be set every time and then a record
> written only the
> last time.
>
> For example, current records of
>
> pnr=1,aar=2001
> pnr=1,aar=2002
> pnr=1,aar=2003
>
> should result in
> pnr=1,sampled2001=1,sampled2002=1,sampled2003=1
> and not as now only in pnr=1,sampled2003=1.
>
> How do I do that?
>
>
> DATA libout.pdata;
> SET cpr;
> byear=aar-alder;
> %let numyears=%eval (&slutaar-&startaar+1);
> Array sampled{&numyears} sampled&startaar -
> sampled&slutaar;
> %let index=aar-&startaar+1;
> sampled{&index}=1;
> DROP alder numyears;
> IF last.pnr THEN output;
> ELSE DO;
> END;
> RUN;
>
> Regards,
>
> H�kan Lane
>
> >
> >
> > -----Original Message-----
> > From: SAS(r) Discussion [mailto:SAS-L(a)LISTSERV.UGA.EDU]
> On Behalf Of
> > Håkan Lane
> > Sent: Monday, December 14, 2009 7:31 AM
> > To: SAS-L(a)LISTSERV.UGA.EDU
> > Subject: SAS dynamic arrays
> >
> > I would like to implement an array the size of which is not known
> > a priori. Instead of declaring an implicit value for the number of
> > elements, I wish to find this value from a variable. This can be
> > done in other languages including Fortran.
> >
> > My attempt to code this as shown below fails.
> >
> > DATA libout.pdata;
> > SET cpr;
> > byear=aar-alder;
> > numyears=&slutaar-&startaar+1;
> > Array sampled{numyears} sampled&startaar - sampled&slutaar;
> > sampled{aar}=1;
> > DROP alder numyears;
> > IF last.pnr THEN output;
> > ELSE DO;
> > END;
> > RUN;
> >
> > The idea is to replace a structure with one record every year that
> > a person was in our records with their age so an array with a 1 if
> > they were in and 0 if they weren't. The age (alder from above) is
> > represented with a birthyear. This would quite obviously save a lot
> > of redundant data. The issue is that we might run the program with
> > different start and end years. That is why it would be better for
> > them to be external constants.
> >
> > Thanks in advance.
> >
> > Regards,
> >
> > H�kan Lane
> >
>

H�kan,

Use a RETAIN statement to hold the values of sampled&startaar
through sampled&slutaar over until the last record. You will
need to initialize retained variables to zero or missing with
the first record for every pnr value. Thus, the following
code should work:


DATA libout.pdata;
retain sampled&startaar - sampled&slutaar;
SET cpr;
by pnr;
byear=aar-alder;
numyears=&slutaar-&startaar+1;
Array sampled{*} sampled&startaar - sampled&slutaar;
if first.pnr then do i=1 to numyears;
sampled{i}=0;
end;
sampled{aar}=1;
DROP alder numyears i;
IF last.pnr THEN output;
RUN;


Dale

---------------------------------------
Dale McLerran
Fred Hutchinson Cancer Research Center
mailto: dmclerra(a)NO_SPAMfhcrc.org
Ph: (206) 667-2926
Fax: (206) 667-5977
---------------------------------------