BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Crysis85
Obsidian | Level 7

Hello,

basically I'm writing a data step that for each ID writes in a new variable all the variables that are changed from the previous day

I'm thinking something like this:

 

PROC SORT DATA=ccr_report_power_hist OUT=hist;
	BY ID_ANAG DESCENDING valdate;
run;

DATA hist;
	SET hist;
	BY ID_ANAG;
	IF _n_ 	EQ 1 THEN;
		DO;
			current_line = -1;
			RETAIN current_line;
		END;
	IF first.id_anag AND last.id_anag EQ 0 THEN 
		DO;
			first_date = valdate;
			ARRAY current_values[*] _CHARACTER_;
			current_line = _n_;
		END;
	IF _n_ = current_line + 1 THEN
		DO;
			first_date = valdate;
			ARRAY temp_values[*] _CHARACTER_;
			DO i=1 TO DIM(temp_values);
				same_values = '';
				IF current_value[i] EQ temp_value[i] THEN
				DO;
					same_values = CATS(same_values, VNAME(current_value[i]));
				END;
			END;
		END;	
run;

I think I'm misunderstanding how arrays are used in sas. I get the "Undeclared array referenced" for both the arrays, but I'm quite sure that the first IF is entered at least once.

1 ACCEPTED SOLUTION

Accepted Solutions
Kurt_Bremser
Super User

RETAIN and array declaration should never be written inside conditional blocks. This is misleading, as retain and array are acted upon during data step compilation, not data step execution. Therefore what you write is misleading.

This is also the reason you declare two arrays containing the same variables (and values). One would suffice.

IF current_value[i] EQ temp_value[i]

will always be true, as you just reference the same datastep variable.

 

BTW, your same_values would end up containing only the last different value, since you set it to empty within the do loop.

 

What you probably wanted was

data hist;
set hist;
by id_anag;
array temp {*} _character_;
length same_values $500; * put sufficient length here;
same_values = '';
do i = 1 to dim(temp);
  if temp{i} eq lag(temp{i}) then same_values = cats(trim(same_values),vname(temp{i}));
end;
if first.id_anag then same_values = '';
run;

 

 

View solution in original post

6 REPLIES 6
Crysis85
Obsidian | Level 7

forgot to retain current_line. Wasn't the problem tho. edited the OP

Kurt_Bremser
Super User

RETAIN and array declaration should never be written inside conditional blocks. This is misleading, as retain and array are acted upon during data step compilation, not data step execution. Therefore what you write is misleading.

This is also the reason you declare two arrays containing the same variables (and values). One would suffice.

IF current_value[i] EQ temp_value[i]

will always be true, as you just reference the same datastep variable.

 

BTW, your same_values would end up containing only the last different value, since you set it to empty within the do loop.

 

What you probably wanted was

data hist;
set hist;
by id_anag;
array temp {*} _character_;
length same_values $500; * put sufficient length here;
same_values = '';
do i = 1 to dim(temp);
  if temp{i} eq lag(temp{i}) then same_values = cats(trim(same_values),vname(temp{i}));
end;
if first.id_anag then same_values = '';
run;

 

 

Crysis85
Obsidian | Level 7

Thanks your help was very instructive, I find the workings of arrays in SAS a little confusing.

Forgot the existence of LAG() very useful.

I have but one question. You put

if first.id_anag then same_values = '';

at the end so that is it's the first row on a block it is overwrited, isn't possible to encase the whole do loop in an if-then and avoid to execute it when it's the first row in a block? 

 

 

Kurt_Bremser
Super User

That is done because of the lag() function. This function fills its FIFO queue only when called, so it is usually a bad idea to put it inside a conditional block. Using it in the if condition, OTOH, makes sure that it is called exactly once per datastep iteration and therefore always holds the value from the previous observation, and not one before that.

So instead of creating same_values conditionally, I instead cleaned it up afterwards in case a new group starts.

Crysis85
Obsidian | Level 7

Very clear. Thanks.

Astounding
PROC Star

There can be many additional issues once this one is cleared up, but this error message has an easy solution.

 

The array names and array references use different names.  You added an "s" at the end of the array names, but left out the "s" later on when referring to array elements.

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 6 replies
  • 1449 views
  • 2 likes
  • 3 in conversation