DATA Step, Macro, Functions and more

call symput, symget, resolve - which one to use?

Reply
Contributor
Posts: 26

call symput, symget, resolve - which one to use?

Hi,
I have a DataSet with column col_EXP, which contains date expression, e.g:

DATA test;
col_EXP="intnx('day',today(),2)";output;
col_EXP="intnx('day',today(),10)";output;
RUN;

Now, I would like to create a new column col_DT with computed date from expression in column col_EXP.

data test2;
set test;
col_DT = ????;
run;

I have tried with call symput, symget and resolve funcions but without any successSmiley Sad
Can anyone help me?
PROC Star
Posts: 7,474

Re: call symput, symget, resolve - which one to use?

Lucas,

There has GOT to be a less convoluted way than the one I'll propose but, if this is something that you HAVE to get done, the following might provide what you need:


DATA test;
length col_EXP $50;
col_EXP="intnx('day',today(),2)";output;
col_EXP="intnx('day',today(),10)";output;
RUN;

filename ft17f001 temp;
data _null_;
file ft17f001;
set test end=lastone;
if _n_ eq 1 then do;
put 'data test2;';
put +3 'format col_DT date9.;';
end;
put +3 'col_DT=' col_EXP ';';
put +3 'output;';
if lastone then put 'Run;';
run;
%inc ft17f001 / source2;

data test2;
set test;
set test2;
run;

HTH,
Art
Super Contributor
Super Contributor
Posts: 365

Re: call symput, symget, resolve - which one to use?

Hello Lucas,

I am not quite sure why you use this approach. Could you explain your goal in more detail? Anyway, this can be achieved with macro variables like this:
[pre]
DATA _null_t;
%let col_EXP1=intnx('day',today(),2);
%let col_EXP2=intnx('day',today(),10);
RUN;
data Result;
col_DT = &col_EXP1; ouput;
col_DT = &col_EXP2; ouput;
format col_DT date7.;
run;
[/pre]
I do not think it is what you need. This is why I' like to know more details.
Sincerely,
SPR
Regular Contributor
Posts: 171

Re: call symput, symget, resolve - which one to use?

Here is an alternative macro solution, although no less convoluted.

[pre]
DATA test;
length col_EXP $50;
col_EXP="intnx('day',today(),2)";output;
col_EXP="intnx('day',today(),10)";output;
RUN;

proc sql noprint;
select count(*) into: num_expressions
from test;

%let num_expressions = &num_expressions;

select col_EXP into :col_EXP1-:col_EXP&num_expressions
from test;
quit;

%macro test;
%do i = 1 %to &num_expressions;
col_EXP ="&&&col_exp&i";
col_DT = &&&col_exp&i;
output;
%end;
%mend;

data test1;
%test
run;
[/pre]
Contributor
Posts: 26

Re: call symput, symget, resolve - which one to use?

Hi,
thank you all for a quick response! Sorry for my english Smiley Wink


@art2897
Thanks! I wrote something similar to your program. Tommorow I will try to paste my code. It works fine but as you said it is quite complex. How works 'put +3' statement in your code? Smiley Happy

@SPR
The expression must be define in a permanent DataSet. Based on this expression a newcolumn col_DT is computed. I hope I explained problem more precisely.

@polingjw
yeahSmiley Happy your macro is convoluted. Great exercise to practise macro variables Smiley Happy

================================
Let's try to find a solution in one DataStep! Smiley Happy
I have tried something like this (in many many combinations :/):

DATA test;
col_EXP="intnx('day',today(),2)";output;
col_EXP="intnx('day',today(),10)";output;
RUN;

DATA test2;
set test;
call symput ('col_EXP_DT', col_EXP);
col_DT = symget('col_EXP_DT');
RUN;

But unfortunately symget does not resolved the expression Smiley Sad
SAS Super FREQ
Posts: 8,866

Re: call symput, symget, resolve - which one to use?

Hi:
About this code:
[pre]
DATA test2;
set test;
call symput ('col_EXP_DT', col_EXP);
col_DT = symget('col_EXP_DT');
RUN;
[/pre]

You cannot both create and use a macro variable within 1 DATA step program. That means if you create &col_EXP_DT in a DATA step program, that a step boundary must be encountered before you USE &col_EXT_DT in a program.

See this Tech Support note (and the Macro Facility documentation) for more details:
http://support.sas.com/kb/23/182.html

cynthia
Regular Contributor
Posts: 241

Re: call symput, symget, resolve - which one to use?

Posted in reply to Cynthia_sas
...
> You cannot both create and use a macro variable within
> 1 DATA step program. That means if you create
> &col_EXP_DT in a DATA step program, that a step
> boundary must be encountered before you USE
> &col_EXT_DT in a program.
>
> See this Tech Support note (and the Macro Facility
> documentation) for more details:
> http://support.sas.com/kb/23/182.html
...
I guess the note is not 100% clear if even a long time user ends up drawing a wrong conclusion like that. You definitely *can* both create and use a macro variable within a data step.
[pre]
%symdel mvar;
data _null_;
call symput('mvar', 'what');
something = resolve('&mvar');
put something=;
run;
/* on log
something=what
*/
[/pre] Message was edited by: chang_y_chung@hotmail.com
SAS Super FREQ
Posts: 8,866

Re: call symput, symget, resolve - which one to use?

Posted in reply to chang_y_chung_hotmail_com
The posted TS Note says that:

You cannot use a macro variable reference to retrieve the value of a macro variable


What they mean is a "simple" &macvar form of reference. There are other techniques, as you have shown. But the most common issue is trying to use a simple &macvar in the same step where it is created.

cynthia
Super User
Posts: 10,035

Re: call symput, symget, resolve - which one to use?

There is another problem.
You need assign long enough space for variable col_EXP.

[pre]
DATA test;
length col_EXP $ 100;
col_EXP="intnx('day',today(),2)";output;
col_EXP="intnx('day',today(),10)";output;
RUN;

DATA test2;
set test;
call symput (cats('col_EXP_DT',_n_), col_EXP);
col_DT = symget('col_EXP_DT');
RUN;
%put _user_;
[/pre]



Ksharp
SAS Super FREQ
Posts: 8,866

Re: call symput, symget, resolve - which one to use?

What about the invalid argument message with your code? cynthia
[pre]
492
493 DATA test2;
494 set test;
495 call symput (cats('col_EXP_DT',_n_), col_EXP);
496 col_DT = symget('col_EXP_DT');
497 RUN;

NOTE: Invalid argument to function SYMGET at line 496 column 10.
col_EXP=intnx('day',today(),2) col_DT= _ERROR_=1 _N_=1
NOTE: Invalid argument to function SYMGET at line 496 column 10.
col_EXP=intnx('day',today(),10) col_DT= _ERROR_=1 _N_=2
NOTE: There were 2 observations read from the data set
WORK.TEST.
NOTE: The data set WORK.TEST2 has 2 observations and 2
variables.
NOTE: DATA statement used (Total process time):
real time 0.14 seconds
cpu time 0.01 seconds
[/pre]
Super User
Posts: 10,035

Re: call symput, symget, resolve - which one to use?

Posted in reply to Cynthia_sas
Cynthia.
I have not received these NOTEs.
I am using SAS 9.2 TS1M0 for Windows.
The following is my LOG.

[pre]
132
133 DATA test2;
134 set test;
135 call symput (cats('col_EXP_DT',_n_), col_EXP);
136 col_DT = symget('col_EXP_DT');
137 RUN;

NOTE: There were 2 observations read from the data set WORK.TEST.
NOTE: The data set WORK.TEST2 has 2 observations and 2 variables.
NOTE: DATA statement used (Total process time):
real time 0.27 seconds
cpu time 0.01 seconds


138 %put _user_;
GLOBAL COL_EXP_DT intnx('day',today(),2)
GLOBAL COL_EXP_DT1 intnx('day',today(),2)
GLOBAL COL_EXP_DT2 intnx('day',today(),10)
[/pre]




Ksharp
SAS Super FREQ
Posts: 8,866

Re: call symput, symget, resolve - which one to use?

How did you get &COL_EXP_DT (without a number) in your global symbol table?? You appended _N_ to the macro variable name in the CALL SYMPUT statement in your program. That should have created ONLY &COL_EXP_DT1 and &COL_EXP_DT2.

If &COL_EXP_DT (without a number) does not exist, then you will get the invalid argument message. I suspect the reason you're not seeing the message is that in some previous test run you actually created &COL_EXP_DT.

But really, it's a moot point about the message, because I believe the original poster did NOT just want to see the text string with the INTNX function, I think he actually wanted to have the INTNX function execute. And, I agree with ArtC and other responders who have indicated that what is being shown 1) doesn't make sense and 2) probably doesn't require a macro variable.

I just don't think a lot of time needs to be spent coming up with more variations to do something that is not well-explained on data that is not fully understandable. If we understood a bit more about the real data and the real scenario and the actual task to be accomplished, someone might have a useful suggestion.

cynthia
Super User
Posts: 10,035

Re: call symput, symget, resolve - which one to use?

Posted in reply to Cynthia_sas
Cynthia.
&COL_EXP_DT (without a number) is actually from OP's code and I revise it,then got this curious result.
And I receive these notes as yours.
When I close SAS session and re-run the code,the following is LOG.

[pre]

6
7 DATA test2;
8 set test;
9 call symput (cats('col_EXP_DT',_n_), col_EXP);
10 col_DT = symget('col_EXP_DT');
11 RUN;

NOTE: Invalid argument to function SYMGET at line 10 column 10.
col_EXP=intnx('day',today(),2) col_DT= _ERROR_=1 _N_=1
NOTE: Invalid argument to function SYMGET at line 10 column 10.
col_EXP=intnx('day',today(),10) col_DT= _ERROR_=1 _N_=2
NOTE: There were 2 observations read from the data set WORK.TEST.
NOTE: The data set WORK.TEST2 has 2 observations and 2 variables.
NOTE: DATA statement used (Total process time):
real time 0.22 seconds
cpu time 0.05 seconds


12 %put _user_;
GLOBAL COL_EXP_DT1 intnx('day',today(),2)
GLOBAL COL_EXP_DT2 intnx('day',today(),10)

[/pre]

and maybe change it a little more.

[pre]
DATA test2;
set test;
call symput (cats('col_EXP_DT',_n_), col_EXP);
col_DT = symget(cats('col_EXP_DT',_n_));
RUN;
%put _user_;
[/pre]
then These notes will not appear again.

[pre]
18
19 DATA test2;
20 set test;
21 call symput (cats('col_EXP_DT',_n_), col_EXP);
22 col_DT = symget(cats('col_EXP_DT',_n_));
23 RUN;

NOTE: There were 2 observations read from the data set WORK.TEST.
NOTE: The data set WORK.TEST2 has 2 observations and 2 variables.
NOTE: DATA statement used (Total process time):
real time 0.05 seconds
cpu time 0.02 seconds


24 %put _user_;
GLOBAL COL_EXP_DT1 intnx('day',today(),2)
GLOBAL COL_EXP_DT2 intnx('day',today(),10)
[/pre]



Ksharp
Valued Guide
Posts: 634

Re: call symput, symget, resolve - which one to use?

Aside that this does not work the way you want, again we ask what are you trying to do?

If you want to create a new variable then no macro variables are needed.
[pre]
DATA test;
col_EXP="intnx('day',today(),2)";output;
col_EXP="intnx('day',today(),10)";output;
RUN;

DATA test2;
set test;
col_DT = col_exp;
RUN;
[/pre]
But even this does not make any sense.
Super User
Posts: 10,035

Re: call symput, symget, resolve - which one to use?

Macro statement can solve your problem.
And I think 'call symput, symget, resolve' would not solve your problem,because you request to dynamic invoke Macro variables ,it is hard to achieve.

[pre]

DATA test;
length col_EXP $ 100;
col_EXP="intnx('day',today(),2)";output;
col_EXP="intnx('day',today(),10)";output;
RUN;

DATA _null_;
set test nobs=num_obs;
call symput (cats('col_EXP_DT',_n_), col_EXP);
call symput ('nobs',num_obs);
RUN;
%put _user_;

%macro data;
data test2;
set test;
if _n_ eq 1 then col_DT=&col_EXP_DT1;
%do i=2 %to &nobs;
else if _n_ eq &i then col_DT=&&col_EXP_DT&i ;
%end;
format col_DT yymmdd10.;
run;
%mend;

%data

proc print;run;
[/pre]



Ksharp Message was edited by: Ksharp
Ask a Question
Discussion stats
  • 22 replies
  • 1391 views
  • 0 likes
  • 8 in conversation