0
votes

New SAS user.

I'm learning to use/write macros right now. I'm trying to loop through the variable ZONE in a data set "zonelist", as well as count the number of observations in the data set. Here's my code:

data _null_;
    set zonelist;
    call symput ('zone'||_n_, zone);
    call symput ('numzones', _n_);
    run;

I expected this to create the variables 'zone1', 'zone2' etc to call them in a do loop. This is a reasonable way to do this, right? Anyway, SAS seems to be adding whitespace to my variable names. I get this error when I run it:

ERROR: Symbolic variable name ZONE           1 must contain only
letters, digits, and underscores. NOTE: Invalid argument to function
SYMPUT('zone        '[12 of 16 characters shown],'100         '[12 of
16 characters shown]) at line 567 column 10. zone=100 _ERROR_=1 _N_=1

And of course I get the same error for each observation in my dataset. It makes sense why the ZONE value from the table would have a bunch of whitespace (the variable is $16 I think), but why is it adding all of that space to my variable name? What am I missing here?

3

3 Answers

1
votes

This happens due to the numeric / character conversion of the _n_ variable. When numeric values are converted to character, they are right aligned.

Try the following instead:

data _null_;
  set zonelist;
  call symputx(cats('zone',_n_), zone);
  call symputx('numzones', _n_);
run;

The cats function will perform the numeric / character conversion and also strip the leading blanks.

If you have SAS 9 then you can also use the symputX function to strip leading / trailing blanks from the macro VALUES as well.

0
votes

I solved it using "compress", to just delete all of the spaces:

data _null_;
  set zonelist;
  call symputx(compress('zone',_n_), zone);
  call symputx('numzones', _n_);
run;

However, this doesn't help me understand why I needed to do this at all. Any enlightenment would be appreciated!

0
votes

SAS has two types of variables, fixed length character strings and floating point numbers. Let's look at your first statement.

call symput ('zone'||_n_, zone);

In there you are referencing two variables and one string literal. Since the || operator works on character variables SAS will need to do an implicit conversion of the numeric variable _n_ to a character string. SAS will use the best12. format so it will result in a value like ' 1'. So you will end up with an invalid value for the call symput() function to use for the macro variable name.

But what about that third value, the variable zone? If zone is a number then the same implicit conversion will happen and the macro variable will end up containing leading spaces. Or the zone variable is a character string, in which case your macro variable will most likely end up having trailing spaces, unless the length of the value of zone happens to exactly match the maximum length that the variable zone is defined to hold.

As others have suggested there are two things to do to fix this.

First use the call symputx() instead of call symput() (unless you really want those trailing spaces stored in your macro variables) which will automatically strip() the input values. It will also silence the note about implicit numeric to character conversion.

The second is to use some method of generating the macro varaible name that does not insert spaces. The easiest way is to just use the cats() function instead of the || operator. But you could also use combinations of other functions like put(), compress(), strip(), etc.

call symputx(cats('zone',_n_),zone);