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.
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.
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.
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 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.
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.
You need a THEN to go with the IF before the DO.
@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 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.