BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Satori
Quartz | Level 8

Hi, 

 

this is my code:

%let va=id assets rev;
%let la=lid lassets lrev; %let ca=cid cassets crev;
proc sort data=dataset; by id year;
data dataset; set dataset; array va{*} &va; array la{*}; do j=1 to dim(va); la{j}=lag(va{j}); end;
data dataset; set dataset; array la{*} &la; do j=1 to dim(la); if lbvdidc ne bvdidc then la{j}=.; end;
data dataset; set dataset; array va{*} &va; array la{*} &va; array ca{*} &va; do j=1 to dim(va); ca{j} = log(va{j}/la{j}); end;

the log says:

ERROR: All variables in array list must be the same type, i.e., all numeric or character.
ERROR: All variables in array list must be the same type, i.e., all numeric or character.
ERROR: The array la has been defined with zero elements.
ERROR: Too many array subscripts specified for array la.

id is a character variable; assets and rev are numeric.

 

How do I fix this to allow for both?

 

My objective is to calculate the following: ln(X/Xt-1) for variables assets and rev. I want to do this by id.

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

My objective is to calculate the following: ln(X/Xt-1) for variables assets and rev. I want to do this by id.

So you want to do something like this?

data want;
  set have;
  by id;
  if not first.id do;
    ln_assets = log(assest/lag_assests);
    ln_rev = lag(rev/lag_rev);
  end;
  output;
  lag_assets=assests;
  lag_rev=rev;
  retain lag_: ;
run;

There is no reason to put ID into any array for that.

View solution in original post

8 REPLIES 8
Tom
Super User Tom
Super User

You cannot make an array with variables of different types.

 

Please explain what you are actually trying to do if you want help with writing code to do.  Not HOW you want to do (which was trying to use an array with mixed variable types) but the actual overall goal. 

 

Providing example input and the output desired for that input will help a lot in explaining what you are trying to do.

Satori
Quartz | Level 8
yes, you are right. I added a note with my objective at the bottom of the post
Tom
Super User Tom
Super User

My objective is to calculate the following: ln(X/Xt-1) for variables assets and rev. I want to do this by id.

So you want to do something like this?

data want;
  set have;
  by id;
  if not first.id do;
    ln_assets = log(assest/lag_assests);
    ln_rev = lag(rev/lag_rev);
  end;
  output;
  lag_assets=assests;
  lag_rev=rev;
  retain lag_: ;
run;

There is no reason to put ID into any array for that.

Satori
Quartz | Level 8
I'm confused! how is the lag calculated? lag_ ?
Tom
Super User Tom
Super User

@Satori wrote:
I'm confused! how is the lag calculated? lag_ ?

The values are assigned at the end of the step and the RETAIN statement means they are not removed when the next iteration starts. 

 

So when the step gets to the SET statement and the next observation is read the LAG_xxx variables still have the values assigned at the end of the previous observation.  

 

The IF statement means you do not use the missing values on the first observation. Nor use the bogus non missing values carried forward from the previous by group on the first observation of this by group.

 

You could do the same thing without the RETAIN by calling the LAG() function.

data want;
  set have;
  by id;
  lag_assets=lag(assests);
  lag_rev=lag(rev);
  if not first.id do;
    ln_assets = log(assest/lag_assests);
    ln_rev = lag(rev/lag_rev);
  end;
run;

Note you cannot remove the extra variables, or move the assignment statements inside the IF/THEN block, because for LAG() to work as you normally want you have to call it with every value.  It does not look backwards into some mythical database or table of values.  It just remembers the set of values you passed it by executing the function and returns the one you asked for.

Satori
Quartz | Level 8

Thanks for the explanation. I ran the code and got this error:

 

 

1127       data dataset; set dataset; by id; lag_assets=lag(assets); lag_rev=lag(rev);
1128       	if not first.id do; lna=log(assets/lag_assets); lnr=log(rev/lag_rev); end;
                                __                                                        ___
                                22                                                        161
ERROR 22-322: Syntax error, expecting one of the following: !, !!, &, *, **, +, -, /, ;, <, <=, <>, =, >, ><, >=, AND, EQ, GE, GT, IN, LE, LT, MAX, MIN, NE, NG, NL, NOTIN, OR, ^=, 
              |, ||, ~=.  

ERROR 161-185: No matching DO/SELECT statement.

 

 

 

 

Tom
Super User Tom
Super User

You need a THEN to go with the IF before the DO.

ballardw
Super User

@Satori wrote:

Hi, 

 

this is my code:

%let va=id assets rev;
%let la=lid lassets lrev; %let ca=cid cassets crev;
proc sort data=dataset; by id year;
data dataset; set dataset; array va{*} &va; array la{*}; do j=1 to dim(va); la{j}=lag(va{j}); end;
data dataset; set dataset; array la{*} &la; do j=1 to dim(la); if lbvdidc ne bvdidc then la{j}=.; end;
data dataset; set dataset; array va{*} &va; array la{*} &va; array ca{*} &va; do j=1 to dim(va); ca{j} = log(va{j}/la{j}); end;

the log says:

ERROR: All variables in array list must be the same type, i.e., all numeric or character.
ERROR: All variables in array list must be the same type, i.e., all numeric or character.
ERROR: The array la has been defined with zero elements.
ERROR: Too many array subscripts specified for array la.

id is a character variable; assets and rev are numeric.

 

How do I fix this to allow for both?

 


Simple, you don't. SAS will only allow variables of one type in an array.

 

With your stated objective of

My objective is to calculate the following: ln(X/Xt-1) for variables assets and rev. I want to do this by id.

it doesn't even make any sense to include character values as LN isn't going to do anything with any character variable except complain.  Which likely indicates you have a variable you intended or thought to be numeric that actually is not.

 

BTW use of this construct in code, while syntactically correct is a time-bomb for beginning SAS programmers:

data dataset; set dataset; 

When you have the same data set name on the DATA step as a SET, MERGE or UPDATE you completely replace the data set unless there is a syntax error. So minor runtime errors can change values, such as using Var1=<some assignment> where you mean VAR10=<some assignment>. So you have completely replaced all of the values of Var1 and would have to revert to a prior data set, or start from reading/importing the data to recover values.

The more time you use this same name approach the harder it will be to find to find where you made a mistake.

 

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

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
  • 8 replies
  • 965 views
  • 1 like
  • 3 in conversation