DATA Step, Macro, Functions and more

Retain Array

Reply
Contributor
Posts: 22

Retain Array

Hi to all,
I need to save two observation in two array. For example i have this data set (Information):

a1 a2 a3
1 2 3
1500 3400 780

I try with this code:

data example;

retain b1-b3 1;
set information (obs=1);
array b b1-b2 _Numeric_;

set information ( firstobs=2
obs=2);

array c _Numeric_;
run;


The SAS log shows that is all correct but the problem is that array b and array c have the same value : 1500 3400 780

I would like to have : array b has this: 1 2 3
array c has this:1500 3400 780

Where is it the error? Message was edited by: reone
SAS Super FREQ
Posts: 8,745

Re: Retain Array

Hi:
This is a very good intro on how ARRAY processing works with SAS:
http://support.sas.com/rnd/papers/sgf07/arrays1780.pdf

cynthia
Contributor
Posts: 22

Re: Retain Array

Thanks Cynthia,
I have read the paper suggested from you, but I can't find the solution for my problem.
Have you some other solution?

Thanks!
PROC Star
Posts: 7,366

Re: Retain Array

What are you trying to accomplish? Do you just want a SAS file that has the first record as variable names and the second as the data?

Art
Frequent Contributor
Posts: 102

Re: Retain Array

I agree with Art's question about what exactly you are trying to accomplish.
That said, I think your problem stems from not understanding that arrays point to a set variables, and that occurs at compile time. They cannot be changed between steps like you apear to be trying. Here is a simple solution to the problem as presented, but I suspect the example is so simplified that this might not work for you.

data information;
input a1 a2 a3;
DATALINES;
1 2 3
1500 3400 780
;
run;

data example(drop = a1-a3);
array a a1-a3;
array b b1-b3;
array c c1-c3;
retain b c;
set information;
if _n_ = 1 then do;
do over a;
b = a;
end;
end;
if _n_ = 2 then do;
do over a;
c = a;
end;
output;
end;
run;

Curtis I made a small but important wording change


Message was edited by: Curtis Mack
Contributor
Posts: 22

Re: Retain Array

Thanks for the answers!

sorry if I was not clear, I repeat my problem:

I Have this data set (TABLE) INFORMATION:

_N_ a1 a2 a3
1 1 2 3
2 12 14 15

where _N_ : is number of observation
a1 a2 a3 : are the fields

and in this Data Set I would like to have two array:
array b: 1 2 3
array c: 12 14 15

Kurtis, I Have followed your solution (with DO OVER), but it not works the retain:

data example;
array a a1-a3 _NUMERIC_;
array b b1-b3 _NUMERIC_;
array c c1-c3 _NUMERIC_;

retain b;
retain c;

set information;
if _N_ = 1 then do;
do over a ;
b=a;
end;
end;

if _N_ = 2 then do;
do over a ;
c=a;
end;
end;

do over b ;
put b;
end;

do over c;
put c;
end;

run;

The program running, but the retain it doesn't work. Moreover I can't access directly
to variable b(2) or c(3);

Have you an other solution? Message was edited by: reone
Frequent Contributor
Posts: 106

Re: Retain Array

reone,

I agree with Art and think it would be best to describe what you actually want to do. The bigger picture that is. Creating these arrays seems to be a small part of the actual problem only. While it might be possible to do what you want, it most certainly is not the best way to deal with the task at hand.

Robert
Contributor
Posts: 22

Re: Retain Array

Hi Robert,

The problem is that I need to compare every record with subsequent record.
I have this data set:

_N_ Mounth Cod
1 1 8374
2 1 5647
3 2 8374
4 3 8375
5 3 654
6 3 328
..
167 12 8374

I need to know for every COD, if this COD is in the subsequent months;
I have thought to use the array;
To do that, I use the proc transpose and in this new data set i have two observation; in the first I have the mounth and in the second i have the code.

With these array I can compare the element with the successive elements;

Thanks

Message was edited by: reone Message was edited by: reone
Frequent Contributor
Posts: 106

Re: Retain Array

One technique that I have seen reads the input dataset twice applying some kind of "firstobs based lookahead"
[pre]
data _null_ ;
set sashelp.class ;
set sashelp.class (firstobs=2 keep=name sex
rename=(name=next_name sex=next_sex)) ;
if sex=next_sex then put name 'and ' next_name 'same sex' ;
else put name 'and ' next_name 'different sex' ;
run ;
[/pre]
The downside of this is that the datastep stops as soon as the last observation of the second set statement is read. A crude circumvention to this problem might be:
[pre]
data _null_ ;
set sashelp.class ;
if not end_ds2 then
set sashelp.class (firstobs=2 keep=name sex
rename=(name=next_name sex=next_sex)) end=end_ds2 ;
if sex=next_sex then put name 'and ' next_name 'same sex' ;
else put name 'and ' next_name 'different sex' ;
run ;
[/pre]
Here you will have the values of the last observation from the second set statement carried forward by means of the retain mechanism. Bottom line: works but special care has to be taken for the last observation.

Important addition: forgot to add the keep= option to the second set statement. Failing to do so causes all other variables' values to be overwritten!


Message was edited by: Robert.Bardos
Contributor
Posts: 22

Re: Retain Array

Thanks for the answer,
I have tried your code and it works!

but I have the problem that firstobs change and it isn't fix.
firstobs has this value _N_ + 1

I have modified the firstobs in your code:

data _null_ ;
set sashelp.class ;
num = _N_+ 1;
if not end_ds2 then
set sashelp.class (firstobs=num
rename=(name=next_name sex=next_sex)) end=end_ds2 ;
if sex=next_sex then put name 'and ' next_name 'same sex' ;
else put name 'and ' next_name 'different sex' ;
run ;

but it doesn't work!
Frequent Contributor
Posts: 106

Re: Retain Array

Did you see the keep= option that I added by modifying my original post? Look for "important addition" and compare the code.
Valued Guide
Posts: 2,175

Re: Retain Array

have you looked at documentation for firstobs= ?
When you do (or re-read) you will find that unlike "POINT=" the value for "FIRSTOBS=" must be provided as a constant (it is really quite logical when you think about it)
It is pointless in this situation (pardon pun)
Comparing "this" with "next" is just the same as "this" with "previous", apart from a matter of timing. It's not forecasting.
Why not do it the easy way
dif1 = ( this_col = lag( this_col) ) ;
dif2 = ( col2 = lag( col2) ) ;

provides a simple model
Valued Guide
Posts: 2,175

Re: Retain Array

>
> The problem is that I need to compare every record
> with subsequent record.

you need to have data from more than one observation available at a time

In these problem situations, I try hard to avoid making things too complicated, and sometimes using arrays makes things complicated. For example to compare every variable in the observation with every variable on the previous observation is impossible with an array when you have both numeric and character variables, and work-arounds with more arrays is completely unneccessary when lag() provides the information from the previous row (but needs columns named see call vnext() if that is an issue).
To compare a set of variables on row N with the same set of variables on other rows could be done with something like[pre]data output_data_set ;
%let input_data_set = sashelp.class ; * or your.data_whatever ;
%let list_columns = age height weight ; * list columns to be checked ;
%let num_cols = 3 ; * enter correct number or derive count from the list ;
if 0 then set &input_data_set ; * to load data attributes befre array statements;
array check(*) &list_columns ;* MUST have all the same data type ;
array x_ref(&num_cols) %*need to add $length for character columns; _temporary_ ;
primary_data_row = 19 ; * the row compare with other rows ;
if _N_ = 1 then do;
set &input_data_set point= primary_data_row ;
do _i_ = 1 to &num_cols ;
x_ref(_i_) = check(_i_) ;
* collecting the x_ref columns to check later ;
end ;
end ;
set &input_data_set ;
diffs = 0 ;
do _i_ = 1 to &num_cols ;
if check(_i_) ne x_ref(_i_) then do;
diffs +1 ;
* do anything appropriate to the _i_-th column of check array ;
end ;
end ;
if diffs then do; * whatever required when the compared columns have at least one difference;
end ;
run ; [/pre]

So, that is a simple demo which works as I expect - remember your problem may be different

luck
peterC
Valued Guide
Posts: 2,175

Re: Retain Array

>
> The problem is that I need to compare every record
> with subsequent record.

is this "half" a cartesian join ?

sounds like sql might offer simpler compare than a data step
Frequent Contributor
Posts: 106

Re: Retain Array

Peter is right.

reone,

Do you want to compare the observations with all subsequent observations?
Or do you want to compare each observation with the immediately following observation only? (That was how I understood your problem, the ongoing discussion however seems to prove me wrong).

Thanks for clarifying
Robert
Ask a Question
Discussion stats
  • 18 replies
  • 378 views
  • 0 likes
  • 7 in conversation