BookmarkSubscribeRSS Feed
sahoositaram555
Pyrite | Level 9

Hi everyone, I'm learning usage of arrays and with your comments i would like to take my learning to the next level. I have written a code below to check datatype of variables present in the array. but it is throwing below mentioned errors.  

 

ERROR: There were 1 unclosed %DO statements. The macro DESCRIPTIVE will not be compiled.
ERROR: A dummy macro will be compiled.

 

can anyone suggest how to solve the error and suggest if there is a way to loop over columns. i have tried %do_over but it also started throwing errors. Please guide how to move forward with the issue.

 

data dummy;
input subjid AGE SEX BMI SODIUM INFECTION;
cards;
01001 56 F 22.3 34.5 Y

01001 60 M 29.3 41.5 N

01001 35 F 26.3 22.5 Y;

01001 23 M 19.3 34.5 Y;

01001 34 F 18.3 41.5 Y;

;
run;

 

%macro descriptive(dataset,first,last,newcol );
data _null_;
set &dataset.;
array variables{*} &first. -- &last.;
array types{*} &newcol.;
%do i=1 %to 7 ;
%if %datatyp(variables) eq CHARACTER %then %do;
%put variables=;
%end;
run;
%mend descriptive;


%descriptive(dataset=dummy, first=AGE ,last=Inefection,newcol=type);

8 REPLIES 8
andreas_lds
Jade | Level 19

While learning arrays, sticking to normal, macro-free code is highly recommended. You are mixing data-step statements (array) with macro-statements, this won't work. Next step: remove all macro code, get the data-step running without it.

 

EDIT: One more thing you should consider: all variables in an array must be either numeric or alphanumeric, mixing types is not possible.

jvdl
Obsidian | Level 7

If you just want all of your character variables, then use the _CHARACTER_ keyword (it's numeric counterpart is, fairly obviously, _NUMERIC_).

 

array AllCharVars _CHARACTER_;
array AllNumVars _NUMERIC_;
DavePrinsloo
Pyrite | Level 9

When using _NUMERIC_ and _CHARACTER_ be aware that all columns defined before the array definition in a SET , MERGE, etc. are added to the array and columns defined after the array statement are not.  Try this:

data _null_
set sashelp.cars;
* This var is in the array nums ;
length num_before_array 8;
array nums _numeric_;
* This var is not the array nums;
length num_after_array 8;
if _n_=1 then do;
   do i=1 to dim(nums);
      vname = vname(nums(i));
      put vname;
   end;
end;
run;
Ksharp
Super User

For such scenario , try function VTYPE() .

%datatyp is just for marco variable.

 

data x;
 set sashelp.class;
 vtype=vtype(name);output;
 vtype=vtype(age);output;
 stop;
run;


%let x=12.2 ;
%put %datatyp(&x);

%let x=a12 ;
%put %datatyp(&x);

 

sahoositaram555
Pyrite | Level 9

Dear all,
@jvdl @andreas_lds @DavePrinsloo @Ksharp,

After following your suggestions i have arrived at a code which is below.
%macro desc();
data _null_;
set DUMMY;
/*array AGE-numeric-INFECTION;*/
array nums _numeric_;
%if _n_=1 %then %do;
%do i=1 %to dim(nums);
vname=vname(nums(i));
%put vname;
%end;

%end;
run;
%mend desc;
%desc();
In the log there is no output,no error either. Please let me know how can i get the observations printed in to the log and i can take them in to a loop to check their datatype .
KINDLY , do help with your where am i going wrong with the understanding.
Please suggest.

Tom
Super User Tom
Super User
Why do you have %DO loop in the middle of a data step? Why not just use a DO loop?
The macro processor is going to see DIM as just text, so you cannot use it as the upper bound in your %DO loop. By the time the data step starts running the macro processor has finished its work generating the code for that step.
sahoositaram555
Pyrite | Level 9
Thanks @Tom for your generous advice. I've used %do as it is inside (%macro--%mend).
Glad you said me about DIM. didn't know tha. So instead of using DIM any other function/ways can you suggest?
Tom
Super User Tom
Super User

@sahoositaram555 wrote:
Thanks @Tom for your generous advice. I've used %do as it is inside (%macro--%mend).
Glad you said me about DIM. didn't know tha. So instead of using DIM any other function/ways can you suggest?

I have no idea what number it is that you expect your macro %DO loop to loop over.  What code is it that you want the %DO loop to generate?

 

Just because you have wrapped your code into a macro so you can conditionally generate some of the statements does not mean that immediately start putting percent signs everywhere. You only use macro code when you want to use macro code. Most of the code in a macro is just going to be the regular SAS code that you want to macro to emit so that SAS can compile it and run it.  It is only for the parts of the CODE that you need the macro processor to help you generate where need to start thinking how you can program the macro logic to generate that code.

 

For you original problem here is simplistic approach you could follow.

1) Write a macro that takes as input one DATASET name and one character VARIABLE name and generates the summary you want for character variables.

2) Write a second macro that takes as input one DATASET name and one number VARIABLE name and generates the summary you want for numeric variables.

3) Write code to get a list of the datasets and variables you want to summarize into a dataset.  

4) Write code that takes that list and generates a call to one of the two macro based on the variable type.

 

Here is one way to do steps 3 and 4.  Assume the two macro are names %CHAR_SUMMARY and %NUM_SUMMARY.

proc contents data=mylib.mydataset out=contents noprint; 
run;

data _null_;
  set contents;
  if type=1 then call execute(cats('%nrstr(%num_summary)(dataset=',libname,'.',memname,',variable=',name,')'));
  else call execute(cats('%nrstr(%char_summary)(dataset=',libname,'.',memname,',variable=',name,')'));
run;

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

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