BookmarkSubscribeRSS Feed
reone
Calcite | Level 5
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
18 REPLIES 18
Cynthia_sas
SAS Super FREQ
Hi:
This is a very good intro on how ARRAY processing works with SAS:
http://support.sas.com/rnd/papers/sgf07/arrays1780.pdf

cynthia
reone
Calcite | Level 5
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!
art297
Opal | Level 21
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
CurtisMack
Fluorite | Level 6
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
reone
Calcite | Level 5
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
Robert_Bardos
Fluorite | Level 6
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
reone
Calcite | Level 5
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
Robert_Bardos
Fluorite | Level 6
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
reone
Calcite | Level 5
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!
Robert_Bardos
Fluorite | Level 6
Did you see the keep= option that I added by modifying my original post? Look for "important addition" and compare the code.
Peter_C
Rhodochrosite | Level 12
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
Peter_C
Rhodochrosite | Level 12
>
> 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
Peter_C
Rhodochrosite | Level 12
>
> 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
Robert_Bardos
Fluorite | Level 6
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

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 18 replies
  • 4591 views
  • 0 likes
  • 7 in conversation