If I have an array testarray(2,4,6,8); I can use dim(testarray,i) to get the dimension of each index but how do I get the total number of dimensions? (in this case I want to return a 4).
I see ndims exits for other sas products but not for base sas. currently I loop i until I get a missing value from dim(testarray,i) but that feels rather inelegant.
Thanks
Macros are not really called "in a data step". The macro processor runs first and then the data step compiler interprets the resulting code.
As I said if the macro only generates statements that can be embedded in a data step then just add a parameter to the macro so that the person (or macro) that is generating the data step can pass in the number.
data want;
array myarray [3,4,5] _temporary_;
%mymacro(name=myarray,ndim=3);
run;
You could make it easier on the coder by just passing in the same information they need to code to make the array and have the macro do the counting for them.
data want;
array myarray [3,4,5] _temporary_;
%mymacro(array_definition=myarray[3,4,5] );
run;
Is this just a theoretical question? The person writing the data step needs to have defined the array, so they already know how many dimensions it has. The DIM() function is useful because you can define an array without knowing the number of elements. For example when using a variable list.
array _num _numeric_;
But you cannot define an array with more than one dimensions without actually specifying the dimensions.
No, its not theoretical. I have to write a macro that automates many different scripts that each use a lot of arrays of different sizes, usually between 2 and 10 different dimensions. So I need to be able to get the number of dimensions for my macro.
This is what I currently have hacked together and it works, but it is ugly and inefficient:
retain ndims 0; flag = 0; do while (flag = 0); b = ndims + 1; if missing(dim(Harray,b)) then flag = 1; else ndims = b; end; put ndims=;
Macros are not really called "in a data step". The macro processor runs first and then the data step compiler interprets the resulting code.
As I said if the macro only generates statements that can be embedded in a data step then just add a parameter to the macro so that the person (or macro) that is generating the data step can pass in the number.
data want;
array myarray [3,4,5] _temporary_;
%mymacro(name=myarray,ndim=3);
run;
You could make it easier on the coder by just passing in the same information they need to code to make the array and have the macro do the counting for them.
data want;
array myarray [3,4,5] _temporary_;
%mymacro(array_definition=myarray[3,4,5] );
run;
If you want a cleaner version of that hack:
if _n_=1 then do while(not missing(dim(harray,ndims+1))); ndims+1; end;
But it will still generate the nasty notes in the log.
NOTE: Invalid argument to function DIM at line 243 column 39. ndims=2 ndims=2 _ERROR_=1 _N_=1 NOTE: Mathematical operations could not be performed at the following places. The results of the operations have been set to missing values. Each place is given by: (Number of times) at (Line):(Column). 1 at 243:39
I don't know if it's more efficient, but it's definitely less ugly:
do ndim=0 by 1 while (dim(harray,ndim+1)^=.);
end;
put ndim=;
To avoid "the nasty notes in the log" with your algorithm, you could use something like this:
_t=n(of harray[*])+nmiss(of harray[*]);
do ndim=1 by 1 until(_t=1);
_t=_t/dim(harray,ndim);
end;
Obviously, the initialization of _t assumes a numeric array. For a character array (in the absence of a character analog of the N function) you could use something like
_t=countw(catx('~',of harray[*]),'~')+cmiss(of harray[*]);
or, if the defined length of the character variables is known (e.g., stored in a variable len)
_t=lengthc(cat(of harray[*]))/len;
OK that is super clever. Best solution to my problem thank you.
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!
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.